.github
alerting
client
config
controller
core
docs
example
jsonpath
k8s
k8stest
metric
pattern
security
storage
util
vendor
cloud.google.com
github.com
TwinProduction
beorn7
boltdb
cespare
davecgh
go-ping
gogo
golang
google
googleapis
gorilla
imdario
json-iterator
go
.codecov.yml
.gitignore
.travis.yml
Gopkg.lock
Gopkg.toml
LICENSE
README.md
adapter.go
any.go
any_array.go
any_bool.go
any_float.go
any_int32.go
any_int64.go
any_invalid.go
any_nil.go
any_number.go
any_object.go
any_str.go
any_uint32.go
any_uint64.go
build.sh
config.go
fuzzy_mode_convert_table.md
go.mod
go.sum
iter.go
iter_array.go
iter_float.go
iter_int.go
iter_object.go
iter_skip.go
iter_skip_sloppy.go
iter_skip_strict.go
iter_str.go
jsoniter.go
pool.go
reflect.go
reflect_array.go
reflect_dynamic.go
reflect_extension.go
reflect_json_number.go
reflect_json_raw_message.go
reflect_map.go
reflect_marshaler.go
reflect_native.go
reflect_optional.go
reflect_slice.go
reflect_struct_decoder.go
reflect_struct_encoder.go
stream.go
stream_float.go
stream_int.go
stream_str.go
test.sh
matttproud
miekg
modern-go
prometheus
spf13
golang.org
google.golang.org
gopkg.in
k8s.io
sigs.k8s.io
modules.txt
watchdog
web
.dockerignore
.gitattributes
.gitignore
Dockerfile
LICENSE.md
Makefile
README.md
config.yaml
go.mod
go.sum
main.go
326 lines
7.0 KiB
Go
326 lines
7.0 KiB
Go
package jsoniter
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/modern-go/reflect2"
|
|
"io"
|
|
"reflect"
|
|
"strconv"
|
|
"unsafe"
|
|
)
|
|
|
|
// Any generic object representation.
|
|
// The lazy json implementation holds []byte and parse lazily.
|
|
type Any interface {
|
|
LastError() error
|
|
ValueType() ValueType
|
|
MustBeValid() Any
|
|
ToBool() bool
|
|
ToInt() int
|
|
ToInt32() int32
|
|
ToInt64() int64
|
|
ToUint() uint
|
|
ToUint32() uint32
|
|
ToUint64() uint64
|
|
ToFloat32() float32
|
|
ToFloat64() float64
|
|
ToString() string
|
|
ToVal(val interface{})
|
|
Get(path ...interface{}) Any
|
|
Size() int
|
|
Keys() []string
|
|
GetInterface() interface{}
|
|
WriteTo(stream *Stream)
|
|
}
|
|
|
|
type baseAny struct{}
|
|
|
|
func (any *baseAny) Get(path ...interface{}) Any {
|
|
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
|
|
}
|
|
|
|
func (any *baseAny) Size() int {
|
|
return 0
|
|
}
|
|
|
|
func (any *baseAny) Keys() []string {
|
|
return []string{}
|
|
}
|
|
|
|
func (any *baseAny) ToVal(obj interface{}) {
|
|
panic("not implemented")
|
|
}
|
|
|
|
// WrapInt32 turn int32 into Any interface
|
|
func WrapInt32(val int32) Any {
|
|
return &int32Any{baseAny{}, val}
|
|
}
|
|
|
|
// WrapInt64 turn int64 into Any interface
|
|
func WrapInt64(val int64) Any {
|
|
return &int64Any{baseAny{}, val}
|
|
}
|
|
|
|
// WrapUint32 turn uint32 into Any interface
|
|
func WrapUint32(val uint32) Any {
|
|
return &uint32Any{baseAny{}, val}
|
|
}
|
|
|
|
// WrapUint64 turn uint64 into Any interface
|
|
func WrapUint64(val uint64) Any {
|
|
return &uint64Any{baseAny{}, val}
|
|
}
|
|
|
|
// WrapFloat64 turn float64 into Any interface
|
|
func WrapFloat64(val float64) Any {
|
|
return &floatAny{baseAny{}, val}
|
|
}
|
|
|
|
// WrapString turn string into Any interface
|
|
func WrapString(val string) Any {
|
|
return &stringAny{baseAny{}, val}
|
|
}
|
|
|
|
// Wrap turn a go object into Any interface
|
|
func Wrap(val interface{}) Any {
|
|
if val == nil {
|
|
return &nilAny{}
|
|
}
|
|
asAny, isAny := val.(Any)
|
|
if isAny {
|
|
return asAny
|
|
}
|
|
typ := reflect2.TypeOf(val)
|
|
switch typ.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:
|
|
if strconv.IntSize == 32 {
|
|
return WrapInt32(int32(val.(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:
|
|
if strconv.IntSize == 32 {
|
|
return WrapUint32(uint32(val.(uint)))
|
|
}
|
|
return WrapUint64(uint64(val.(uint)))
|
|
case reflect.Uintptr:
|
|
if ptrSize == 32 {
|
|
return WrapUint32(uint32(val.(uintptr)))
|
|
}
|
|
return WrapUint64(uint64(val.(uintptr)))
|
|
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{}
|
|
}
|
|
return &falseAny{}
|
|
}
|
|
return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)}
|
|
}
|
|
|
|
// ReadAny read next JSON element as an Any object. It is a better json.RawMessage.
|
|
func (iter *Iterator) ReadAny() Any {
|
|
return iter.readAny()
|
|
}
|
|
|
|
func (iter *Iterator) readAny() Any {
|
|
c := iter.nextToken()
|
|
switch c {
|
|
case '"':
|
|
iter.unreadByte()
|
|
return &stringAny{baseAny{}, iter.ReadString()}
|
|
case 'n':
|
|
iter.skipThreeBytes('u', 'l', 'l') // null
|
|
return &nilAny{}
|
|
case 't':
|
|
iter.skipThreeBytes('r', 'u', 'e') // true
|
|
return &trueAny{}
|
|
case 'f':
|
|
iter.skipFourBytes('a', 'l', 's', 'e') // false
|
|
return &falseAny{}
|
|
case '{':
|
|
return iter.readObjectAny()
|
|
case '[':
|
|
return iter.readArrayAny()
|
|
case '-':
|
|
return iter.readNumberAny(false)
|
|
case 0:
|
|
return &invalidAny{baseAny{}, errors.New("input is empty")}
|
|
default:
|
|
return iter.readNumberAny(true)
|
|
}
|
|
}
|
|
|
|
func (iter *Iterator) readNumberAny(positive bool) Any {
|
|
iter.startCapture(iter.head - 1)
|
|
iter.skipNumber()
|
|
lazyBuf := iter.stopCapture()
|
|
return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
|
|
}
|
|
|
|
func (iter *Iterator) readObjectAny() Any {
|
|
iter.startCapture(iter.head - 1)
|
|
iter.skipObject()
|
|
lazyBuf := iter.stopCapture()
|
|
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}
|
|
}
|
|
|
|
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)
|
|
if valueBytes == nil {
|
|
return newInvalidAny(path[i:])
|
|
}
|
|
iter.ResetBytes(valueBytes)
|
|
case int:
|
|
valueBytes := locateArrayElement(iter, pathKey)
|
|
if valueBytes == nil {
|
|
return newInvalidAny(path[i:])
|
|
}
|
|
iter.ResetBytes(valueBytes)
|
|
case int32:
|
|
if '*' == pathKey {
|
|
return iter.readAny().Get(path[i:]...)
|
|
}
|
|
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()
|
|
}
|
|
|
|
var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
|
|
|
|
func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|
if typ == anyType {
|
|
return &directAnyCodec{}
|
|
}
|
|
if typ.Implements(anyType) {
|
|
return &anyCodec{
|
|
valType: typ,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
|
|
if typ == anyType {
|
|
return &directAnyCodec{}
|
|
}
|
|
if typ.Implements(anyType) {
|
|
return &anyCodec{
|
|
valType: typ,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
if any == nil {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
any.WriteTo(stream)
|
|
}
|
|
|
|
func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
|
any := *(*Any)(ptr)
|
|
return any.Size() == 0
|
|
}
|