1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +02:00

array lazy iterator

This commit is contained in:
Tao Wen 2017-01-24 22:47:56 +08:00
parent 8656482625
commit fa165c684f
4 changed files with 75 additions and 0 deletions

View File

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

View File

@ -125,3 +125,59 @@ func (any *arrayLazyAny) Size() int {
any.fillCache() any.fillCache()
return len(any.cache) 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
}

View File

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

View File

@ -67,6 +67,19 @@ func Test_read_two_element_array_as_any(t *testing.T) {
should.Equal(2, any.Size()) 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) { func Test_invalid_array(t *testing.T) {
_, err := UnmarshalAnyFromString("[") _, err := UnmarshalAnyFromString("[")
if err == nil || err == io.EOF { if err == nil || err == io.EOF {