Kaynağa Gözat

#62 SkipAndReturnBytes should support reader

Tao Wen 8 yıl önce
ebeveyn
işleme
54dbcda64d
3 değiştirilmiş dosya ile 56 ekleme ve 6 silme
  1. 7 0
      feature_iter.go
  2. 31 6
      feature_iter_skip.go
  3. 18 0
      jsoniter_skip_test.go

+ 7 - 0
feature_iter.go

@@ -70,6 +70,8 @@ type Iterator struct {
 	buf    []byte
 	head   int
 	tail   int
+	captureStartedAt int
+	captured	[]byte
 	Error  error
 }
 
@@ -212,6 +214,11 @@ func (iter *Iterator) loadMore() bool {
 		}
 		return false
 	}
+	if iter.captureStartedAt != -1 {
+		iter.captured = append(iter.captured,
+			iter.buf[iter.captureStartedAt:iter.tail]...)
+		iter.captureStartedAt = 0
+	}
 	for {
 		n, err := iter.reader.Read(iter.buf)
 		if n == 0 {

+ 31 - 6
feature_iter_skip.go

@@ -30,13 +30,38 @@ func (iter *Iterator) ReadBool() (ret bool) {
 }
 
 func (iter *Iterator) SkipAndReturnBytes() []byte {
-	if iter.reader != nil {
-		panic("reader input does not support this api")
-	}
-	before := iter.head
+	iter.startCapture()
 	iter.Skip()
-	after := iter.head
-	return iter.buf[before:after]
+	return iter.stopCapture()
+}
+
+type captureBuffer struct {
+	startedAt int
+	captured  []byte
+}
+
+func (iter *Iterator) startCapture() {
+	if iter.captured != nil {
+		panic("already in capture mode")
+	}
+	iter.captureStartedAt = iter.head
+	iter.captured = make([]byte, 0, 32)
+}
+
+func (iter *Iterator) stopCapture() []byte {
+	if iter.captured == nil {
+		panic("not in capture mode")
+	}
+	captured := iter.captured
+	remaining := iter.buf[iter.captureStartedAt: iter.head]
+	iter.captureStartedAt = -1
+	iter.captured = nil
+	if len(captured) == 0 {
+		return remaining
+	} else {
+		captured = append(captured, remaining...)
+		return captured
+	}
 }
 
 // Skip skips a json object and positions to relatively the next json object

+ 18 - 0
jsoniter_skip_test.go

@@ -3,6 +3,8 @@ package jsoniter
 import (
 	"encoding/json"
 	"testing"
+	"github.com/json-iterator/go/require"
+	"bytes"
 )
 
 func Test_skip_number(t *testing.T) {
@@ -75,6 +77,22 @@ func Test_skip_nested(t *testing.T) {
 	}
 }
 
+func Test_skip_and_return_bytes(t *testing.T) {
+	should := require.New(t)
+	iter := ParseString(ConfigDefault, `[ {"a" : [{"b": "c"}], "d": 102 }, "b"]`)
+	iter.ReadArray()
+	skipped := iter.SkipAndReturnBytes()
+	should.Equal(`{"a" : [{"b": "c"}], "d": 102 }`, string(skipped))
+}
+
+func Test_skip_and_return_bytes_with_reader(t *testing.T) {
+	should := require.New(t)
+	iter := Parse(ConfigDefault, bytes.NewBufferString(`[ {"a" : [{"b": "c"}], "d": 102 }, "b"]`), 4)
+	iter.ReadArray()
+	skipped := iter.SkipAndReturnBytes()
+	should.Equal(`{"a" : [{"b": "c"}], "d": 102 }`, string(skipped))
+}
+
 type TestResp struct {
 	Code uint64
 }