| package jsoniter |
| |
| import ( |
| "fmt" |
| "reflect" |
| ) |
| |
| type Any interface { |
| LastError() error |
| ValueType() ValueType |
| ToBool() bool |
| ToInt() int |
| ToInt32() int32 |
| ToInt64() int64 |
| ToUint() uint |
| ToUint32() uint32 |
| ToUint64() uint64 |
| ToFloat32() float32 |
| ToFloat64() float64 |
| ToString() string |
| 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) |
| Parse() *Iterator |
| } |
| |
| type baseAny struct{} |
| |
| func (any *baseAny) Get(path ...interface{}) Any { |
| return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)} |
| } |
| |
| 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 |
| } |
| |
| 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} |
| } |
| |
| func WrapInt64(val int64) Any { |
| return &int64Any{baseAny{}, val} |
| } |
| |
| func WrapUint32(val uint32) Any { |
| return &uint32Any{baseAny{}, val} |
| } |
| |
| func WrapUint64(val uint64) Any { |
| return &uint64Any{baseAny{}, val} |
| } |
| |
| func WrapFloat64(val float64) Any { |
| return &floatAny{baseAny{}, val} |
| } |
| |
| func WrapString(val string) Any { |
| return &stringAny{baseAny{}, nil, val} |
| } |
| |
| func Wrap(val interface{}) Any { |
| if val == nil { |
| return &nilAny{} |
| } |
| asAny, isAny := val.(Any) |
| if isAny { |
| return asAny |
| } |
| type_ := reflect.TypeOf(val) |
| switch type_.Kind() { |
| case reflect.Slice: |
| return wrapArray(val) |
| case reflect.Struct: |
| return wrapStruct(val) |
| case reflect.Map: |
| return wrapMap(val) |
| case reflect.String: |
| return WrapString(val.(string)) |
| case reflect.Int: |
| return WrapInt64(int64(val.(int))) |
| case reflect.Int8: |
| return WrapInt32(int32(val.(int8))) |
| case reflect.Int16: |
| return WrapInt32(int32(val.(int16))) |
| case reflect.Int32: |
| return WrapInt32(val.(int32)) |
| case reflect.Int64: |
| return WrapInt64(val.(int64)) |
| case reflect.Uint: |
| return WrapUint64(uint64(val.(uint))) |
| case reflect.Uint8: |
| return WrapUint32(uint32(val.(uint8))) |
| case reflect.Uint16: |
| return WrapUint32(uint32(val.(uint16))) |
| case reflect.Uint32: |
| return WrapUint32(uint32(val.(uint32))) |
| case reflect.Uint64: |
| return WrapUint64(val.(uint64)) |
| case reflect.Float32: |
| return WrapFloat64(float64(val.(float32))) |
| case reflect.Float64: |
| return WrapFloat64(val.(float64)) |
| case reflect.Bool: |
| if val.(bool) == true { |
| return &trueAny{} |
| } else { |
| return &falseAny{} |
| } |
| } |
| return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", type_)} |
| } |
| |
| func (iter *Iterator) ReadAny() Any { |
| return iter.readAny(nil) |
| } |
| |
| func (iter *Iterator) readAny(reusableIter *Iterator) Any { |
| c := iter.nextToken() |
| switch c { |
| case '"': |
| return iter.readStringAny(reusableIter) |
| case 'n': |
| iter.skipFixedBytes(3) // null |
| return &nilAny{} |
| case 't': |
| iter.skipFixedBytes(3) // true |
| return &trueAny{} |
| case 'f': |
| iter.skipFixedBytes(4) // false |
| return &falseAny{} |
| case '{': |
| return iter.readObjectAny(reusableIter) |
| case '[': |
| return iter.readArrayAny(reusableIter) |
| default: |
| return iter.readNumberAny(reusableIter, c) |
| } |
| } |
| |
| func (iter *Iterator) readNumberAny(reusableIter *Iterator, firstByte byte) Any { |
| dotFound := false |
| lazyBuf := make([]byte, 1, 8) |
| lazyBuf[0] = firstByte |
| 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 |
| if dotFound { |
| return &float64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } else { |
| if firstByte == '-' { |
| return &int64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } else { |
| return &uint64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } |
| } |
| } |
| } |
| lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...) |
| if !iter.loadMore() { |
| iter.head = iter.tail |
| if dotFound { |
| return &float64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } else { |
| if firstByte == '-' { |
| return &int64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } else { |
| return &uint64LazyAny{baseAny{}, lazyBuf, reusableIter, nil, 0} |
| } |
| } |
| } |
| } |
| } |
| |
| func (iter *Iterator) readStringAny(reusableIter *Iterator) Any { |
| 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]...) |
| 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{} |
| } |
| } |
| } |
| |
| func (iter *Iterator) readArrayAny(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]...) |
| return &arrayLazyAny{baseAny{}, lazyBuf, reusableIter, nil, nil, lazyBuf} |
| } |
| } |
| } |
| lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...) |
| if !iter.loadMore() { |
| iter.reportError("skipArray", "incomplete array") |
| return &invalidAny{} |
| } |
| } |
| } |