1
0
mirror of https://github.com/json-iterator/go.git synced 2025-03-23 21:09:11 +02:00
json-iterator/feature_any.go

214 lines
4.9 KiB
Go
Raw Normal View History

2017-01-22 23:29:48 +08:00
package jsoniter
type Any interface {
LastError() error
ToBool() bool
ToInt() int
ToInt32() int32
ToInt64() int64
ToFloat32() float32
ToFloat64() float64
ToString() string
Get(path ...interface{}) Any
2017-01-24 22:36:16 +08:00
Size() int
Keys() []string
IterateObject() (func() (string, Any, bool), bool)
2017-01-24 22:47:56 +08:00
IterateArray() (func() (Any, bool), bool)
2017-01-25 22:43:57 +08:00
GetArray() []Any
SetArray(newList []Any) bool
GetObject() map[string]Any
SetObject(map[string]Any) bool
WriteTo(stream *Stream)
}
2017-01-25 22:43:57 +08:00
type baseAny struct{}
2017-01-24 22:56:18 +08:00
func (any *baseAny) Get(path ...interface{}) Any {
return &invalidAny{}
}
2017-01-24 22:36:16 +08:00
func (any *baseAny) Size() int {
return 0
}
func (any *baseAny) Keys() []string {
return []string{}
}
func (any *baseAny) IterateObject() (func() (string, Any, bool), bool) {
return nil, false
2017-01-22 23:29:48 +08:00
}
2017-01-24 22:47:56 +08:00
func (any *baseAny) IterateArray() (func() (Any, bool), bool) {
return nil, false
}
2017-01-25 22:43:57 +08:00
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 WrapInt64(val int64) Any {
return &intAny{baseAny{}, nil, val}
}
2017-01-22 23:29:48 +08:00
func (iter *Iterator) ReadAny() Any {
return iter.readAny(nil)
}
func (iter *Iterator) readAny(reusableIter *Iterator) Any {
2017-01-23 08:45:57 +08:00
c := iter.nextToken()
switch c {
case '"':
return iter.readStringAny(reusableIter)
2017-01-23 08:45:57 +08:00
case 'n':
iter.skipFixedBytes(3) // null
2017-01-22 23:29:48 +08:00
return &nilAny{}
2017-01-23 08:45:57 +08:00
case 't':
iter.skipFixedBytes(3) // true
return &trueAny{}
case 'f':
iter.skipFixedBytes(4) // false
return &falseAny{}
case '{':
return iter.readObjectAny(reusableIter)
2017-01-24 22:36:16 +08:00
case '[':
return iter.readArrayAny(reusableIter)
default:
iter.unreadByte()
return iter.readNumberAny(reusableIter)
2017-01-22 23:29:48 +08:00
}
}
func (iter *Iterator) readNumberAny(reusableIter *Iterator) Any {
2017-01-22 23:29:48 +08:00
dotFound := false
var lazyBuf []byte
for {
for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i]
if c == '.' {
dotFound = true
continue
}
switch c {
case ' ', '\n', '\r', '\t', ',', '}', ']':
lazyBuf = append(lazyBuf, iter.buf[iter.head:i]...)
iter.head = i
2017-01-23 08:33:43 +08:00
if dotFound {
2017-01-25 22:43:57 +08:00
return &floatLazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0}
2017-01-23 08:33:43 +08:00
} else {
return &intLazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0}
2017-01-23 08:33:43 +08:00
}
2017-01-22 23:29:48 +08:00
}
}
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
if !iter.loadMore() {
2017-01-23 08:33:43 +08:00
iter.head = iter.tail
if dotFound {
return &floatLazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0}
2017-01-23 08:33:43 +08:00
} else {
return &intLazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0}
2017-01-23 08:33:43 +08:00
}
}
}
}
func (iter *Iterator) readStringAny(reusableIter *Iterator) Any {
2017-01-23 08:33:43 +08:00
lazyBuf := make([]byte, 1, 8)
lazyBuf[0] = '"'
for {
end, escaped := iter.findStringEnd()
if end == -1 {
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
if !iter.loadMore() {
iter.reportError("readStringAny", "incomplete string")
return &invalidAny{}
}
if escaped {
iter.head = 1 // skip the first char as last char read is \
}
} else {
lazyBuf = append(lazyBuf, iter.buf[iter.head:end]...)
iter.head = end
return &stringLazyAny{baseAny{}, lazyBuf, reusableIter, nil, ""}
}
}
}
func (iter *Iterator) readObjectAny(reusableIter *Iterator) Any {
level := 1
lazyBuf := make([]byte, 1, 32)
lazyBuf[0] = '{'
for {
start := iter.head
for i := iter.head; i < iter.tail; i++ {
switch iter.buf[i] {
case '"': // If inside string, skip it
iter.head = i + 1
iter.skipString()
i = iter.head - 1 // it will be i++ soon
case '{': // If open symbol, increase level
level++
case '}': // If close symbol, increase level
level--
// If we have returned to the original level, we're done
if level == 0 {
iter.head = i + 1
lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
2017-01-24 22:36:16 +08:00
return &objectLazyAny{baseAny{}, lazyBuf, reusableIter, nil, nil, lazyBuf}
}
}
}
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
if !iter.loadMore() {
iter.reportError("skipObject", "incomplete object")
return &invalidAny{}
2017-01-22 23:29:48 +08:00
}
}
}
2017-01-24 22:36:16 +08:00
func (iter *Iterator) readArrayAny(reusableIter *Iterator) Any {
level := 1
lazyBuf := make([]byte, 1, 32)
2017-01-26 00:25:17 +08:00
lazyBuf[0] = '['
2017-01-24 22:36:16 +08:00
for {
start := iter.head
for i := iter.head; i < iter.tail; i++ {
switch iter.buf[i] {
case '"': // If inside string, skip it
iter.head = i + 1
iter.skipString()
i = iter.head - 1 // it will be i++ soon
case '[': // If open symbol, increase level
level++
case ']': // If close symbol, increase level
level--
// If we have returned to the original level, we're done
if level == 0 {
iter.head = i + 1
lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
2017-01-25 22:43:57 +08:00
return &arrayLazyAny{baseAny{}, lazyBuf, reusableIter, nil, nil, lazyBuf}
2017-01-24 22:36:16 +08:00
}
}
}
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
if !iter.loadMore() {
iter.reportError("skipArray", "incomplete array")
return &invalidAny{}
}
}
}