Selaa lähdekoodia

array lazy iterator

Tao Wen 8 vuotta sitten
vanhempi
commit
fa165c684f
4 muutettua tiedostoa jossa 75 lisäystä ja 0 poistoa
  1. 5 0
      feature_any.go
  2. 56 0
      feature_any_array.go
  3. 1 0
      feature_any_object.go
  4. 13 0
      jsoniter_array_test.go

+ 5 - 0
feature_any.go

@@ -13,6 +13,7 @@ type Any interface {
 	Size() int
 	Keys() []string
 	IterateObject() (func() (string, Any, bool), bool)
+	IterateArray() (func() (Any, bool), bool)
 }
 
 type baseAny struct {}
@@ -29,6 +30,10 @@ func (any *baseAny) IterateObject() (func() (string, Any, bool), bool) {
 	return nil, false
 }
 
+func (any *baseAny) IterateArray() (func() (Any, bool), bool) {
+	return nil, false
+}
+
 func (iter *Iterator) ReadAny() Any {
 	return iter.readAny(nil)
 }

+ 56 - 0
feature_any_array.go

@@ -125,3 +125,59 @@ func (any *arrayLazyAny) Size() int {
 	any.fillCache()
 	return len(any.cache)
 }
+
+
+func (any *arrayLazyAny) IterateArray() (func() (Any, bool), bool) {
+	remaining := any.remaining
+	if len(remaining) == len(any.buf) {
+		iter := any.parse()
+		iter.head++
+		c := iter.nextToken()
+		if c != ']' {
+			iter.unreadByte()
+			v := iter.readAny(iter)
+			any.cache = append(any.cache, v)
+			remaining = iter.buf[iter.head:]
+			any.remaining = remaining
+		} else {
+			remaining = nil
+			any.remaining = nil
+			return nil, false
+		}
+	}
+	if len(any.cache) == 0 {
+		return nil, false
+	}
+	arr := any.cache
+	nextValue := arr[0]
+	i := 1
+	return func() (Any, bool) {
+		value := nextValue
+		if i < len(arr) {
+			// read from cache
+			nextValue = arr[i]
+			i++
+			return value, true
+		} else {
+			// read from buffer
+			iter := any.iter
+			if iter == nil {
+				iter = NewIterator()
+				any.iter = iter
+			}
+			iter.ResetBytes(remaining)
+			c := iter.nextToken()
+			if c == ',' {
+				nextValue = iter.readAny(iter)
+				any.cache = append(any.cache, nextValue)
+				remaining = iter.buf[iter.head:]
+				any.remaining = remaining
+				return value, true
+			} else {
+				remaining = nil
+				any.remaining = nil
+				return value, false
+			}
+		}
+	}, true
+}

+ 1 - 0
feature_any_object.go

@@ -146,6 +146,7 @@ func (any *objectLazyAny) Keys() []string {
 	}
 	return keys
 }
+
 func (any *objectLazyAny) IterateObject() (func() (string, Any, bool), bool) {
 	if any.cache == nil {
 		any.cache = map[string]Any{}

+ 13 - 0
jsoniter_array_test.go

@@ -67,6 +67,19 @@ func Test_read_two_element_array_as_any(t *testing.T) {
 	should.Equal(2, any.Size())
 }
 
+func Test_read_array_with_any_iterator(t *testing.T) {
+	should := require.New(t)
+	any, err := UnmarshalAnyFromString("[1,2]")
+	should.Nil(err)
+	var element Any
+	var elements []int
+	for next, hasNext := any.IterateArray(); hasNext; {
+		element, hasNext = next()
+		elements = append(elements, element.ToInt())
+	}
+	should.Equal([]int{1, 2}, elements)
+}
+
 func Test_invalid_array(t *testing.T) {
 	_, err := UnmarshalAnyFromString("[")
 	if err == nil || err == io.EOF {