Quellcode durchsuchen

#61 removed internal buffer from lazy array and object; jsoniter.Get replaced jsoniter.UnmarshalAny

Tao Wen vor 8 Jahren
Ursprung
Commit
985e263300

+ 3 - 7
feature_adapter.go

@@ -24,11 +24,6 @@ func Unmarshal(data []byte, v interface{}) error {
 	return ConfigDefault.Unmarshal(data, v)
 }
 
-// UnmarshalAny adapts to
-func UnmarshalAny(data []byte) (Any, error) {
-	return ConfigDefault.UnmarshalAny(data)
-}
-
 func lastNotSpacePos(data []byte) int {
 	for i := len(data) - 1; i >= 0; i-- {
 		if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
@@ -42,10 +37,11 @@ func UnmarshalFromString(str string, v interface{}) error {
 	return ConfigDefault.UnmarshalFromString(str, v)
 }
 
-func UnmarshalAnyFromString(str string) (Any, error) {
-	return ConfigDefault.UnmarshalAnyFromString(str)
+func Get(data []byte, path ...interface{}) Any {
+	return ConfigDefault.Get(data, path...)
 }
 
+
 // Marshal adapts to json/encoding Marshal API
 //
 // Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API

+ 52 - 23
feature_any.go

@@ -3,6 +3,7 @@ package jsoniter
 import (
 	"fmt"
 	"reflect"
+	"io"
 )
 
 type Any interface {
@@ -21,12 +22,8 @@ type Any interface {
 	Get(path ...interface{}) Any
 	Size() int
 	Keys() []string
-	IterateObject() (func() (string, Any, bool), bool)
-	IterateArray() (func() (Any, bool), bool)
 	GetArray() []Any
-	SetArray(newList []Any) bool
 	GetObject() map[string]Any
-	SetObject(map[string]Any) bool
 	GetInterface() interface{}
 	WriteTo(stream *Stream)
 }
@@ -45,30 +42,14 @@ func (any *baseAny) Keys() []string {
 	return []string{}
 }
 
-func (any *baseAny) IterateObject() (func() (string, Any, bool), bool) {
-	return nil, false
-}
-
-func (any *baseAny) IterateArray() (func() (Any, bool), bool) {
-	return nil, false
-}
-
 func (any *baseAny) GetArray() []Any {
 	return []Any{}
 }
 
-func (any *baseAny) SetArray(newList []Any) bool {
-	return false
-}
-
 func (any *baseAny) GetObject() map[string]Any {
 	return map[string]Any{}
 }
 
-func (any *baseAny) SetObject(map[string]Any) bool {
-	return false
-}
-
 func WrapInt32(val int32) Any {
 	return &int32Any{baseAny{}, val}
 }
@@ -153,7 +134,8 @@ func (iter *Iterator) readAny() Any {
 	c := iter.nextToken()
 	switch c {
 	case '"':
-		return iter.readStringAny()
+		iter.unreadByte()
+		return &stringAny{baseAny{}, nil, iter.ReadString()}
 	case 'n':
 		iter.skipFixedBytes(3) // null
 		return &nilAny{}
@@ -200,12 +182,59 @@ func (iter *Iterator) readObjectAny() Any {
 	iter.startCapture(iter.head - 1)
 	iter.skipObject()
 	lazyBuf := iter.stopCapture()
-	return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
+	return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
 }
 
 func (iter *Iterator) readArrayAny() Any {
 	iter.startCapture(iter.head - 1)
 	iter.skipArray()
 	lazyBuf := iter.stopCapture()
-	return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
+	return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
 }
+
+func locateObjectField(iter *Iterator, target string) []byte {
+	var found []byte
+	iter.ReadObjectCB(func(iter *Iterator, field string) bool {
+		if field == target {
+			found = iter.SkipAndReturnBytes()
+			return false
+		}
+		iter.Skip()
+		return true
+	})
+	return found
+}
+
+func locateArrayElement(iter *Iterator, target int) []byte {
+	var found []byte
+	n := 0
+	iter.ReadArrayCB(func(iter *Iterator) bool {
+		if n == target {
+			found = iter.SkipAndReturnBytes()
+			return false
+		}
+		iter.Skip()
+		n++
+		return true
+	})
+	return found
+}
+
+func locatePath(iter *Iterator, path []interface{}) Any {
+	for i, pathKeyObj := range path {
+		switch pathKey := pathKeyObj.(type) {
+		case string:
+			valueBytes := locateObjectField(iter, pathKey)
+			iter.ResetBytes(valueBytes)
+		case int:
+			valueBytes := locateArrayElement(iter, pathKey)
+			iter.ResetBytes(valueBytes)
+		default:
+			return newInvalidAny(path[i:])
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		return &invalidAny{baseAny{}, iter.Error}
+	}
+	return iter.readAny()
+}

+ 66 - 232
feature_any_array.go

@@ -11,317 +11,157 @@ type arrayLazyAny struct {
 	cfg       *frozenConfig
 	buf       []byte
 	err       error
-	cache     []Any
-	remaining []byte
 }
 
 func (any *arrayLazyAny) ValueType() ValueType {
 	return Array
 }
 
-func (any *arrayLazyAny) fillCacheUntil(target int) Any {
-	if any.remaining == nil {
-		if target >= len(any.cache) {
-			return nil
-		}
-		return any.cache[target]
-	}
-	if any.cache == nil {
-		any.cache = make([]Any, 0, 8)
-	}
-	i := len(any.cache)
-	if target < i {
-		return any.cache[target]
-	}
-	iter := any.cfg.BorrowIterator(any.remaining)
-	defer any.cfg.ReturnIterator(iter)
-	if len(any.remaining) == len(any.buf) {
-		iter.head++
-		c := iter.nextToken()
-		if c != ']' {
-			iter.unreadByte()
-			element := iter.readAny()
-			any.cache = append(any.cache, element)
-			if target == 0 {
-				any.remaining = iter.buf[iter.head:]
-				any.err = iter.Error
-				return element
-			}
-			i = 1
-		} else {
-			any.remaining = nil
-			any.err = iter.Error
-			return nil
-		}
-	}
-	for iter.nextToken() == ',' {
-		element := iter.readAny()
-		any.cache = append(any.cache, element)
-		if i == target {
-			any.remaining = iter.buf[iter.head:]
-			any.err = iter.Error
-			return element
-		}
-		i++
-	}
-	any.remaining = nil
-	any.err = iter.Error
-	return nil
-}
-
-func (any *arrayLazyAny) fillCache() {
-	if any.remaining == nil {
-		return
-	}
-	if any.cache == nil {
-		any.cache = make([]Any, 0, 8)
-	}
-	iter := any.cfg.BorrowIterator(any.remaining)
-	defer any.cfg.ReturnIterator(iter)
-	if len(any.remaining) == len(any.buf) {
-		iter.head++
-		c := iter.nextToken()
-		if c != ']' {
-			iter.unreadByte()
-			any.cache = append(any.cache, iter.readAny())
-		} else {
-			any.remaining = nil
-			any.err = iter.Error
-			return
-		}
-	}
-	for iter.nextToken() == ',' {
-		any.cache = append(any.cache, iter.readAny())
-	}
-	any.remaining = nil
-	any.err = iter.Error
-}
-
 func (any *arrayLazyAny) LastError() error {
 	return any.err
 }
 
 func (any *arrayLazyAny) ToBool() bool {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	return len(any.cache) != 0
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	return iter.ReadArray()
 }
 
 func (any *arrayLazyAny) ToInt() int {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToInt32() int32 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToInt64() int64 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToUint() uint {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToUint32() uint32 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToUint64() uint64 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToFloat32() float32 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToFloat64() float64 {
-	if any.cache == nil {
-		any.IterateArray() // trigger first element read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *arrayLazyAny) ToString() string {
-	if len(any.remaining) == len(any.buf) {
-		// nothing has been parsed yet
-		return *(*string)(unsafe.Pointer(&any.buf))
-	} else {
-		any.fillCache()
-		str, err := any.cfg.MarshalToString(any.cache)
-		any.err = err
-		return str
-	}
+	return *(*string)(unsafe.Pointer(&any.buf))
 }
 
 func (any *arrayLazyAny) Get(path ...interface{}) Any {
 	if len(path) == 0 {
 		return any
 	}
-	var element Any
 	switch firstPath := path[0].(type) {
 	case int:
-		element = any.fillCacheUntil(firstPath)
-		if element == nil {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
+		iter := any.cfg.BorrowIterator(any.buf)
+		defer any.cfg.ReturnIterator(iter)
+		valueBytes := locateArrayElement(iter, firstPath)
+		if valueBytes == nil {
+			return newInvalidAny(path)
+		} else {
+			iter.ResetBytes(valueBytes)
+			return locatePath(iter, path[1:])
 		}
 	case int32:
 		if '*' == firstPath {
-			any.fillCache()
-			arr := make([]Any, 0, len(any.cache))
-			for _, element := range any.cache {
-				found := element.Get(path[1:]...)
+			iter := any.cfg.BorrowIterator(any.buf)
+			defer any.cfg.ReturnIterator(iter)
+			arr := make([]Any, 0)
+			iter.ReadArrayCB(func(iter *Iterator) bool {
+				found := iter.readAny().Get(path[1:]...)
 				if found.ValueType() != Invalid {
 					arr = append(arr, found)
 				}
-			}
+				return true
+			})
 			return wrapArray(arr)
 		} else {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
+			return newInvalidAny(path)
 		}
 	default:
-		element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
-	}
-	if len(path) == 1 {
-		return element
-	} else {
-		return element.Get(path[1:]...)
+		return newInvalidAny(path)
 	}
 }
 
 func (any *arrayLazyAny) Size() int {
-	any.fillCache()
-	return len(any.cache)
-}
-
-func (any *arrayLazyAny) IterateArray() (func() (Any, bool), bool) {
-	if any.cache == nil {
-		any.cache = make([]Any, 0, 8)
-	}
-	remaining := any.remaining
-	if len(remaining) == len(any.buf) {
-		iter := any.cfg.BorrowIterator(any.remaining)
-		defer any.cfg.ReturnIterator(iter)
-		iter.head++
-		c := iter.nextToken()
-		if c != ']' {
-			iter.unreadByte()
-			v := iter.readAny()
-			any.cache = append(any.cache, v)
-			remaining = iter.buf[iter.head:]
-			any.remaining = remaining
-		} else {
-			remaining = nil
-			any.remaining = nil
-			any.err = iter.Error
-			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.cfg.BorrowIterator(any.remaining)
-			defer any.cfg.ReturnIterator(iter)
-			c := iter.nextToken()
-			if c == ',' {
-				nextValue = iter.readAny()
-				any.cache = append(any.cache, nextValue)
-				remaining = iter.buf[iter.head:]
-				any.remaining = remaining
-				any.err = iter.Error
-				return value, true
-			} else {
-				remaining = nil
-				any.remaining = nil
-				any.err = iter.Error
-				return value, false
-			}
-		}
-	}, true
+	size := 0
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	iter.ReadArrayCB(func(iter *Iterator) bool {
+		size++
+		iter.Skip()
+		return true
+	})
+	return size
 }
 
 func (any *arrayLazyAny) GetArray() []Any {
-	any.fillCache()
-	return any.cache
-}
-
-func (any *arrayLazyAny) SetArray(newList []Any) bool {
-	any.fillCache()
-	any.cache = newList
-	return true
+	elements := make([]Any, 0)
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	iter.ReadArrayCB(func(iter *Iterator) bool {
+		elements = append(elements, iter.ReadAny())
+		return true
+	})
+	return elements
 }
 
 func (any *arrayLazyAny) WriteTo(stream *Stream) {
-	if len(any.remaining) == len(any.buf) {
-		// nothing has been parsed yet
-		stream.Write(any.buf)
-	} else {
-		any.fillCache()
-		stream.WriteVal(any.cache)
-	}
+	stream.Write(any.buf)
 }
 
 func (any *arrayLazyAny) GetInterface() interface{} {
-	any.fillCache()
-	return any.cache
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	return iter.Read()
 }
 
 type arrayAny struct {
@@ -506,12 +346,6 @@ func (any *arrayAny) GetArray() []Any {
 	return any.cache
 }
 
-func (any *arrayAny) SetArray(newList []Any) bool {
-	any.fillCache()
-	any.cache = newList
-	return true
-}
-
 func (any *arrayAny) WriteTo(stream *Stream) {
 	if len(any.cache) == 0 {
 		// nothing has been parsed yet

+ 4 - 0
feature_any_invalid.go

@@ -7,6 +7,10 @@ type invalidAny struct {
 	err error
 }
 
+func newInvalidAny(path []interface{}) *invalidAny {
+	return &invalidAny{baseAny{}, fmt.Errorf("%v not found", path)}
+}
+
 func (any *invalidAny) LastError() error {
 	return any.err
 }

+ 77 - 325
feature_any_object.go

@@ -8,343 +8,172 @@ import (
 
 type objectLazyAny struct {
 	baseAny
-	cfg       *frozenConfig
-	buf       []byte
-	err       error
-	cache     map[string]Any
-	remaining []byte
+	cfg *frozenConfig
+	buf []byte
+	err error
 }
 
 func (any *objectLazyAny) ValueType() ValueType {
 	return Object
 }
 
-func (any *objectLazyAny) fillCacheUntil(target string) Any {
-	if any.remaining == nil {
-		return any.cache[target]
-	}
-	if any.cache == nil {
-		any.cache = map[string]Any{}
-	}
-	val := any.cache[target]
-	if val != nil {
-		return val
-	}
-	iter := any.cfg.BorrowIterator(any.remaining)
-	defer any.cfg.ReturnIterator(iter)
-	if len(any.remaining) == len(any.buf) {
-		iter.head++
-		c := iter.nextToken()
-		if c != '}' {
-			iter.unreadByte()
-			k := string(iter.readObjectFieldAsBytes())
-			v := iter.readAny()
-			any.cache[k] = v
-			if target == k {
-				any.remaining = iter.buf[iter.head:]
-				any.err = iter.Error
-				return v
-			}
-		} else {
-			any.remaining = nil
-			any.err = iter.Error
-			return nil
-		}
-	}
-	for iter.nextToken() == ',' {
-		k := string(iter.readObjectFieldAsBytes())
-		v := iter.readAny()
-		any.cache[k] = v
-		if target == k {
-			any.remaining = iter.buf[iter.head:]
-			any.err = iter.Error
-			return v
-		}
-	}
-	any.remaining = nil
-	any.err = iter.Error
-	return nil
-}
-
-func (any *objectLazyAny) fillCache() {
-	if any.remaining == nil {
-		return
-	}
-	if any.cache == nil {
-		any.cache = map[string]Any{}
-	}
-	iter := any.cfg.BorrowIterator(any.remaining)
-	defer any.cfg.ReturnIterator(iter)
-	if len(any.remaining) == len(any.buf) {
-		iter.head++
-		c := iter.nextToken()
-		if c != '}' {
-			iter.unreadByte()
-			k := string(iter.readObjectFieldAsBytes())
-			v := iter.readAny()
-			any.cache[k] = v
-		} else {
-			any.remaining = nil
-			any.err = iter.Error
-			return
-		}
-	}
-	for iter.nextToken() == ',' {
-		k := string(iter.readObjectFieldAsBytes())
-		v := iter.readAny()
-		any.cache[k] = v
-	}
-	any.remaining = nil
-	any.err = iter.Error
-	return
-}
-
 func (any *objectLazyAny) LastError() error {
 	return any.err
 }
 
 func (any *objectLazyAny) ToBool() bool {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	return len(any.cache) != 0
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	return iter.ReadObject() != ""
 }
 
 func (any *objectLazyAny) ToInt() int {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToInt32() int32 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToInt64() int64 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToUint() uint {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToUint32() uint32 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToUint64() uint64 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToFloat32() float32 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToFloat64() float64 {
-	if any.cache == nil {
-		any.IterateObject() // trigger first value read
-	}
-	if len(any.cache) == 0 {
+	if any.ToBool() {
+		return 1
+	} else {
 		return 0
 	}
-	return 1
 }
 
 func (any *objectLazyAny) ToString() string {
-	if len(any.remaining) == len(any.buf) {
-		// nothing has been parsed yet
-		return *(*string)(unsafe.Pointer(&any.buf))
-	} else {
-		any.fillCache()
-		str, err := any.cfg.MarshalToString(any.cache)
-		any.err = err
-		return str
-	}
+	return *(*string)(unsafe.Pointer(&any.buf))
 }
 
 func (any *objectLazyAny) Get(path ...interface{}) Any {
 	if len(path) == 0 {
 		return any
 	}
-	var element Any
-
 	switch firstPath := path[0].(type) {
 	case string:
-		element = any.fillCacheUntil(firstPath)
-		if element == nil {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
+		iter := any.cfg.BorrowIterator(any.buf)
+		defer any.cfg.ReturnIterator(iter)
+		valueBytes := locateObjectField(iter, firstPath)
+		if valueBytes == nil {
+			return newInvalidAny(path)
+		} else {
+			iter.ResetBytes(valueBytes)
+			return locatePath(iter, path[1:])
 		}
 	case int32:
 		if '*' == firstPath {
-			any.fillCache()
 			mappedAll := map[string]Any{}
-			for key, value := range any.cache {
-				mapped := value.Get(path[1:]...)
+			iter := any.cfg.BorrowIterator(any.buf)
+			defer any.cfg.ReturnIterator(iter)
+			iter.ReadObjectCB(func(iter *Iterator, field string) bool {
+				mapped := locatePath(iter, path[1:])
 				if mapped.ValueType() != Invalid {
-					mappedAll[key] = mapped
+					mappedAll[field] = mapped
 				}
-			}
+				return true
+			})
 			return wrapMap(mappedAll)
 		} else {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
+			return newInvalidAny(path)
 		}
 	default:
-		element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
-	}
-	if len(path) == 1 {
-		return element
-	} else {
-		return element.Get(path[1:]...)
+		return newInvalidAny(path)
 	}
 }
 
 func (any *objectLazyAny) Keys() []string {
-	any.fillCache()
-	keys := make([]string, 0, len(any.cache))
-	for key := range any.cache {
-		keys = append(keys, key)
-	}
+	keys := []string{}
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	iter.ReadObjectCB(func(iter *Iterator, field string) bool {
+		iter.Skip()
+		keys = append(keys, field)
+		return true
+	})
 	return keys
 }
 
 func (any *objectLazyAny) Size() int {
-	any.fillCache()
-	return len(any.cache)
-}
-
-func (any *objectLazyAny) IterateObject() (func() (string, Any, bool), bool) {
-	if any.cache == nil {
-		any.cache = map[string]Any{}
-	}
-	remaining := any.remaining
-	if len(remaining) == len(any.buf) {
-		iter := any.cfg.BorrowIterator(any.remaining)
-		defer any.cfg.ReturnIterator(iter)
-		iter.head++
-		c := iter.nextToken()
-		if c != '}' {
-			iter.unreadByte()
-			k := string(iter.readObjectFieldAsBytes())
-			v := iter.readAny()
-			any.cache[k] = v
-			remaining = iter.buf[iter.head:]
-			any.remaining = remaining
-		} else {
-			remaining = nil
-			any.remaining = nil
-			any.err = iter.Error
-			return nil, false
-		}
-	}
-	if len(any.cache) == 0 {
-		return nil, false
-	}
-	keys := make([]string, 0, len(any.cache))
-	values := make([]Any, 0, len(any.cache))
-	for key, value := range any.cache {
-		keys = append(keys, key)
-		values = append(values, value)
-	}
-	nextKey := keys[0]
-	nextValue := values[0]
-	i := 1
-	return func() (string, Any, bool) {
-		key := nextKey
-		value := nextValue
-		if i < len(keys) {
-			// read from cache
-			nextKey = keys[i]
-			nextValue = values[i]
-			i++
-			return key, value, true
-		} else {
-			// read from buffer
-			iter := any.cfg.BorrowIterator(any.remaining)
-			defer any.cfg.ReturnIterator(iter)
-			c := iter.nextToken()
-			if c == ',' {
-				nextKey = string(iter.readObjectFieldAsBytes())
-				nextValue = iter.readAny()
-				any.cache[nextKey] = nextValue
-				remaining = iter.buf[iter.head:]
-				any.remaining = remaining
-				any.err = iter.Error
-				return key, value, true
-			} else {
-				nextKey = ""
-				remaining = nil
-				any.remaining = nil
-				any.err = iter.Error
-				return key, value, false
-			}
-		}
-	}, true
+	size := 0
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	iter.ReadObjectCB(func(iter *Iterator, field string) bool {
+		iter.Skip()
+		size ++
+		return true
+	})
+	return size
 }
 
 func (any *objectLazyAny) GetObject() map[string]Any {
-	any.fillCache()
-	return any.cache
-}
-
-func (any *objectLazyAny) SetObject(val map[string]Any) bool {
-	any.fillCache()
-	any.cache = val
-	return true
+	asMap := map[string]Any{}
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	iter.ReadObjectCB(func(iter *Iterator, field string) bool {
+		asMap[field] = iter.ReadAny()
+		return true
+	})
+	return asMap
 }
 
 func (any *objectLazyAny) WriteTo(stream *Stream) {
-	if len(any.remaining) == len(any.buf) {
-		// nothing has been parsed yet
-		stream.Write(any.buf)
-	} else {
-		any.fillCache()
-		stream.WriteVal(any.cache)
-	}
+	stream.Write(any.buf)
 }
 
 func (any *objectLazyAny) GetInterface() interface{} {
-	any.fillCache()
-	return any.cache
+	iter := any.cfg.BorrowIterator(any.buf)
+	defer any.cfg.ReturnIterator(iter)
+	return iter.Read()
 }
 
 type objectAny struct {
@@ -537,57 +366,11 @@ func (any *objectAny) Size() int {
 	return len(any.cache)
 }
 
-func (any *objectAny) IterateObject() (func() (string, Any, bool), bool) {
-	if any.cache == nil {
-		any.cache = map[string]Any{}
-	}
-	if any.val.NumField() == 0 {
-		return nil, false
-	}
-	cacheKeys := make([]string, len(any.cache))
-	i := 0
-	for key := range any.cache {
-		cacheKeys[i] = key
-		i++
-	}
-	i = 0
-	return func() (string, Any, bool) {
-		if i == any.val.NumField() {
-			return "", nil, false
-		}
-		var fieldName string
-		var fieldValueAsAny Any
-		if i == len(cacheKeys) {
-			fieldName = any.val.Type().Field(i).Name
-			cacheKeys = append(cacheKeys, fieldName)
-			fieldValue := any.val.Field(i)
-			if fieldValue.CanInterface() {
-				fieldValueAsAny = Wrap(fieldValue.Interface())
-				any.cache[fieldName] = fieldValueAsAny
-			} else {
-				fieldValueAsAny = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
-				any.cache[fieldName] = fieldValueAsAny
-			}
-		} else {
-			fieldName = cacheKeys[i]
-			fieldValueAsAny = any.cache[fieldName]
-		}
-		i++
-		return fieldName, fieldValueAsAny, i != any.val.NumField()
-	}, true
-}
-
 func (any *objectAny) GetObject() map[string]Any {
 	any.fillCache()
 	return any.cache
 }
 
-func (any *objectAny) SetObject(val map[string]Any) bool {
-	any.fillCache()
-	any.cache = val
-	return true
-}
-
 func (any *objectAny) WriteTo(stream *Stream) {
 	if len(any.cache) == 0 {
 		// nothing has been parsed yet
@@ -785,42 +568,11 @@ func (any *mapAny) Size() int {
 	return len(any.cache)
 }
 
-func (any *mapAny) IterateObject() (func() (string, Any, bool), bool) {
-	any.fillCache()
-	if len(any.cache) == 0 {
-		return nil, false
-	}
-	keys := make([]string, len(any.cache))
-	values := make([]Any, len(any.cache))
-	i := 0
-	for k, v := range any.cache {
-		keys[i] = k
-		values[i] = v
-		i++
-	}
-	i = 0
-	return func() (string, Any, bool) {
-		if i == len(keys) {
-			return "", nil, false
-		}
-		k := keys[i]
-		v := values[i]
-		i++
-		return k, v, i != len(keys)
-	}, true
-}
-
 func (any *mapAny) GetObject() map[string]Any {
 	any.fillCache()
 	return any.cache
 }
 
-func (any *mapAny) SetObject(val map[string]Any) bool {
-	any.fillCache()
-	any.cache = val
-	return true
-}
-
 func (any *mapAny) WriteTo(stream *Stream) {
 	if len(any.cache) == 0 {
 		// nothing has been parsed yet

+ 3 - 2
feature_any_string.go

@@ -122,8 +122,9 @@ func (any *stringLazyAny) ToFloat64() float64 {
 }
 
 func (any *stringLazyAny) ToString() string {
-	any.fillCache()
-	return any.cache
+	var val string
+	any.err = any.cfg.Unmarshal(any.buf, &val)
+	return val
 }
 
 func (any *stringLazyAny) WriteTo(stream *Stream) {

+ 2 - 31
feature_config.go

@@ -206,39 +206,10 @@ func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
 	return iter.Error
 }
 
-func (cfg *frozenConfig) UnmarshalAnyFromString(str string) (Any, error) {
-	data := []byte(str)
-	data = data[:lastNotSpacePos(data)]
+func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
 	iter := cfg.BorrowIterator(data)
 	defer cfg.ReturnIterator(iter)
-	any := iter.ReadAny()
-	if iter.head == iter.tail {
-		iter.loadMore()
-	}
-	if iter.Error == io.EOF {
-		return any, nil
-	}
-	if iter.Error == nil {
-		iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
-	}
-	return nil, iter.Error
-}
-
-func (cfg *frozenConfig) UnmarshalAny(data []byte) (Any, error) {
-	data = data[:lastNotSpacePos(data)]
-	iter := cfg.BorrowIterator(data)
-	defer cfg.ReturnIterator(iter)
-	any := iter.ReadAny()
-	if iter.head == iter.tail {
-		iter.loadMore()
-	}
-	if iter.Error == io.EOF {
-		return any, nil
-	}
-	if iter.Error == nil {
-		iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
-	}
-	return any, iter.Error
+	return locatePath(iter, path)
 }
 
 func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {

+ 0 - 1
feature_iter.go

@@ -124,7 +124,6 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator {
 // ResetBytes can reset an Iterator instance for another json byte slice
 func (iter *Iterator) ResetBytes(input []byte) *Iterator {
 	iter.reader = nil
-	iter.Error = nil
 	iter.buf = input
 	iter.head = 0
 	iter.tail = len(input)

+ 2 - 0
feature_pool.go

@@ -15,6 +15,7 @@ func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
 }
 
 func (cfg *frozenConfig) ReturnStream(stream *Stream) {
+	stream.Error = nil
 	select {
 	case cfg.streamPool <- stream:
 		return
@@ -34,6 +35,7 @@ func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator {
 }
 
 func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
+	iter.Error = nil
 	select {
 	case cfg.iteratorPool <- iter:
 		return

+ 26 - 51
jsoniter_any_array_test.go

@@ -3,75 +3,62 @@ package jsoniter
 import (
 	"testing"
 	"github.com/json-iterator/go/require"
-	"io"
 )
 
 func Test_read_empty_array_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[]")
-	should.Nil(err)
+	any := Get([]byte("[]"))
+	should.Equal(Array, any.Get().ValueType())
+	should.Equal(Invalid, any.Get(0.3).ValueType())
 	should.Equal(0, any.Size())
+	should.Equal(Array, any.ValueType())
+	should.Nil(any.LastError())
+	should.Equal(0, any.ToInt())
+	should.Equal(int32(0), any.ToInt32())
+	should.Equal(int64(0), any.ToInt64())
+	should.Equal(uint(0), any.ToUint())
+	should.Equal(uint32(0), any.ToUint32())
+	should.Equal(uint64(0), any.ToUint64())
+	should.Equal(float32(0), any.ToFloat32())
+	should.Equal(float64(0), any.ToFloat64())
 }
 
 func Test_read_one_element_array_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[1]")
-	should.Nil(err)
+	any := Get([]byte("[1]"))
 	should.Equal(1, any.Size())
 }
 
 func Test_read_two_element_array_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[1,2]")
-	should.Nil(err)
+	any := Get([]byte("[1,2]"))
 	should.Equal(1, any.Get(0).ToInt())
 	should.Equal(2, any.Size())
 	should.True(any.ToBool())
 	should.Equal(1, any.ToInt())
-}
-
-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)
+	should.Equal(1, any.GetArray()[0].ToInt())
+	should.Equal([]interface{}{float64(1), float64(2)}, any.GetInterface())
+	stream := NewStream(ConfigDefault, nil, 32)
+	any.WriteTo(stream)
+	should.Equal("[1,2]", string(stream.Buffer()))
 }
 
 func Test_wrap_array(t *testing.T) {
 	should := require.New(t)
 	any := Wrap([]int{1, 2, 3})
 	should.Equal("[1,2,3]", any.ToString())
-	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, 3}, elements)
-	any = Wrap([]int{1, 2, 3})
-	should.Equal(3, any.Size())
-	any = Wrap([]int{1, 2, 3})
-	should.Equal(2, any.Get(1).ToInt())
 }
 
 func Test_array_lazy_any_get(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[1,[2,3],4]")
-	should.Nil(err)
+	any := Get([]byte("[1,[2,3],4]"))
 	should.Equal(3, any.Get(1, 1).ToInt())
 	should.Equal("[1,[2,3],4]", any.ToString())
 }
 
 func Test_array_lazy_any_get_all(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[[1],[2],[3,4]]")
-	should.Nil(err)
+	any := Get([]byte("[[1],[2],[3,4]]"))
 	should.Equal("[1,2,3]", any.Get('*', 0).ToString())
 }
 
@@ -87,27 +74,15 @@ func Test_array_wrapper_any_get_all(t *testing.T) {
 
 func Test_array_lazy_any_get_invalid(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[]")
-	should.Nil(err)
+	any := Get([]byte("[]"))
 	should.Equal(Invalid, any.Get(1, 1).ValueType())
 	should.NotNil(any.Get(1, 1).LastError())
 	should.Equal(Invalid, any.Get("1").ValueType())
 	should.NotNil(any.Get("1").LastError())
 }
 
-func Test_array_lazy_any_set(t *testing.T) {
-	should := require.New(t)
-	any, err := UnmarshalAnyFromString("[1,[2,3],4]")
-	should.Nil(err)
-	any.GetArray()[0] = WrapInt64(2)
-	str, err := MarshalToString(any)
-	should.Nil(err)
-	should.Equal("[2,[2,3],4]", str)
-}
-
 func Test_invalid_array(t *testing.T) {
-	_, err := UnmarshalAnyFromString("[")
-	if err == nil || err == io.EOF {
-		t.FailNow()
-	}
+	should := require.New(t)
+	any := Get([]byte("["), 0)
+	should.Equal(Invalid, any.ValueType())
 }

+ 1 - 2
jsoniter_any_bool_test.go

@@ -7,7 +7,6 @@ import (
 
 func Test_read_bool_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("true")
-	should.Nil(err)
+	any := Get([]byte("true"))
 	should.True(any.ToBool())
 }

+ 1 - 2
jsoniter_any_float_test.go

@@ -7,8 +7,7 @@ import (
 
 func Test_read_float_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("12.3")
-	should.Nil(err)
+	any := Get([]byte("12.3"))
 	should.Equal(float64(12.3), any.ToFloat64())
 	should.Equal("12.3", any.ToString())
 	should.True(any.ToBool())

+ 2 - 4
jsoniter_any_int_test.go

@@ -8,8 +8,7 @@ import (
 
 func Test_read_int64_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("1234")
-	should.Nil(err)
+	any := Get([]byte("1234"))
 	should.Equal(1234, any.ToInt())
 	should.Equal(io.EOF, any.LastError())
 	should.Equal("1234", any.ToString())
@@ -18,7 +17,6 @@ func Test_read_int64_as_any(t *testing.T) {
 
 func Test_int_lazy_any_get(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString("1234")
-	should.Nil(err)
+	any := Get([]byte("1234"))
 	should.Equal(Invalid, any.Get(1, "2").ValueType())
 }

+ 0 - 11
jsoniter_any_map_test.go

@@ -11,15 +11,4 @@ func Test_wrap_map(t *testing.T) {
 	should.Equal("hello", any.Get("Field1").ToString())
 	any = Wrap(map[string]string{"Field1": "hello"})
 	should.Equal(1, any.Size())
-	any = Wrap(map[string]string{"Field1": "hello"})
-	vals := map[string]string{}
-	var k string
-	var v Any
-	for next, hasNext := any.IterateObject(); hasNext; {
-		k, v, hasNext = next()
-		if v.ValueType() == String {
-			vals[k] = v.ToString()
-		}
-	}
-	should.Equal(map[string]string{"Field1": "hello"}, vals)
 }

+ 1 - 2
jsoniter_any_null_test.go

@@ -7,8 +7,7 @@ import (
 
 func Test_read_null_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`null`)
-	should.Nil(err)
+	any := Get([]byte(`null`))
 	should.Equal(0, any.ToInt())
 	should.Equal(float64(0), any.ToFloat64())
 	should.Equal("", any.ToString())

+ 8 - 94
jsoniter_any_object_test.go

@@ -7,117 +7,42 @@ import (
 
 func Test_read_object_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
-	should.Nil(err)
+	any := Get([]byte(`{"a":"b","c":"d"}`))
 	should.Equal(`{"a":"b","c":"d"}`, any.ToString())
 	// partial parse
 	should.Equal("b", any.Get("a").ToString())
 	should.Equal("d", any.Get("c").ToString())
 	should.Equal(2, len(any.Keys()))
-	any, err = UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
+	any = Get([]byte(`{"a":"b","c":"d"}`))
 	// full parse
 	should.Equal(2, len(any.Keys()))
 	should.Equal(2, any.Size())
 	should.True(any.ToBool())
 	should.Equal(1, any.ToInt())
-}
-
-func Test_object_any_lazy_iterator(t *testing.T) {
-	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
-	should.Nil(err)
-	// iterator parse
-	vals := map[string]string{}
-	var k string
-	var v Any
-	next, hasNext := any.IterateObject()
-	should.True(hasNext)
-
-	k, v, hasNext = next()
-	should.True(hasNext)
-	vals[k] = v.ToString()
-
-	// trigger full parse
-	should.Equal(2, len(any.Keys()))
-
-	k, v, hasNext = next()
-	should.False(hasNext)
-	vals[k] = v.ToString()
-
-	should.Equal(map[string]string{"a": "b", "c": "d"}, vals)
-	vals = map[string]string{}
-	for next, hasNext := any.IterateObject(); hasNext; {
-		k, v, hasNext = next()
-		if v.ValueType() == String {
-			vals[k] = v.ToString()
-		}
-	}
-	should.Equal(map[string]string{"a": "b", "c": "d"}, vals)
-}
-
-func Test_object_any_with_two_lazy_iterators(t *testing.T) {
-	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":"b","c":"d","e":"f"}`)
-	should.Nil(err)
-	var k string
-	var v Any
-	next1, hasNext1 := any.IterateObject()
-	next2, hasNext2 := any.IterateObject()
-	should.True(hasNext1)
-	k, v, hasNext1 = next1()
-	should.True(hasNext1)
-	should.Equal("a", k)
-	should.Equal("b", v.ToString())
-
-	should.True(hasNext2)
-	k, v, hasNext2 = next2()
-	should.True(hasNext2)
-	should.Equal("a", k)
-	should.Equal("b", v.ToString())
-
-	k, v, hasNext1 = next1()
-	should.True(hasNext1)
-	should.Equal("c", k)
-	should.Equal("d", v.ToString())
-
-	k, v, hasNext2 = next2()
-	should.True(hasNext2)
-	should.Equal("c", k)
-	should.Equal("d", v.ToString())
+	should.Equal(Object, any.ValueType())
+	should.Nil(any.LastError())
+	should.Equal("b", any.GetObject()["a"].ToString())
 }
 
 func Test_object_lazy_any_get(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)
-	should.Nil(err)
+	any := Get([]byte(`{"a":{"b":{"c":"d"}}}`))
 	should.Equal("d", any.Get("a", "b", "c").ToString())
 }
 
 func Test_object_lazy_any_get_all(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":[0],"b":[1]}`)
-	should.Nil(err)
+	any := Get([]byte(`{"a":[0],"b":[1]}`))
 	should.Contains(any.Get('*', 0).ToString(), `"a":0`)
 }
 
 func Test_object_lazy_any_get_invalid(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{}`)
-	should.Nil(err)
+	any := Get([]byte(`{}`))
 	should.Equal(Invalid, any.Get("a", "b", "c").ValueType())
 	should.Equal(Invalid, any.Get(1).ValueType())
 }
 
-func Test_object_lazy_any_set(t *testing.T) {
-	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)
-	should.Nil(err)
-	any.GetObject()["a"] = WrapInt64(1)
-	str, err := MarshalToString(any)
-	should.Nil(err)
-	should.Equal(`{"a":1}`, str)
-}
-
 func Test_wrap_object(t *testing.T) {
 	should := require.New(t)
 	type TestObject struct {
@@ -128,17 +53,6 @@ func Test_wrap_object(t *testing.T) {
 	should.Equal("hello", any.Get("Field1").ToString())
 	any = Wrap(TestObject{"hello", "world"})
 	should.Equal(2, any.Size())
-	any = Wrap(TestObject{"hello", "world"})
-	vals := map[string]string{}
-	var k string
-	var v Any
-	for next, hasNext := any.IterateObject(); hasNext; {
-		k, v, hasNext = next()
-		if v.ValueType() == String {
-			vals[k] = v.ToString()
-		}
-	}
-	should.Equal(map[string]string{"Field1": "hello"}, vals)
 }
 
 func Test_any_within_struct(t *testing.T) {

+ 4 - 5
jsoniter_any_string_test.go

@@ -7,15 +7,14 @@ import (
 
 func Test_read_string_as_any(t *testing.T) {
 	should := require.New(t)
-	any, err := UnmarshalAnyFromString(`"hello"`)
-	should.Nil(err)
+	any := Get([]byte(`"hello"`))
 	should.Equal("hello", any.ToString())
 	should.True(any.ToBool())
-	any, err = UnmarshalAnyFromString(`" "`)
+	any = Get([]byte(`" "`))
 	should.False(any.ToBool())
-	any, err = UnmarshalAnyFromString(`"false"`)
+	any = Get([]byte(`"false"`))
 	should.False(any.ToBool())
-	any, err = UnmarshalAnyFromString(`"123"`)
+	any = Get([]byte(`"123"`))
 	should.Equal(123, any.ToInt())
 }