1
0
mirror of https://github.com/json-iterator/go.git synced 2024-12-09 08:55:35 +02:00
json-iterator/any.go

326 lines
7.0 KiB
Go
Raw Normal View History

2017-01-22 17:29:48 +02:00
package jsoniter
2017-01-28 15:11:36 +02:00
import (
"errors"
2017-01-28 15:11:36 +02:00
"fmt"
2018-02-28 11:09:30 +02:00
"github.com/modern-go/reflect2"
"io"
2017-06-19 17:43:53 +02:00
"reflect"
2018-02-23 02:12:45 +02:00
"strconv"
2018-02-24 16:04:41 +02:00
"unsafe"
2017-01-28 15:11:36 +02:00
)
2017-01-26 10:24:01 +02:00
2017-07-09 10:26:30 +02:00
// Any generic object representation.
// The lazy json implementation holds []byte and parse lazily.
2017-01-22 17:29:48 +02:00
type Any interface {
LastError() error
2017-01-26 10:24:01 +02:00
ValueType() ValueType
2017-06-19 15:21:20 +02:00
MustBeValid() Any
2017-01-22 17:29:48 +02:00
ToBool() bool
ToInt() int
ToInt32() int32
ToInt64() int64
2017-01-29 10:55:32 +02:00
ToUint() uint
ToUint32() uint32
ToUint64() uint64
2017-01-22 17:29:48 +02:00
ToFloat32() float32
ToFloat64() float64
ToString() string
2017-06-19 09:40:00 +02:00
ToVal(val interface{})
Get(path ...interface{}) Any
2017-01-24 16:36:16 +02:00
Size() int
Keys() []string
2017-01-26 09:44:10 +02:00
GetInterface() interface{}
2017-01-25 16:43:57 +02:00
WriteTo(stream *Stream)
}
2017-01-25 16:43:57 +02:00
type baseAny struct{}
2017-01-24 16:56:18 +02:00
func (any *baseAny) Get(path ...interface{}) Any {
2018-02-19 08:18:42 +02:00
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
2017-01-24 16:56:18 +02:00
}
2017-01-24 16:36:16 +02:00
func (any *baseAny) Size() int {
return 0
}
func (any *baseAny) Keys() []string {
return []string{}
}
2017-06-19 09:40:00 +02:00
func (any *baseAny) ToVal(obj interface{}) {
panic("not implemented")
}
2017-07-09 10:26:30 +02:00
// WrapInt32 turn int32 into Any interface
2017-01-29 10:55:32 +02:00
func WrapInt32(val int32) Any {
return &int32Any{baseAny{}, val}
}
2017-07-09 10:26:30 +02:00
// WrapInt64 turn int64 into Any interface
2017-01-25 16:43:57 +02:00
func WrapInt64(val int64) Any {
2017-01-29 10:55:32 +02:00
return &int64Any{baseAny{}, val}
}
2017-07-09 10:26:30 +02:00
// WrapUint32 turn uint32 into Any interface
2017-01-29 10:55:32 +02:00
func WrapUint32(val uint32) Any {
return &uint32Any{baseAny{}, val}
}
2017-07-09 10:26:30 +02:00
// WrapUint64 turn uint64 into Any interface
2017-01-29 10:55:32 +02:00
func WrapUint64(val uint64) Any {
return &uint64Any{baseAny{}, val}
2017-01-26 10:33:16 +02:00
}
2017-07-09 10:26:30 +02:00
// WrapFloat64 turn float64 into Any interface
2017-01-26 10:33:16 +02:00
func WrapFloat64(val float64) Any {
return &floatAny{baseAny{}, val}
2017-01-25 16:43:57 +02:00
}
2017-07-09 10:26:30 +02:00
// WrapString turn string into Any interface
2017-01-26 10:41:49 +02:00
func WrapString(val string) Any {
return &stringAny{baseAny{}, val}
2017-01-26 10:41:49 +02:00
}
2017-07-09 10:26:30 +02:00
// Wrap turn a go object into Any interface
2017-01-28 15:11:36 +02:00
func Wrap(val interface{}) Any {
2017-01-28 17:11:29 +02:00
if val == nil {
return &nilAny{}
}
2017-05-19 13:44:27 +02:00
asAny, isAny := val.(Any)
if isAny {
return asAny
}
2018-02-22 04:12:08 +02:00
typ := reflect2.TypeOf(val)
2017-07-09 10:26:30 +02:00
switch typ.Kind() {
2017-01-28 15:11:36 +02:00
case reflect.Slice:
return wrapArray(val)
2017-01-28 16:45:03 +02:00
case reflect.Struct:
return wrapStruct(val)
2017-01-28 17:11:29 +02:00
case reflect.Map:
return wrapMap(val)
2017-01-28 15:11:36 +02:00
case reflect.String:
return WrapString(val.(string))
case reflect.Int:
2018-02-23 02:12:45 +02:00
if strconv.IntSize == 32 {
return WrapInt32(int32(val.(int)))
}
2017-01-28 15:11:36 +02:00
return WrapInt64(int64(val.(int)))
case reflect.Int8:
2017-01-29 10:55:32 +02:00
return WrapInt32(int32(val.(int8)))
2017-01-28 15:11:36 +02:00
case reflect.Int16:
2017-01-29 10:55:32 +02:00
return WrapInt32(int32(val.(int16)))
2017-01-28 15:11:36 +02:00
case reflect.Int32:
2017-01-29 10:55:32 +02:00
return WrapInt32(val.(int32))
2017-01-28 15:11:36 +02:00
case reflect.Int64:
return WrapInt64(val.(int64))
case reflect.Uint:
2018-02-23 02:12:45 +02:00
if strconv.IntSize == 32 {
return WrapUint32(uint32(val.(uint)))
}
2017-01-29 10:55:32 +02:00
return WrapUint64(uint64(val.(uint)))
2018-02-23 02:12:45 +02:00
case reflect.Uintptr:
if ptrSize == 32 {
return WrapUint32(uint32(val.(uintptr)))
}
return WrapUint64(uint64(val.(uintptr)))
2017-01-28 15:11:36 +02:00
case reflect.Uint8:
2017-01-29 10:55:32 +02:00
return WrapUint32(uint32(val.(uint8)))
2017-01-28 15:11:36 +02:00
case reflect.Uint16:
2017-01-29 10:55:32 +02:00
return WrapUint32(uint32(val.(uint16)))
2017-01-28 15:11:36 +02:00
case reflect.Uint32:
2017-01-29 10:55:32 +02:00
return WrapUint32(uint32(val.(uint32)))
2017-01-28 15:11:36 +02:00
case reflect.Uint64:
2017-01-29 10:55:32 +02:00
return WrapUint64(val.(uint64))
2017-01-28 15:11:36 +02:00
case reflect.Float32:
return WrapFloat64(float64(val.(float32)))
case reflect.Float64:
return WrapFloat64(val.(float64))
2017-01-28 17:11:29 +02:00
case reflect.Bool:
if val.(bool) == true {
return &trueAny{}
}
2017-07-09 10:26:30 +02:00
return &falseAny{}
2017-01-28 15:11:36 +02:00
}
2017-07-09 10:26:30 +02:00
return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)}
2017-01-28 15:11:36 +02:00
}
2017-07-09 10:26:30 +02:00
// ReadAny read next JSON element as an Any object. It is a better json.RawMessage.
2017-01-22 17:29:48 +02:00
func (iter *Iterator) ReadAny() Any {
2017-06-17 15:10:08 +02:00
return iter.readAny()
}
2017-06-17 15:10:08 +02:00
func (iter *Iterator) readAny() Any {
2017-01-23 02:45:57 +02:00
c := iter.nextToken()
switch c {
case '"':
iter.unreadByte()
return &stringAny{baseAny{}, iter.ReadString()}
2017-01-23 02:45:57 +02:00
case 'n':
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('u', 'l', 'l') // null
2017-01-22 17:29:48 +02:00
return &nilAny{}
2017-01-23 02:45:57 +02:00
case 't':
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('r', 'u', 'e') // true
2017-01-23 02:45:57 +02:00
return &trueAny{}
case 'f':
2017-07-10 09:23:35 +02:00
iter.skipFourBytes('a', 'l', 's', 'e') // false
2017-01-23 02:45:57 +02:00
return &falseAny{}
case '{':
2017-06-17 15:10:08 +02:00
return iter.readObjectAny()
2017-01-24 16:36:16 +02:00
case '[':
2017-06-17 15:10:08 +02:00
return iter.readArrayAny()
2017-06-18 11:00:28 +02:00
case '-':
return iter.readNumberAny(false)
2017-10-31 16:47:02 +02:00
case 0:
return &invalidAny{baseAny{}, errors.New("input is empty")}
2017-01-24 16:36:16 +02:00
default:
2017-06-18 11:00:28 +02:00
return iter.readNumberAny(true)
2017-01-22 17:29:48 +02:00
}
}
2017-06-18 11:00:28 +02:00
func (iter *Iterator) readNumberAny(positive bool) Any {
iter.startCapture(iter.head - 1)
iter.skipNumber()
2017-06-18 11:00:28 +02:00
lazyBuf := iter.stopCapture()
return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
2017-01-23 02:33:43 +02:00
}
2017-06-17 15:10:08 +02:00
func (iter *Iterator) readObjectAny() Any {
2017-06-18 11:00:28 +02:00
iter.startCapture(iter.head - 1)
iter.skipObject()
lazyBuf := iter.stopCapture()
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
2017-01-22 17:29:48 +02:00
}
2017-01-24 16:36:16 +02:00
2017-06-17 15:10:08 +02:00
func (iter *Iterator) readArrayAny() Any {
2017-06-18 11:00:28 +02:00
iter.startCapture(iter.head - 1)
iter.skipArray()
lazyBuf := iter.stopCapture()
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
2017-01-24 16:36:16 +02:00
}
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)
2017-06-19 15:21:20 +02:00
if valueBytes == nil {
return newInvalidAny(path[i:])
}
iter.ResetBytes(valueBytes)
case int:
valueBytes := locateArrayElement(iter, pathKey)
2017-06-19 15:21:20 +02:00
if valueBytes == nil {
return newInvalidAny(path[i:])
}
iter.ResetBytes(valueBytes)
case int32:
if '*' == pathKey {
return iter.readAny().Get(path[i:]...)
}
2017-07-09 10:26:30 +02:00
return newInvalidAny(path[i:])
default:
return newInvalidAny(path[i:])
}
}
if iter.Error != nil && iter.Error != io.EOF {
return &invalidAny{baseAny{}, iter.Error}
}
return iter.readAny()
2017-06-19 15:21:20 +02:00
}
2018-02-19 17:01:19 +02:00
2018-02-22 04:12:08 +02:00
var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
2018-02-20 17:04:04 +02:00
2018-02-22 04:12:08 +02:00
func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
2018-02-20 17:04:04 +02:00
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
2018-02-22 04:12:08 +02:00
valType: typ,
2018-02-20 17:04:04 +02:00
}
}
return nil
}
2018-02-22 04:12:08 +02:00
func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
2018-02-20 17:04:04 +02:00
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
2018-02-22 04:12:08 +02:00
valType: typ,
2018-02-20 17:04:04 +02:00
}
}
return nil
}
2018-02-19 17:01:19 +02:00
type anyCodec struct {
valType reflect2.Type
}
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
panic("not implemented")
}
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := codec.valType.UnsafeIndirect(ptr)
any := obj.(Any)
any.WriteTo(stream)
}
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
obj := codec.valType.UnsafeIndirect(ptr)
any := obj.(Any)
return any.Size() == 0
}
type directAnyCodec struct {
}
func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*(*Any)(ptr) = iter.readAny()
}
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
any := *(*Any)(ptr)
2018-10-24 15:05:37 +02:00
if any == nil {
stream.WriteNil()
return
}
2018-02-19 17:01:19 +02:00
any.WriteTo(stream)
}
func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool {
any := *(*Any)(ptr)
return any.Size() == 0
2018-02-20 17:04:04 +02:00
}