package jsoniter import ( "bytes" "io" ) // RawMessage to make replace json with jsoniter type RawMessage []byte // Unmarshal adapts to json/encoding Unmarshal API // // Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. // Refer to https://godoc.org/encoding/json#Unmarshal for more information func Unmarshal(data []byte, v interface{}) error { return ConfigDefault.Unmarshal(data, v) } // UnmarshalFromString is a convenient method to read from string instead of []byte func UnmarshalFromString(str string, v interface{}) error { return ConfigDefault.UnmarshalFromString(str, v) } // Get quick method to get value from deeply nested JSON structure 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 // Refer to https://godoc.org/encoding/json#Marshal for more information func Marshal(v interface{}) ([]byte, error) { return ConfigDefault.Marshal(v) } // MarshalIndent same as json.MarshalIndent. Prefix is not supported. func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { return ConfigDefault.MarshalIndent(v, prefix, indent) } // MarshalToString convenient method to write as string instead of []byte func MarshalToString(v interface{}) (string, error) { return ConfigDefault.MarshalToString(v) } // NewDecoder adapts to json/stream NewDecoder API. // // NewDecoder returns a new decoder that reads from r. // // Instead of a json/encoding Decoder, an Decoder is returned // Refer to https://godoc.org/encoding/json#NewDecoder for more information func NewDecoder(reader io.Reader) *Decoder { return ConfigDefault.NewDecoder(reader) } // Decoder reads and decodes JSON values from an input stream. // Decoder provides identical APIs with json/stream Decoder (Token() and UseNumber() are in progress) type Decoder struct { iter *Iterator } // Decode decode JSON into interface{} func (adapter *Decoder) Decode(obj interface{}) error { if adapter.iter.head == adapter.iter.tail && adapter.iter.reader != nil { if !adapter.iter.loadMore() { return io.EOF } } adapter.iter.ReadVal(obj) err := adapter.iter.Error if err == io.EOF { return nil } return adapter.iter.Error } // More is there more? func (adapter *Decoder) More() bool { iter := adapter.iter if iter.Error != nil { return false } c := iter.nextToken() if c == 0 { return false } iter.unreadByte() return c != ']' && c != '}' } // Buffered remaining buffer func (adapter *Decoder) Buffered() io.Reader { remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail] return bytes.NewReader(remaining) } // UseNumber causes the Decoder to unmarshal a number into an interface{} as a // Number instead of as a float64. func (adapter *Decoder) UseNumber() { cfg := adapter.iter.cfg.configBeforeFrozen cfg.UseNumber = true adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) } // DisallowUnknownFields causes the Decoder to return an error when the destination // is a struct and the input contains object keys which do not match any // non-ignored, exported fields in the destination. func (adapter *Decoder) DisallowUnknownFields() { cfg := adapter.iter.cfg.configBeforeFrozen cfg.DisallowUnknownFields = true adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) } // NewEncoder same as json.NewEncoder func NewEncoder(writer io.Writer) *Encoder { return ConfigDefault.NewEncoder(writer) } // Encoder same as json.Encoder type Encoder struct { stream *Stream } // Encode encode interface{} as JSON to io.Writer func (adapter *Encoder) Encode(val interface{}) error { adapter.stream.WriteVal(val) adapter.stream.WriteRaw("\n") adapter.stream.Flush() return adapter.stream.Error } // SetIndent set the indention. Prefix is not supported func (adapter *Encoder) SetIndent(prefix, indent string) { config := adapter.stream.cfg.configBeforeFrozen config.IndentionStep = len(indent) adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) } // SetEscapeHTML escape html by default, set to false to disable func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) { config := adapter.stream.cfg.configBeforeFrozen config.EscapeHTML = escapeHTML adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) } // Valid reports whether data is a valid JSON encoding. func Valid(data []byte) bool { return ConfigDefault.Valid(data) }
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 }
package jsoniter import ( "reflect" "unsafe" ) type arrayLazyAny struct { baseAny cfg *frozenConfig buf []byte err error } func (any *arrayLazyAny) ValueType() ValueType { return ArrayValue } func (any *arrayLazyAny) MustBeValid() Any { return any } func (any *arrayLazyAny) LastError() error { return any.err } func (any *arrayLazyAny) ToBool() bool { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) return iter.ReadArray() } func (any *arrayLazyAny) ToInt() int { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToInt32() int32 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToInt64() int64 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToUint() uint { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToUint32() uint32 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToUint64() uint64 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToFloat32() float32 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToFloat64() float64 { if any.ToBool() { return 1 } return 0 } func (any *arrayLazyAny) ToString() string { return *(*string)(unsafe.Pointer(&any.buf)) } func (any *arrayLazyAny) ToVal(val interface{}) { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) iter.ReadVal(val) } func (any *arrayLazyAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } switch firstPath := path[0].(type) { case int: iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) valueBytes := locateArrayElement(iter, firstPath) if valueBytes == nil { return newInvalidAny(path) } iter.ResetBytes(valueBytes) return locatePath(iter, path[1:]) case int32: if '*' == firstPath { 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() != InvalidValue { arr = append(arr, found) } return true }) return wrapArray(arr) } return newInvalidAny(path) default: return newInvalidAny(path) } } func (any *arrayLazyAny) Size() int { 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) WriteTo(stream *Stream) { stream.Write(any.buf) } func (any *arrayLazyAny) GetInterface() interface{} { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) return iter.Read() } type arrayAny struct { baseAny val reflect.Value } func wrapArray(val interface{}) *arrayAny { return &arrayAny{baseAny{}, reflect.ValueOf(val)} } func (any *arrayAny) ValueType() ValueType { return ArrayValue } func (any *arrayAny) MustBeValid() Any { return any } func (any *arrayAny) LastError() error { return nil } func (any *arrayAny) ToBool() bool { return any.val.Len() != 0 } func (any *arrayAny) ToInt() int { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToInt32() int32 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToInt64() int64 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToUint() uint { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToUint32() uint32 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToUint64() uint64 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToFloat32() float32 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToFloat64() float64 { if any.val.Len() == 0 { return 0 } return 1 } func (any *arrayAny) ToString() string { str, _ := MarshalToString(any.val.Interface()) return str } func (any *arrayAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } switch firstPath := path[0].(type) { case int: if firstPath < 0 || firstPath >= any.val.Len() { return newInvalidAny(path) } return Wrap(any.val.Index(firstPath).Interface()) case int32: if '*' == firstPath { mappedAll := make([]Any, 0) for i := 0; i < any.val.Len(); i++ { mapped := Wrap(any.val.Index(i).Interface()).Get(path[1:]...) if mapped.ValueType() != InvalidValue { mappedAll = append(mappedAll, mapped) } } return wrapArray(mappedAll) } return newInvalidAny(path) default: return newInvalidAny(path) } } func (any *arrayAny) Size() int { return any.val.Len() } func (any *arrayAny) WriteTo(stream *Stream) { stream.WriteVal(any.val) } func (any *arrayAny) GetInterface() interface{} { return any.val.Interface() }
package jsoniter type trueAny struct { baseAny } func (any *trueAny) LastError() error { return nil } func (any *trueAny) ToBool() bool { return true } func (any *trueAny) ToInt() int { return 1 } func (any *trueAny) ToInt32() int32 { return 1 } func (any *trueAny) ToInt64() int64 { return 1 } func (any *trueAny) ToUint() uint { return 1 } func (any *trueAny) ToUint32() uint32 { return 1 } func (any *trueAny) ToUint64() uint64 { return 1 } func (any *trueAny) ToFloat32() float32 { return 1 } func (any *trueAny) ToFloat64() float64 { return 1 } func (any *trueAny) ToString() string { return "true" } func (any *trueAny) WriteTo(stream *Stream) { stream.WriteTrue() } func (any *trueAny) Parse() *Iterator { return nil } func (any *trueAny) GetInterface() interface{} { return true } func (any *trueAny) ValueType() ValueType { return BoolValue } func (any *trueAny) MustBeValid() Any { return any } type falseAny struct { baseAny } func (any *falseAny) LastError() error { return nil } func (any *falseAny) ToBool() bool { return false } func (any *falseAny) ToInt() int { return 0 } func (any *falseAny) ToInt32() int32 { return 0 } func (any *falseAny) ToInt64() int64 { return 0 } func (any *falseAny) ToUint() uint { return 0 } func (any *falseAny) ToUint32() uint32 { return 0 } func (any *falseAny) ToUint64() uint64 { return 0 } func (any *falseAny) ToFloat32() float32 { return 0 } func (any *falseAny) ToFloat64() float64 { return 0 } func (any *falseAny) ToString() string { return "false" } func (any *falseAny) WriteTo(stream *Stream) { stream.WriteFalse() } func (any *falseAny) Parse() *Iterator { return nil } func (any *falseAny) GetInterface() interface{} { return false } func (any *falseAny) ValueType() ValueType { return BoolValue } func (any *falseAny) MustBeValid() Any { return any }
package jsoniter import ( "strconv" ) type floatAny struct { baseAny val float64 } func (any *floatAny) Parse() *Iterator { return nil } func (any *floatAny) ValueType() ValueType { return NumberValue } func (any *floatAny) MustBeValid() Any { return any } func (any *floatAny) LastError() error { return nil } func (any *floatAny) ToBool() bool { return any.ToFloat64() != 0 } func (any *floatAny) ToInt() int { return int(any.val) } func (any *floatAny) ToInt32() int32 { return int32(any.val) } func (any *floatAny) ToInt64() int64 { return int64(any.val) } func (any *floatAny) ToUint() uint { if any.val > 0 { return uint(any.val) } return 0 } func (any *floatAny) ToUint32() uint32 { if any.val > 0 { return uint32(any.val) } return 0 } func (any *floatAny) ToUint64() uint64 { if any.val > 0 { return uint64(any.val) } return 0 } func (any *floatAny) ToFloat32() float32 { return float32(any.val) } func (any *floatAny) ToFloat64() float64 { return any.val } func (any *floatAny) ToString() string { return strconv.FormatFloat(any.val, 'E', -1, 64) } func (any *floatAny) WriteTo(stream *Stream) { stream.WriteFloat64(any.val) } func (any *floatAny) GetInterface() interface{} { return any.val }
package jsoniter import ( "strconv" ) type int32Any struct { baseAny val int32 } func (any *int32Any) LastError() error { return nil } func (any *int32Any) ValueType() ValueType { return NumberValue } func (any *int32Any) MustBeValid() Any { return any } func (any *int32Any) ToBool() bool { return any.val != 0 } func (any *int32Any) ToInt() int { return int(any.val) } func (any *int32Any) ToInt32() int32 { return any.val } func (any *int32Any) ToInt64() int64 { return int64(any.val) } func (any *int32Any) ToUint() uint { return uint(any.val) } func (any *int32Any) ToUint32() uint32 { return uint32(any.val) } func (any *int32Any) ToUint64() uint64 { return uint64(any.val) } func (any *int32Any) ToFloat32() float32 { return float32(any.val) } func (any *int32Any) ToFloat64() float64 { return float64(any.val) } func (any *int32Any) ToString() string { return strconv.FormatInt(int64(any.val), 10) } func (any *int32Any) WriteTo(stream *Stream) { stream.WriteInt32(any.val) } func (any *int32Any) Parse() *Iterator { return nil } func (any *int32Any) GetInterface() interface{} { return any.val }
package jsoniter import ( "strconv" ) type int64Any struct { baseAny val int64 } func (any *int64Any) LastError() error { return nil } func (any *int64Any) ValueType() ValueType { return NumberValue } func (any *int64Any) MustBeValid() Any { return any } func (any *int64Any) ToBool() bool { return any.val != 0 } func (any *int64Any) ToInt() int { return int(any.val) } func (any *int64Any) ToInt32() int32 { return int32(any.val) } func (any *int64Any) ToInt64() int64 { return any.val } func (any *int64Any) ToUint() uint { return uint(any.val) } func (any *int64Any) ToUint32() uint32 { return uint32(any.val) } func (any *int64Any) ToUint64() uint64 { return uint64(any.val) } func (any *int64Any) ToFloat32() float32 { return float32(any.val) } func (any *int64Any) ToFloat64() float64 { return float64(any.val) } func (any *int64Any) ToString() string { return strconv.FormatInt(any.val, 10) } func (any *int64Any) WriteTo(stream *Stream) { stream.WriteInt64(any.val) } func (any *int64Any) Parse() *Iterator { return nil } func (any *int64Any) GetInterface() interface{} { return any.val }
package jsoniter import "fmt" type invalidAny struct { baseAny err error } func newInvalidAny(path []interface{}) *invalidAny { return &invalidAny{baseAny{}, fmt.Errorf("%v not found", path)} } func (any *invalidAny) LastError() error { return any.err } func (any *invalidAny) ValueType() ValueType { return InvalidValue } func (any *invalidAny) MustBeValid() Any { panic(any.err) } func (any *invalidAny) ToBool() bool { return false } func (any *invalidAny) ToInt() int { return 0 } func (any *invalidAny) ToInt32() int32 { return 0 } func (any *invalidAny) ToInt64() int64 { return 0 } func (any *invalidAny) ToUint() uint { return 0 } func (any *invalidAny) ToUint32() uint32 { return 0 } func (any *invalidAny) ToUint64() uint64 { return 0 } func (any *invalidAny) ToFloat32() float32 { return 0 } func (any *invalidAny) ToFloat64() float64 { return 0 } func (any *invalidAny) ToString() string { return "" } func (any *invalidAny) WriteTo(stream *Stream) { } func (any *invalidAny) Get(path ...interface{}) Any { if any.err == nil { return &invalidAny{baseAny{}, fmt.Errorf("get %v from invalid", path)} } return &invalidAny{baseAny{}, fmt.Errorf("%v, get %v from invalid", any.err, path)} } func (any *invalidAny) Parse() *Iterator { return nil } func (any *invalidAny) GetInterface() interface{} { return nil }
package jsoniter type nilAny struct { baseAny } func (any *nilAny) LastError() error { return nil } func (any *nilAny) ValueType() ValueType { return NilValue } func (any *nilAny) MustBeValid() Any { return any } func (any *nilAny) ToBool() bool { return false } func (any *nilAny) ToInt() int { return 0 } func (any *nilAny) ToInt32() int32 { return 0 } func (any *nilAny) ToInt64() int64 { return 0 } func (any *nilAny) ToUint() uint { return 0 } func (any *nilAny) ToUint32() uint32 { return 0 } func (any *nilAny) ToUint64() uint64 { return 0 } func (any *nilAny) ToFloat32() float32 { return 0 } func (any *nilAny) ToFloat64() float64 { return 0 } func (any *nilAny) ToString() string { return "" } func (any *nilAny) WriteTo(stream *Stream) { stream.WriteNil() } func (any *nilAny) Parse() *Iterator { return nil } func (any *nilAny) GetInterface() interface{} { return nil }
package jsoniter import ( "io" "unsafe" ) type numberLazyAny struct { baseAny cfg *frozenConfig buf []byte err error } func (any *numberLazyAny) ValueType() ValueType { return NumberValue } func (any *numberLazyAny) MustBeValid() Any { return any } func (any *numberLazyAny) LastError() error { return any.err } func (any *numberLazyAny) ToBool() bool { return any.ToFloat64() != 0 } func (any *numberLazyAny) ToInt() int { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadInt() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToInt32() int32 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadInt32() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToInt64() int64 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadInt64() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToUint() uint { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadUint() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToUint32() uint32 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadUint32() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToUint64() uint64 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadUint64() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToFloat32() float32 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadFloat32() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToFloat64() float64 { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) val := iter.ReadFloat64() if iter.Error != nil && iter.Error != io.EOF { any.err = iter.Error } return val } func (any *numberLazyAny) ToString() string { return *(*string)(unsafe.Pointer(&any.buf)) } func (any *numberLazyAny) WriteTo(stream *Stream) { stream.Write(any.buf) } func (any *numberLazyAny) GetInterface() interface{} { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) return iter.Read() }
package jsoniter import ( "reflect" "unsafe" ) type objectLazyAny struct { baseAny cfg *frozenConfig buf []byte err error } func (any *objectLazyAny) ValueType() ValueType { return ObjectValue } func (any *objectLazyAny) MustBeValid() Any { return any } func (any *objectLazyAny) LastError() error { return any.err } func (any *objectLazyAny) ToBool() bool { return true } func (any *objectLazyAny) ToInt() int { return 0 } func (any *objectLazyAny) ToInt32() int32 { return 0 } func (any *objectLazyAny) ToInt64() int64 { return 0 } func (any *objectLazyAny) ToUint() uint { return 0 } func (any *objectLazyAny) ToUint32() uint32 { return 0 } func (any *objectLazyAny) ToUint64() uint64 { return 0 } func (any *objectLazyAny) ToFloat32() float32 { return 0 } func (any *objectLazyAny) ToFloat64() float64 { return 0 } func (any *objectLazyAny) ToString() string { return *(*string)(unsafe.Pointer(&any.buf)) } func (any *objectLazyAny) ToVal(obj interface{}) { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) iter.ReadVal(obj) } func (any *objectLazyAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } switch firstPath := path[0].(type) { case string: iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) valueBytes := locateObjectField(iter, firstPath) if valueBytes == nil { return newInvalidAny(path) } iter.ResetBytes(valueBytes) return locatePath(iter, path[1:]) case int32: if '*' == firstPath { mappedAll := map[string]Any{} iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) iter.ReadMapCB(func(iter *Iterator, field string) bool { mapped := locatePath(iter, path[1:]) if mapped.ValueType() != InvalidValue { mappedAll[field] = mapped } return true }) return wrapMap(mappedAll) } return newInvalidAny(path) default: return newInvalidAny(path) } } func (any *objectLazyAny) Keys() []string { keys := []string{} iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) iter.ReadMapCB(func(iter *Iterator, field string) bool { iter.Skip() keys = append(keys, field) return true }) return keys } func (any *objectLazyAny) Size() int { 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) WriteTo(stream *Stream) { stream.Write(any.buf) } func (any *objectLazyAny) GetInterface() interface{} { iter := any.cfg.BorrowIterator(any.buf) defer any.cfg.ReturnIterator(iter) return iter.Read() } type objectAny struct { baseAny err error val reflect.Value } func wrapStruct(val interface{}) *objectAny { return &objectAny{baseAny{}, nil, reflect.ValueOf(val)} } func (any *objectAny) ValueType() ValueType { return ObjectValue } func (any *objectAny) MustBeValid() Any { return any } func (any *objectAny) Parse() *Iterator { return nil } func (any *objectAny) LastError() error { return any.err } func (any *objectAny) ToBool() bool { return any.val.NumField() != 0 } func (any *objectAny) ToInt() int { return 0 } func (any *objectAny) ToInt32() int32 { return 0 } func (any *objectAny) ToInt64() int64 { return 0 } func (any *objectAny) ToUint() uint { return 0 } func (any *objectAny) ToUint32() uint32 { return 0 } func (any *objectAny) ToUint64() uint64 { return 0 } func (any *objectAny) ToFloat32() float32 { return 0 } func (any *objectAny) ToFloat64() float64 { return 0 } func (any *objectAny) ToString() string { str, err := MarshalToString(any.val.Interface()) any.err = err return str } func (any *objectAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } switch firstPath := path[0].(type) { case string: field := any.val.FieldByName(firstPath) if !field.IsValid() { return newInvalidAny(path) } return Wrap(field.Interface()) case int32: if '*' == firstPath { mappedAll := map[string]Any{} for i := 0; i < any.val.NumField(); i++ { field := any.val.Field(i) if field.CanInterface() { mapped := Wrap(field.Interface()).Get(path[1:]...) if mapped.ValueType() != InvalidValue { mappedAll[any.val.Type().Field(i).Name] = mapped } } } return wrapMap(mappedAll) } return newInvalidAny(path) default: return newInvalidAny(path) } } func (any *objectAny) Keys() []string { keys := make([]string, 0, any.val.NumField()) for i := 0; i < any.val.NumField(); i++ { keys = append(keys, any.val.Type().Field(i).Name) } return keys } func (any *objectAny) Size() int { return any.val.NumField() } func (any *objectAny) WriteTo(stream *Stream) { stream.WriteVal(any.val) } func (any *objectAny) GetInterface() interface{} { return any.val.Interface() } type mapAny struct { baseAny err error val reflect.Value } func wrapMap(val interface{}) *mapAny { return &mapAny{baseAny{}, nil, reflect.ValueOf(val)} } func (any *mapAny) ValueType() ValueType { return ObjectValue } func (any *mapAny) MustBeValid() Any { return any } func (any *mapAny) Parse() *Iterator { return nil } func (any *mapAny) LastError() error { return any.err } func (any *mapAny) ToBool() bool { return true } func (any *mapAny) ToInt() int { return 0 } func (any *mapAny) ToInt32() int32 { return 0 } func (any *mapAny) ToInt64() int64 { return 0 } func (any *mapAny) ToUint() uint { return 0 } func (any *mapAny) ToUint32() uint32 { return 0 } func (any *mapAny) ToUint64() uint64 { return 0 } func (any *mapAny) ToFloat32() float32 { return 0 } func (any *mapAny) ToFloat64() float64 { return 0 } func (any *mapAny) ToString() string { str, err := MarshalToString(any.val.Interface()) any.err = err return str } func (any *mapAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } switch firstPath := path[0].(type) { case int32: if '*' == firstPath { mappedAll := map[string]Any{} for _, key := range any.val.MapKeys() { keyAsStr := key.String() element := Wrap(any.val.MapIndex(key).Interface()) mapped := element.Get(path[1:]...) if mapped.ValueType() != InvalidValue { mappedAll[keyAsStr] = mapped } } return wrapMap(mappedAll) } return newInvalidAny(path) default: value := any.val.MapIndex(reflect.ValueOf(firstPath)) if !value.IsValid() { return newInvalidAny(path) } return Wrap(value.Interface()) } } func (any *mapAny) Keys() []string { keys := make([]string, 0, any.val.Len()) for _, key := range any.val.MapKeys() { keys = append(keys, key.String()) } return keys } func (any *mapAny) Size() int { return any.val.Len() } func (any *mapAny) WriteTo(stream *Stream) { stream.WriteVal(any.val) } func (any *mapAny) GetInterface() interface{} { return any.val.Interface() }
package jsoniter import ( "fmt" "strconv" ) type stringAny struct { baseAny val string } func (any *stringAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} } func (any *stringAny) Parse() *Iterator { return nil } func (any *stringAny) ValueType() ValueType { return StringValue } func (any *stringAny) MustBeValid() Any { return any } func (any *stringAny) LastError() error { return nil } func (any *stringAny) ToBool() bool { str := any.ToString() if str == "0" { return false } for _, c := range str { switch c { case ' ', '\n', '\r', '\t': default: return true } } return false } func (any *stringAny) ToInt() int { return int(any.ToInt64()) } func (any *stringAny) ToInt32() int32 { return int32(any.ToInt64()) } func (any *stringAny) ToInt64() int64 { if any.val == "" { return 0 } flag := 1 startPos := 0 if any.val[0] == '+' || any.val[0] == '-' { startPos = 1 } if any.val[0] == '-' { flag = -1 } endPos := startPos for i := startPos; i < len(any.val); i++ { if any.val[i] >= '0' && any.val[i] <= '9' { endPos = i + 1 } else { break } } parsed, _ := strconv.ParseInt(any.val[startPos:endPos], 10, 64) return int64(flag) * parsed } func (any *stringAny) ToUint() uint { return uint(any.ToUint64()) } func (any *stringAny) ToUint32() uint32 { return uint32(any.ToUint64()) } func (any *stringAny) ToUint64() uint64 { if any.val == "" { return 0 } startPos := 0 if any.val[0] == '-' { return 0 } if any.val[0] == '+' { startPos = 1 } endPos := startPos for i := startPos; i < len(any.val); i++ { if any.val[i] >= '0' && any.val[i] <= '9' { endPos = i + 1 } else { break } } parsed, _ := strconv.ParseUint(any.val[startPos:endPos], 10, 64) return parsed } func (any *stringAny) ToFloat32() float32 { return float32(any.ToFloat64()) } func (any *stringAny) ToFloat64() float64 { if len(any.val) == 0 { return 0 } // first char invalid if any.val[0] != '+' && any.val[0] != '-' && (any.val[0] > '9' || any.val[0] < '0') { return 0 } // extract valid num expression from string // eg 123true => 123, -12.12xxa => -12.12 endPos := 1 for i := 1; i < len(any.val); i++ { if any.val[i] == '.' || any.val[i] == 'e' || any.val[i] == 'E' || any.val[i] == '+' || any.val[i] == '-' { endPos = i + 1 continue } // end position is the first char which is not digit if any.val[i] >= '0' && any.val[i] <= '9' { endPos = i + 1 } else { endPos = i break } } parsed, _ := strconv.ParseFloat(any.val[:endPos], 64) return parsed } func (any *stringAny) ToString() string { return any.val } func (any *stringAny) WriteTo(stream *Stream) { stream.WriteString(any.val) } func (any *stringAny) GetInterface() interface{} { return any.val }
package jsoniter import ( "strconv" ) type uint32Any struct { baseAny val uint32 } func (any *uint32Any) LastError() error { return nil } func (any *uint32Any) ValueType() ValueType { return NumberValue } func (any *uint32Any) MustBeValid() Any { return any } func (any *uint32Any) ToBool() bool { return any.val != 0 } func (any *uint32Any) ToInt() int { return int(any.val) } func (any *uint32Any) ToInt32() int32 { return int32(any.val) } func (any *uint32Any) ToInt64() int64 { return int64(any.val) } func (any *uint32Any) ToUint() uint { return uint(any.val) } func (any *uint32Any) ToUint32() uint32 { return any.val } func (any *uint32Any) ToUint64() uint64 { return uint64(any.val) } func (any *uint32Any) ToFloat32() float32 { return float32(any.val) } func (any *uint32Any) ToFloat64() float64 { return float64(any.val) } func (any *uint32Any) ToString() string { return strconv.FormatInt(int64(any.val), 10) } func (any *uint32Any) WriteTo(stream *Stream) { stream.WriteUint32(any.val) } func (any *uint32Any) Parse() *Iterator { return nil } func (any *uint32Any) GetInterface() interface{} { return any.val }
package jsoniter import ( "strconv" ) type uint64Any struct { baseAny val uint64 } func (any *uint64Any) LastError() error { return nil } func (any *uint64Any) ValueType() ValueType { return NumberValue } func (any *uint64Any) MustBeValid() Any { return any } func (any *uint64Any) ToBool() bool { return any.val != 0 } func (any *uint64Any) ToInt() int { return int(any.val) } func (any *uint64Any) ToInt32() int32 { return int32(any.val) } func (any *uint64Any) ToInt64() int64 { return int64(any.val) } func (any *uint64Any) ToUint() uint { return uint(any.val) } func (any *uint64Any) ToUint32() uint32 { return uint32(any.val) } func (any *uint64Any) ToUint64() uint64 { return any.val } func (any *uint64Any) ToFloat32() float32 { return float32(any.val) } func (any *uint64Any) ToFloat64() float64 { return float64(any.val) } func (any *uint64Any) ToString() string { return strconv.FormatUint(any.val, 10) } func (any *uint64Any) WriteTo(stream *Stream) { stream.WriteUint64(any.val) } func (any *uint64Any) Parse() *Iterator { return nil } func (any *uint64Any) GetInterface() interface{} { return any.val }
package jsoniter import ( "encoding/json" "io" "reflect" "sync" "unsafe" "github.com/modern-go/concurrent" "github.com/modern-go/reflect2" ) // Config customize how the API should behave. // The API is created from Config by Froze. type Config struct { IndentionStep int MarshalFloatWith6Digits bool EscapeHTML bool SortMapKeys bool UseNumber bool DisallowUnknownFields bool TagKey string OnlyTaggedField bool ValidateJsonRawMessage bool ObjectFieldMustBeSimpleString bool CaseSensitive bool } // API the public interface of this package. // Primary Marshal and Unmarshal. type API interface { IteratorPool StreamPool MarshalToString(v interface{}) (string, error) Marshal(v interface{}) ([]byte, error) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) UnmarshalFromString(str string, v interface{}) error Unmarshal(data []byte, v interface{}) error Get(data []byte, path ...interface{}) Any NewEncoder(writer io.Writer) *Encoder NewDecoder(reader io.Reader) *Decoder Valid(data []byte) bool RegisterExtension(extension Extension) DecoderOf(typ reflect2.Type) ValDecoder EncoderOf(typ reflect2.Type) ValEncoder } // ConfigDefault the default API var ConfigDefault = Config{ EscapeHTML: true, }.Froze() // ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior var ConfigCompatibleWithStandardLibrary = Config{ EscapeHTML: true, SortMapKeys: true, ValidateJsonRawMessage: true, }.Froze() // ConfigFastest marshals float with only 6 digits precision var ConfigFastest = Config{ EscapeHTML: false, MarshalFloatWith6Digits: true, // will lose precession ObjectFieldMustBeSimpleString: true, // do not unescape object field }.Froze() type frozenConfig struct { configBeforeFrozen Config sortMapKeys bool indentionStep int objectFieldMustBeSimpleString bool onlyTaggedField bool disallowUnknownFields bool decoderCache *concurrent.Map encoderCache *concurrent.Map encoderExtension Extension decoderExtension Extension extraExtensions []Extension streamPool *sync.Pool iteratorPool *sync.Pool caseSensitive bool } func (cfg *frozenConfig) initCache() { cfg.decoderCache = concurrent.NewMap() cfg.encoderCache = concurrent.NewMap() } func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) { cfg.decoderCache.Store(cacheKey, decoder) } func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) { cfg.encoderCache.Store(cacheKey, encoder) } func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder { decoder, found := cfg.decoderCache.Load(cacheKey) if found { return decoder.(ValDecoder) } return nil } func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder { encoder, found := cfg.encoderCache.Load(cacheKey) if found { return encoder.(ValEncoder) } return nil } var cfgCache = concurrent.NewMap() func getFrozenConfigFromCache(cfg Config) *frozenConfig { obj, found := cfgCache.Load(cfg) if found { return obj.(*frozenConfig) } return nil } func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) { cfgCache.Store(cfg, frozenConfig) } // Froze forge API from config func (cfg Config) Froze() API { api := &frozenConfig{ sortMapKeys: cfg.SortMapKeys, indentionStep: cfg.IndentionStep, objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString, onlyTaggedField: cfg.OnlyTaggedField, disallowUnknownFields: cfg.DisallowUnknownFields, caseSensitive: cfg.CaseSensitive, } api.streamPool = &sync.Pool{ New: func() interface{} { return NewStream(api, nil, 512) }, } api.iteratorPool = &sync.Pool{ New: func() interface{} { return NewIterator(api) }, } api.initCache() encoderExtension := EncoderExtension{} decoderExtension := DecoderExtension{} if cfg.MarshalFloatWith6Digits { api.marshalFloatWith6Digits(encoderExtension) } if cfg.EscapeHTML { api.escapeHTML(encoderExtension) } if cfg.UseNumber { api.useNumber(decoderExtension) } if cfg.ValidateJsonRawMessage { api.validateJsonRawMessage(encoderExtension) } api.encoderExtension = encoderExtension api.decoderExtension = decoderExtension api.configBeforeFrozen = cfg return api } func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig { api := getFrozenConfigFromCache(cfg) if api != nil { return api } api = cfg.Froze().(*frozenConfig) for _, extension := range extraExtensions { api.RegisterExtension(extension) } addFrozenConfigToCache(cfg, api) return api } func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) { encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) { rawMessage := *(*json.RawMessage)(ptr) iter := cfg.BorrowIterator([]byte(rawMessage)) defer cfg.ReturnIterator(iter) iter.Read() if iter.Error != nil && iter.Error != io.EOF { stream.WriteRaw("null") } else { stream.WriteRaw(string(rawMessage)) } }, func(ptr unsafe.Pointer) bool { return len(*((*json.RawMessage)(ptr))) == 0 }} extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder } func (cfg *frozenConfig) useNumber(extension DecoderExtension) { extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) { exitingValue := *((*interface{})(ptr)) if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr { iter.ReadVal(exitingValue) return } if iter.WhatIsNext() == NumberValue { *((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) } else { *((*interface{})(ptr)) = iter.Read() } }} } func (cfg *frozenConfig) getTagKey() string { tagKey := cfg.configBeforeFrozen.TagKey if tagKey == "" { return "json" } return tagKey } func (cfg *frozenConfig) RegisterExtension(extension Extension) { cfg.extraExtensions = append(cfg.extraExtensions, extension) copied := cfg.configBeforeFrozen cfg.configBeforeFrozen = copied } type lossyFloat32Encoder struct { } func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteFloat32Lossy(*((*float32)(ptr))) } func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool { return *((*float32)(ptr)) == 0 } type lossyFloat64Encoder struct { } func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteFloat64Lossy(*((*float64)(ptr))) } func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool { return *((*float64)(ptr)) == 0 } // EnableLossyFloatMarshalling keeps 10**(-6) precision // for float variables for better performance. func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) { // for better performance extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{} extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{} } type htmlEscapedStringEncoder struct { } func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { str := *((*string)(ptr)) stream.WriteStringWithHTMLEscaped(str) } func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { return *((*string)(ptr)) == "" } func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) { encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{} } func (cfg *frozenConfig) cleanDecoders() { typeDecoders = map[string]ValDecoder{} fieldDecoders = map[string]ValDecoder{} *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) } func (cfg *frozenConfig) cleanEncoders() { typeEncoders = map[string]ValEncoder{} fieldEncoders = map[string]ValEncoder{} *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) } func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) { stream := cfg.BorrowStream(nil) defer cfg.ReturnStream(stream) stream.WriteVal(v) if stream.Error != nil { return "", stream.Error } return string(stream.Buffer()), nil } func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) { stream := cfg.BorrowStream(nil) defer cfg.ReturnStream(stream) stream.WriteVal(v) if stream.Error != nil { return nil, stream.Error } result := stream.Buffer() copied := make([]byte, len(result)) copy(copied, result) return copied, nil } func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { if prefix != "" { panic("prefix is not supported") } for _, r := range indent { if r != ' ' { panic("indent can only be space") } } newCfg := cfg.configBeforeFrozen newCfg.IndentionStep = len(indent) return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v) } func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error { data := []byte(str) iter := cfg.BorrowIterator(data) defer cfg.ReturnIterator(iter) iter.ReadVal(v) c := iter.nextToken() if c == 0 { if iter.Error == io.EOF { return nil } return iter.Error } iter.ReportError("Unmarshal", "there are bytes left after unmarshal") return iter.Error } func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any { iter := cfg.BorrowIterator(data) defer cfg.ReturnIterator(iter) return locatePath(iter, path) } func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error { iter := cfg.BorrowIterator(data) defer cfg.ReturnIterator(iter) iter.ReadVal(v) c := iter.nextToken() if c == 0 { if iter.Error == io.EOF { return nil } return iter.Error } iter.ReportError("Unmarshal", "there are bytes left after unmarshal") return iter.Error } func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder { stream := NewStream(cfg, writer, 512) return &Encoder{stream} } func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder { iter := Parse(cfg, reader, 512) return &Decoder{iter} } func (cfg *frozenConfig) Valid(data []byte) bool { iter := cfg.BorrowIterator(data) defer cfg.ReturnIterator(iter) iter.Skip() return iter.Error == nil }
// Copyright 2015 go-fuzz project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE. // Modified from original file https://github.com/dvyukov/go-fuzz-corpus/blob/master/json/json.go package jsoniter import ( "encoding/json" "fmt" "reflect" ) func Fuzz(data []byte) int { score := 0 for _, ctor := range []func() interface{}{ //func() interface{} { return nil }, func() interface{} { return new([]interface{}) }, func() interface{} { m := map[string]string{}; return &m }, func() interface{} { m := map[string]interface{}{}; return &m }, func() interface{} { return new(S) }, } { v := ctor() if ConfigCompatibleWithStandardLibrary.Unmarshal(data, v) != nil { continue } score = 1 vj := ctor() err := json.Unmarshal(data, vj) if err != nil { panic(err) } if !reflect.DeepEqual(v, vj) { fmt.Printf("v0: %#v\n", v) fmt.Printf("v1: %#v\n", vj) panic("not equal") } data1, err := ConfigCompatibleWithStandardLibrary.Marshal(v) if err != nil { panic(err) } v1 := ctor() if ConfigCompatibleWithStandardLibrary.Unmarshal(data1, v1) != nil { continue } if !reflect.DeepEqual(v, v1) { fmt.Printf("v0: %#v\n", v) fmt.Printf("v1: %#v\n", v1) panic("not equal") } } return score } type S struct { A int `json:",omitempty"` B string `json:"B1,omitempty"` C float64 D bool E uint8 F []byte G interface{} H map[string]interface{} I map[string]string J []interface{} K []string L S1 M *S1 N *int O **int // P json.RawMessage Q Marshaller R int `json:"-"` S int `json:",string"` } type S1 struct { A int B string } type Marshaller struct { v string } func (m *Marshaller) MarshalJSON() ([]byte, error) { return ConfigCompatibleWithStandardLibrary.Marshal(m.v) } func (m *Marshaller) UnmarshalJSON(data []byte) error { return ConfigCompatibleWithStandardLibrary.Unmarshal(data, &m.v) }
package jsoniter import ( "encoding/json" "fmt" "io" ) // ValueType the type for JSON element type ValueType int const ( // InvalidValue invalid JSON element InvalidValue ValueType = iota // StringValue JSON element "string" StringValue // NumberValue JSON element 100 or 0.10 NumberValue // NilValue JSON element null NilValue // BoolValue JSON element true or false BoolValue // ArrayValue JSON element [] ArrayValue // ObjectValue JSON element {} ObjectValue ) var hexDigits []byte var valueTypes []ValueType func init() { hexDigits = make([]byte, 256) for i := 0; i < len(hexDigits); i++ { hexDigits[i] = 255 } for i := '0'; i <= '9'; i++ { hexDigits[i] = byte(i - '0') } for i := 'a'; i <= 'f'; i++ { hexDigits[i] = byte((i - 'a') + 10) } for i := 'A'; i <= 'F'; i++ { hexDigits[i] = byte((i - 'A') + 10) } valueTypes = make([]ValueType, 256) for i := 0; i < len(valueTypes); i++ { valueTypes[i] = InvalidValue } valueTypes['"'] = StringValue valueTypes['-'] = NumberValue valueTypes['0'] = NumberValue valueTypes['1'] = NumberValue valueTypes['2'] = NumberValue valueTypes['3'] = NumberValue valueTypes['4'] = NumberValue valueTypes['5'] = NumberValue valueTypes['6'] = NumberValue valueTypes['7'] = NumberValue valueTypes['8'] = NumberValue valueTypes['9'] = NumberValue valueTypes['t'] = BoolValue valueTypes['f'] = BoolValue valueTypes['n'] = NilValue valueTypes['['] = ArrayValue valueTypes['{'] = ObjectValue } // Iterator is a io.Reader like object, with JSON specific read functions. // Error is not returned as return value, but stored as Error member on this iterator instance. type Iterator struct { cfg *frozenConfig reader io.Reader buf []byte head int tail int depth int captureStartedAt int captured []byte Error error Attachment interface{} // open for customized decoder } // NewIterator creates an empty Iterator instance func NewIterator(cfg API) *Iterator { return &Iterator{ cfg: cfg.(*frozenConfig), reader: nil, buf: nil, head: 0, tail: 0, depth: 0, } } // Parse creates an Iterator instance from io.Reader func Parse(cfg API, reader io.Reader, bufSize int) *Iterator { return &Iterator{ cfg: cfg.(*frozenConfig), reader: reader, buf: make([]byte, bufSize), head: 0, tail: 0, depth: 0, } } // ParseBytes creates an Iterator instance from byte array func ParseBytes(cfg API, input []byte) *Iterator { return &Iterator{ cfg: cfg.(*frozenConfig), reader: nil, buf: input, head: 0, tail: len(input), depth: 0, } } // ParseString creates an Iterator instance from string func ParseString(cfg API, input string) *Iterator { return ParseBytes(cfg, []byte(input)) } // Pool returns a pool can provide more iterator with same configuration func (iter *Iterator) Pool() IteratorPool { return iter.cfg } // Reset reuse iterator instance by specifying another reader func (iter *Iterator) Reset(reader io.Reader) *Iterator { iter.reader = reader iter.head = 0 iter.tail = 0 iter.depth = 0 return iter } // ResetBytes reuse iterator instance by specifying another byte array as input func (iter *Iterator) ResetBytes(input []byte) *Iterator { iter.reader = nil iter.buf = input iter.head = 0 iter.tail = len(input) iter.depth = 0 return iter } // WhatIsNext gets ValueType of relatively next json element func (iter *Iterator) WhatIsNext() ValueType { valueType := valueTypes[iter.nextToken()] iter.unreadByte() return valueType } func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool { for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] switch c { case ' ', '\n', '\t', '\r': continue } iter.head = i return false } return true } func (iter *Iterator) isObjectEnd() bool { c := iter.nextToken() if c == ',' { return false } if c == '}' { return true } iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c})) return true } func (iter *Iterator) nextToken() byte { // a variation of skip whitespaces, returning the next non-whitespace token for { for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] switch c { case ' ', '\n', '\t', '\r': continue } iter.head = i + 1 return c } if !iter.loadMore() { return 0 } } } // ReportError record a error in iterator instance with current position. func (iter *Iterator) ReportError(operation string, msg string) { if iter.Error != nil { if iter.Error != io.EOF { return } } peekStart := iter.head - 10 if peekStart < 0 { peekStart = 0 } peekEnd := iter.head + 10 if peekEnd > iter.tail { peekEnd = iter.tail } parsing := string(iter.buf[peekStart:peekEnd]) contextStart := iter.head - 50 if contextStart < 0 { contextStart = 0 } contextEnd := iter.head + 50 if contextEnd > iter.tail { contextEnd = iter.tail } context := string(iter.buf[contextStart:contextEnd]) iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...", operation, msg, iter.head-peekStart, parsing, context) } // CurrentBuffer gets current buffer as string for debugging purpose func (iter *Iterator) CurrentBuffer() string { peekStart := iter.head - 10 if peekStart < 0 { peekStart = 0 } return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head, string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) } func (iter *Iterator) readByte() (ret byte) { if iter.head == iter.tail { if iter.loadMore() { ret = iter.buf[iter.head] iter.head++ return ret } return 0 } ret = iter.buf[iter.head] iter.head++ return ret } func (iter *Iterator) loadMore() bool { if iter.reader == nil { if iter.Error == nil { iter.head = iter.tail iter.Error = io.EOF } return false } if iter.captured != nil { iter.captured = append(iter.captured, iter.buf[iter.captureStartedAt:iter.tail]...) iter.captureStartedAt = 0 } for { n, err := iter.reader.Read(iter.buf) if n == 0 { if err != nil { if iter.Error == nil { iter.Error = err } return false } } else { iter.head = 0 iter.tail = n return true } } } func (iter *Iterator) unreadByte() { if iter.Error != nil { return } iter.head-- return } // Read read the next JSON element as generic interface{}. func (iter *Iterator) Read() interface{} { valueType := iter.WhatIsNext() switch valueType { case StringValue: return iter.ReadString() case NumberValue: if iter.cfg.configBeforeFrozen.UseNumber { return json.Number(iter.readNumberAsString()) } return iter.ReadFloat64() case NilValue: iter.skipFourBytes('n', 'u', 'l', 'l') return nil case BoolValue: return iter.ReadBool() case ArrayValue: arr := []interface{}{} iter.ReadArrayCB(func(iter *Iterator) bool { var elem interface{} iter.ReadVal(&elem) arr = append(arr, elem) return true }) return arr case ObjectValue: obj := map[string]interface{}{} iter.ReadMapCB(func(Iter *Iterator, field string) bool { var elem interface{} iter.ReadVal(&elem) obj[field] = elem return true }) return obj default: iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType)) return nil } } // limit maximum depth of nesting, as allowed by https://tools.ietf.org/html/rfc7159#section-9 const maxDepth = 10000 func (iter *Iterator) incrementDepth() (success bool) { iter.depth++ if iter.depth <= maxDepth { return true } iter.ReportError("incrementDepth", "exceeded max depth") return false } func (iter *Iterator) decrementDepth() (success bool) { iter.depth-- if iter.depth >= 0 { return true } iter.ReportError("decrementDepth", "unexpected negative nesting") return false }
package jsoniter // ReadArray read array element, tells if the array has more element to read. func (iter *Iterator) ReadArray() (ret bool) { c := iter.nextToken() switch c { case 'n': iter.skipThreeBytes('u', 'l', 'l') return false // null case '[': c = iter.nextToken() if c != ']' { iter.unreadByte() return true } return false case ']': return false case ',': return true default: iter.ReportError("ReadArray", "expect [ or , or ] or n, but found "+string([]byte{c})) return } } // ReadArrayCB read array with callback func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) { c := iter.nextToken() if c == '[' { if !iter.incrementDepth() { return false } c = iter.nextToken() if c != ']' { iter.unreadByte() if !callback(iter) { iter.decrementDepth() return false } c = iter.nextToken() for c == ',' { if !callback(iter) { iter.decrementDepth() return false } c = iter.nextToken() } if c != ']' { iter.ReportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c})) iter.decrementDepth() return false } return iter.decrementDepth() } return iter.decrementDepth() } if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return true // null } iter.ReportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c})) return false }
package jsoniter import ( "encoding/json" "io" "math/big" "strconv" "strings" "unsafe" ) var floatDigits []int8 const invalidCharForNumber = int8(-1) const endOfNumber = int8(-2) const dotInNumber = int8(-3) func init() { floatDigits = make([]int8, 256) for i := 0; i < len(floatDigits); i++ { floatDigits[i] = invalidCharForNumber } for i := int8('0'); i <= int8('9'); i++ { floatDigits[i] = i - int8('0') } floatDigits[','] = endOfNumber floatDigits[']'] = endOfNumber floatDigits['}'] = endOfNumber floatDigits[' '] = endOfNumber floatDigits['\t'] = endOfNumber floatDigits['\n'] = endOfNumber floatDigits['.'] = dotInNumber } // ReadBigFloat read big.Float func (iter *Iterator) ReadBigFloat() (ret *big.Float) { str := iter.readNumberAsString() if iter.Error != nil && iter.Error != io.EOF { return nil } prec := 64 if len(str) > prec { prec = len(str) } val, _, err := big.ParseFloat(str, 10, uint(prec), big.ToZero) if err != nil { iter.Error = err return nil } return val } // ReadBigInt read big.Int func (iter *Iterator) ReadBigInt() (ret *big.Int) { str := iter.readNumberAsString() if iter.Error != nil && iter.Error != io.EOF { return nil } ret = big.NewInt(0) var success bool ret, success = ret.SetString(str, 10) if !success { iter.ReportError("ReadBigInt", "invalid big int") return nil } return ret } //ReadFloat32 read float32 func (iter *Iterator) ReadFloat32() (ret float32) { c := iter.nextToken() if c == '-' { return -iter.readPositiveFloat32() } iter.unreadByte() return iter.readPositiveFloat32() } func (iter *Iterator) readPositiveFloat32() (ret float32) { i := iter.head // first char if i == iter.tail { return iter.readFloat32SlowPath() } c := iter.buf[i] i++ ind := floatDigits[c] switch ind { case invalidCharForNumber: return iter.readFloat32SlowPath() case endOfNumber: iter.ReportError("readFloat32", "empty number") return case dotInNumber: iter.ReportError("readFloat32", "leading dot is invalid") return case 0: if i == iter.tail { return iter.readFloat32SlowPath() } c = iter.buf[i] switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': iter.ReportError("readFloat32", "leading zero is invalid") return } } value := uint64(ind) // chars before dot non_decimal_loop: for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] switch ind { case invalidCharForNumber: return iter.readFloat32SlowPath() case endOfNumber: iter.head = i return float32(value) case dotInNumber: break non_decimal_loop } if value > uint64SafeToMultiple10 { return iter.readFloat32SlowPath() } value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; } // chars after dot if c == '.' { i++ decimalPlaces := 0 if i == iter.tail { return iter.readFloat32SlowPath() } for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] switch ind { case endOfNumber: if decimalPlaces > 0 && decimalPlaces < len(pow10) { iter.head = i return float32(float64(value) / float64(pow10[decimalPlaces])) } // too many decimal places return iter.readFloat32SlowPath() case invalidCharForNumber, dotInNumber: return iter.readFloat32SlowPath() } decimalPlaces++ if value > uint64SafeToMultiple10 { return iter.readFloat32SlowPath() } value = (value << 3) + (value << 1) + uint64(ind) } } return iter.readFloat32SlowPath() } func (iter *Iterator) readNumberAsString() (ret string) { strBuf := [16]byte{} str := strBuf[0:0] load_loop: for { for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] switch c { case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': str = append(str, c) continue default: iter.head = i break load_loop } } if !iter.loadMore() { break } } if iter.Error != nil && iter.Error != io.EOF { return } if len(str) == 0 { iter.ReportError("readNumberAsString", "invalid number") } return *(*string)(unsafe.Pointer(&str)) } func (iter *Iterator) readFloat32SlowPath() (ret float32) { str := iter.readNumberAsString() if iter.Error != nil && iter.Error != io.EOF { return } errMsg := validateFloat(str) if errMsg != "" { iter.ReportError("readFloat32SlowPath", errMsg) return } val, err := strconv.ParseFloat(str, 32) if err != nil { iter.Error = err return } return float32(val) } // ReadFloat64 read float64 func (iter *Iterator) ReadFloat64() (ret float64) { c := iter.nextToken() if c == '-' { return -iter.readPositiveFloat64() } iter.unreadByte() return iter.readPositiveFloat64() } func (iter *Iterator) readPositiveFloat64() (ret float64) { i := iter.head // first char if i == iter.tail { return iter.readFloat64SlowPath() } c := iter.buf[i] i++ ind := floatDigits[c] switch ind { case invalidCharForNumber: return iter.readFloat64SlowPath() case endOfNumber: iter.ReportError("readFloat64", "empty number") return case dotInNumber: iter.ReportError("readFloat64", "leading dot is invalid") return case 0: if i == iter.tail { return iter.readFloat64SlowPath() } c = iter.buf[i] switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': iter.ReportError("readFloat64", "leading zero is invalid") return } } value := uint64(ind) // chars before dot non_decimal_loop: for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] switch ind { case invalidCharForNumber: return iter.readFloat64SlowPath() case endOfNumber: iter.head = i return float64(value) case dotInNumber: break non_decimal_loop } if value > uint64SafeToMultiple10 { return iter.readFloat64SlowPath() } value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; } // chars after dot if c == '.' { i++ decimalPlaces := 0 if i == iter.tail { return iter.readFloat64SlowPath() } for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] switch ind { case endOfNumber: if decimalPlaces > 0 && decimalPlaces < len(pow10) { iter.head = i return float64(value) / float64(pow10[decimalPlaces]) } // too many decimal places return iter.readFloat64SlowPath() case invalidCharForNumber, dotInNumber: return iter.readFloat64SlowPath() } decimalPlaces++ if value > uint64SafeToMultiple10 { return iter.readFloat64SlowPath() } value = (value << 3) + (value << 1) + uint64(ind) if value > maxFloat64 { return iter.readFloat64SlowPath() } } } return iter.readFloat64SlowPath() } func (iter *Iterator) readFloat64SlowPath() (ret float64) { str := iter.readNumberAsString() if iter.Error != nil && iter.Error != io.EOF { return } errMsg := validateFloat(str) if errMsg != "" { iter.ReportError("readFloat64SlowPath", errMsg) return } val, err := strconv.ParseFloat(str, 64) if err != nil { iter.Error = err return } return val } func validateFloat(str string) string { // strconv.ParseFloat is not validating `1.` or `1.e1` if len(str) == 0 { return "empty number" } if str[0] == '-' { return "-- is not valid" } dotPos := strings.IndexByte(str, '.') if dotPos != -1 { if dotPos == len(str)-1 { return "dot can not be last character" } switch str[dotPos+1] { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': default: return "missing digit after dot" } } return "" } // ReadNumber read json.Number func (iter *Iterator) ReadNumber() (ret json.Number) { return json.Number(iter.readNumberAsString()) }
package jsoniter import ( "math" "strconv" ) var intDigits []int8 const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1 const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1 const maxFloat64 = 1<<53 - 1 func init() { intDigits = make([]int8, 256) for i := 0; i < len(intDigits); i++ { intDigits[i] = invalidCharForNumber } for i := int8('0'); i <= int8('9'); i++ { intDigits[i] = i - int8('0') } } // ReadUint read uint func (iter *Iterator) ReadUint() uint { if strconv.IntSize == 32 { return uint(iter.ReadUint32()) } return uint(iter.ReadUint64()) } // ReadInt read int func (iter *Iterator) ReadInt() int { if strconv.IntSize == 32 { return int(iter.ReadInt32()) } return int(iter.ReadInt64()) } // ReadInt8 read int8 func (iter *Iterator) ReadInt8() (ret int8) { c := iter.nextToken() if c == '-' { val := iter.readUint32(iter.readByte()) if val > math.MaxInt8+1 { iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return -int8(val) } val := iter.readUint32(c) if val > math.MaxInt8 { iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return int8(val) } // ReadUint8 read uint8 func (iter *Iterator) ReadUint8() (ret uint8) { val := iter.readUint32(iter.nextToken()) if val > math.MaxUint8 { iter.ReportError("ReadUint8", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return uint8(val) } // ReadInt16 read int16 func (iter *Iterator) ReadInt16() (ret int16) { c := iter.nextToken() if c == '-' { val := iter.readUint32(iter.readByte()) if val > math.MaxInt16+1 { iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return -int16(val) } val := iter.readUint32(c) if val > math.MaxInt16 { iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return int16(val) } // ReadUint16 read uint16 func (iter *Iterator) ReadUint16() (ret uint16) { val := iter.readUint32(iter.nextToken()) if val > math.MaxUint16 { iter.ReportError("ReadUint16", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return uint16(val) } // ReadInt32 read int32 func (iter *Iterator) ReadInt32() (ret int32) { c := iter.nextToken() if c == '-' { val := iter.readUint32(iter.readByte()) if val > math.MaxInt32+1 { iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return -int32(val) } val := iter.readUint32(c) if val > math.MaxInt32 { iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) return } return int32(val) } // ReadUint32 read uint32 func (iter *Iterator) ReadUint32() (ret uint32) { return iter.readUint32(iter.nextToken()) } func (iter *Iterator) readUint32(c byte) (ret uint32) { ind := intDigits[c] if ind == 0 { iter.assertInteger() return 0 // single zero } if ind == invalidCharForNumber { iter.ReportError("readUint32", "unexpected character: "+string([]byte{byte(ind)})) return } value := uint32(ind) if iter.tail-iter.head > 10 { i := iter.head ind2 := intDigits[iter.buf[i]] if ind2 == invalidCharForNumber { iter.head = i iter.assertInteger() return value } i++ ind3 := intDigits[iter.buf[i]] if ind3 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*10 + uint32(ind2) } //iter.head = i + 1 //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) i++ ind4 := intDigits[iter.buf[i]] if ind4 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*100 + uint32(ind2)*10 + uint32(ind3) } i++ ind5 := intDigits[iter.buf[i]] if ind5 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4) } i++ ind6 := intDigits[iter.buf[i]] if ind6 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5) } i++ ind7 := intDigits[iter.buf[i]] if ind7 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6) } i++ ind8 := intDigits[iter.buf[i]] if ind8 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7) } i++ ind9 := intDigits[iter.buf[i]] value = value*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8) iter.head = i if ind9 == invalidCharForNumber { iter.assertInteger() return value } } for { for i := iter.head; i < iter.tail; i++ { ind = intDigits[iter.buf[i]] if ind == invalidCharForNumber { iter.head = i iter.assertInteger() return value } if value > uint32SafeToMultiply10 { value2 := (value << 3) + (value << 1) + uint32(ind) if value2 < value { iter.ReportError("readUint32", "overflow") return } value = value2 continue } value = (value << 3) + (value << 1) + uint32(ind) } if !iter.loadMore() { iter.assertInteger() return value } } } // ReadInt64 read int64 func (iter *Iterator) ReadInt64() (ret int64) { c := iter.nextToken() if c == '-' { val := iter.readUint64(iter.readByte()) if val > math.MaxInt64+1 { iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) return } return -int64(val) } val := iter.readUint64(c) if val > math.MaxInt64 { iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) return } return int64(val) } // ReadUint64 read uint64 func (iter *Iterator) ReadUint64() uint64 { return iter.readUint64(iter.nextToken()) } func (iter *Iterator) readUint64(c byte) (ret uint64) { ind := intDigits[c] if ind == 0 { iter.assertInteger() return 0 // single zero } if ind == invalidCharForNumber { iter.ReportError("readUint64", "unexpected character: "+string([]byte{byte(ind)})) return } value := uint64(ind) if iter.tail-iter.head > 10 { i := iter.head ind2 := intDigits[iter.buf[i]] if ind2 == invalidCharForNumber { iter.head = i iter.assertInteger() return value } i++ ind3 := intDigits[iter.buf[i]] if ind3 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*10 + uint64(ind2) } //iter.head = i + 1 //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) i++ ind4 := intDigits[iter.buf[i]] if ind4 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*100 + uint64(ind2)*10 + uint64(ind3) } i++ ind5 := intDigits[iter.buf[i]] if ind5 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4) } i++ ind6 := intDigits[iter.buf[i]] if ind6 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5) } i++ ind7 := intDigits[iter.buf[i]] if ind7 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6) } i++ ind8 := intDigits[iter.buf[i]] if ind8 == invalidCharForNumber { iter.head = i iter.assertInteger() return value*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7) } i++ ind9 := intDigits[iter.buf[i]] value = value*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8) iter.head = i if ind9 == invalidCharForNumber { iter.assertInteger() return value } } for { for i := iter.head; i < iter.tail; i++ { ind = intDigits[iter.buf[i]] if ind == invalidCharForNumber { iter.head = i iter.assertInteger() return value } if value > uint64SafeToMultiple10 { value2 := (value << 3) + (value << 1) + uint64(ind) if value2 < value { iter.ReportError("readUint64", "overflow") return } value = value2 continue } value = (value << 3) + (value << 1) + uint64(ind) } if !iter.loadMore() { iter.assertInteger() return value } } } func (iter *Iterator) assertInteger() { if iter.head < iter.tail && iter.buf[iter.head] == '.' { iter.ReportError("assertInteger", "can not decode float as int") } }
package jsoniter import ( "fmt" "strings" ) // ReadObject read one field from object. // If object ended, returns empty string. // Otherwise, returns the field name. func (iter *Iterator) ReadObject() (ret string) { c := iter.nextToken() switch c { case 'n': iter.skipThreeBytes('u', 'l', 'l') return "" // null case '{': c = iter.nextToken() if c == '"' { iter.unreadByte() field := iter.ReadString() c = iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } return field } if c == '}' { return "" // end of object } iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c})) return case ',': field := iter.ReadString() c = iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } return field case '}': return "" // end of object default: iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c}))) return } } // CaseInsensitive func (iter *Iterator) readFieldHash() int64 { hash := int64(0x811c9dc5) c := iter.nextToken() if c != '"' { iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c})) return 0 } for { for i := iter.head; i < iter.tail; i++ { // require ascii string and no escape b := iter.buf[i] if b == '\\' { iter.head = i for _, b := range iter.readStringSlowPath() { if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) hash *= 0x1000193 } c = iter.nextToken() if c != ':' { iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) return 0 } return hash } if b == '"' { iter.head = i + 1 c = iter.nextToken() if c != ':' { iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) return 0 } return hash } if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) hash *= 0x1000193 } if !iter.loadMore() { iter.ReportError("readFieldHash", `incomplete field name`) return 0 } } } func calcHash(str string, caseSensitive bool) int64 { if !caseSensitive { str = strings.ToLower(str) } hash := int64(0x811c9dc5) for _, b := range []byte(str) { hash ^= int64(b) hash *= 0x1000193 } return int64(hash) } // ReadObjectCB read object with callback, the key is ascii only and field name not copied func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { c := iter.nextToken() var field string if c == '{' { if !iter.incrementDepth() { return false } c = iter.nextToken() if c == '"' { iter.unreadByte() field = iter.ReadString() c = iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } if !callback(iter, field) { iter.decrementDepth() return false } c = iter.nextToken() for c == ',' { field = iter.ReadString() c = iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } if !callback(iter, field) { iter.decrementDepth() return false } c = iter.nextToken() } if c != '}' { iter.ReportError("ReadObjectCB", `object not ended with }`) iter.decrementDepth() return false } return iter.decrementDepth() } if c == '}' { return iter.decrementDepth() } iter.ReportError("ReadObjectCB", `expect " after {, but found `+string([]byte{c})) iter.decrementDepth() return false } if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return true // null } iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c})) return false } // ReadMapCB read map with callback, the key can be any string func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { c := iter.nextToken() if c == '{' { if !iter.incrementDepth() { return false } c = iter.nextToken() if c == '"' { iter.unreadByte() field := iter.ReadString() if iter.nextToken() != ':' { iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) iter.decrementDepth() return false } if !callback(iter, field) { iter.decrementDepth() return false } c = iter.nextToken() for c == ',' { field = iter.ReadString() if iter.nextToken() != ':' { iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) iter.decrementDepth() return false } if !callback(iter, field) { iter.decrementDepth() return false } c = iter.nextToken() } if c != '}' { iter.ReportError("ReadMapCB", `object not ended with }`) iter.decrementDepth() return false } return iter.decrementDepth() } if c == '}' { return iter.decrementDepth() } iter.ReportError("ReadMapCB", `expect " after {, but found `+string([]byte{c})) iter.decrementDepth() return false } if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return true // null } iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) return false } func (iter *Iterator) readObjectStart() bool { c := iter.nextToken() if c == '{' { c = iter.nextToken() if c == '}' { return false } iter.unreadByte() return true } else if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return false } iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c})) return false } func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) { str := iter.ReadStringAsSlice() if iter.skipWhitespacesWithoutLoadMore() { if ret == nil { ret = make([]byte, len(str)) copy(ret, str) } if !iter.loadMore() { return } } if iter.buf[iter.head] != ':' { iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]})) return } iter.head++ if iter.skipWhitespacesWithoutLoadMore() { if ret == nil { ret = make([]byte, len(str)) copy(ret, str) } if !iter.loadMore() { return } } if ret == nil { return str } return ret }
package jsoniter import "fmt" // ReadNil reads a json object as nil and // returns whether it's a nil or not func (iter *Iterator) ReadNil() (ret bool) { c := iter.nextToken() if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') // null return true } iter.unreadByte() return false } // ReadBool reads a json object as BoolValue func (iter *Iterator) ReadBool() (ret bool) { c := iter.nextToken() if c == 't' { iter.skipThreeBytes('r', 'u', 'e') return true } if c == 'f' { iter.skipFourBytes('a', 'l', 's', 'e') return false } iter.ReportError("ReadBool", "expect t or f, but found "+string([]byte{c})) return } // SkipAndReturnBytes skip next JSON element, and return its content as []byte. // The []byte can be kept, it is a copy of data. func (iter *Iterator) SkipAndReturnBytes() []byte { iter.startCapture(iter.head) iter.Skip() return iter.stopCapture() } // SkipAndAppendBytes skips next JSON element and appends its content to // buffer, returning the result. func (iter *Iterator) SkipAndAppendBytes(buf []byte) []byte { iter.startCaptureTo(buf, iter.head) iter.Skip() return iter.stopCapture() } func (iter *Iterator) startCaptureTo(buf []byte, captureStartedAt int) { if iter.captured != nil { panic("already in capture mode") } iter.captureStartedAt = captureStartedAt iter.captured = buf } func (iter *Iterator) startCapture(captureStartedAt int) { iter.startCaptureTo(make([]byte, 0, 32), captureStartedAt) } func (iter *Iterator) stopCapture() []byte { if iter.captured == nil { panic("not in capture mode") } captured := iter.captured remaining := iter.buf[iter.captureStartedAt:iter.head] iter.captureStartedAt = -1 iter.captured = nil return append(captured, remaining...) } // Skip skips a json object and positions to relatively the next json object func (iter *Iterator) Skip() { c := iter.nextToken() switch c { case '"': iter.skipString() case 'n': iter.skipThreeBytes('u', 'l', 'l') // null case 't': iter.skipThreeBytes('r', 'u', 'e') // true case 'f': iter.skipFourBytes('a', 'l', 's', 'e') // false case '0': iter.unreadByte() iter.ReadFloat32() case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': iter.skipNumber() case '[': iter.skipArray() case '{': iter.skipObject() default: iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) return } } func (iter *Iterator) skipFourBytes(b1, b2, b3, b4 byte) { if iter.readByte() != b1 { iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) return } if iter.readByte() != b2 { iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) return } if iter.readByte() != b3 { iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) return } if iter.readByte() != b4 { iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) return } } func (iter *Iterator) skipThreeBytes(b1, b2, b3 byte) { if iter.readByte() != b1 { iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) return } if iter.readByte() != b2 { iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) return } if iter.readByte() != b3 { iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) return } }
//+build !jsoniter_sloppy package jsoniter import ( "fmt" "io" ) func (iter *Iterator) skipNumber() { if !iter.trySkipNumber() { iter.unreadByte() if iter.Error != nil && iter.Error != io.EOF { return } iter.ReadFloat64() if iter.Error != nil && iter.Error != io.EOF { iter.Error = nil iter.ReadBigFloat() } } } func (iter *Iterator) trySkipNumber() bool { dotFound := false for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '.': if dotFound { iter.ReportError("validateNumber", `more than one dot found in number`) return true // already failed } if i+1 == iter.tail { return false } c = iter.buf[i+1] switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': default: iter.ReportError("validateNumber", `missing digit after dot`) return true // already failed } dotFound = true default: switch c { case ',', ']', '}', ' ', '\t', '\n', '\r': if iter.head == i { return false // if - without following digits } iter.head = i return true // must be valid } return false // may be invalid } } return false } func (iter *Iterator) skipString() { if !iter.trySkipString() { iter.unreadByte() iter.ReadString() } } func (iter *Iterator) trySkipString() bool { for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] if c == '"' { iter.head = i + 1 return true // valid } else if c == '\\' { return false } else if c < ' ' { iter.ReportError("trySkipString", fmt.Sprintf(`invalid control character found: %d`, c)) return true // already failed } } return false } func (iter *Iterator) skipObject() { iter.unreadByte() iter.ReadObjectCB(func(iter *Iterator, field string) bool { iter.Skip() return true }) } func (iter *Iterator) skipArray() { iter.unreadByte() iter.ReadArrayCB(func(iter *Iterator) bool { iter.Skip() return true }) }
package jsoniter import ( "fmt" "unicode/utf16" ) // ReadString read string from iterator func (iter *Iterator) ReadString() (ret string) { c := iter.nextToken() if c == '"' { for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] if c == '"' { ret = string(iter.buf[iter.head:i]) iter.head = i + 1 return ret } else if c == '\\' { break } else if c < ' ' { iter.ReportError("ReadString", fmt.Sprintf(`invalid control character found: %d`, c)) return } } return iter.readStringSlowPath() } else if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return "" } iter.ReportError("ReadString", `expects " or n, but found `+string([]byte{c})) return } func (iter *Iterator) readStringSlowPath() (ret string) { var str []byte var c byte for iter.Error == nil { c = iter.readByte() if c == '"' { return string(str) } if c == '\\' { c = iter.readByte() str = iter.readEscapedChar(c, str) } else { str = append(str, c) } } iter.ReportError("readStringSlowPath", "unexpected end of input") return } func (iter *Iterator) readEscapedChar(c byte, str []byte) []byte { switch c { case 'u': r := iter.readU4() if utf16.IsSurrogate(r) { c = iter.readByte() if iter.Error != nil { return nil } if c != '\\' { iter.unreadByte() str = appendRune(str, r) return str } c = iter.readByte() if iter.Error != nil { return nil } if c != 'u' { str = appendRune(str, r) return iter.readEscapedChar(c, str) } r2 := iter.readU4() if iter.Error != nil { return nil } combined := utf16.DecodeRune(r, r2) if combined == '\uFFFD' { str = appendRune(str, r) str = appendRune(str, r2) } else { str = appendRune(str, combined) } } else { str = appendRune(str, r) } case '"': str = append(str, '"') case '\\': str = append(str, '\\') case '/': str = append(str, '/') case 'b': str = append(str, '\b') case 'f': str = append(str, '\f') case 'n': str = append(str, '\n') case 'r': str = append(str, '\r') case 't': str = append(str, '\t') default: iter.ReportError("readEscapedChar", `invalid escape char after \`) return nil } return str } // ReadStringAsSlice read string from iterator without copying into string form. // The []byte can not be kept, as it will change after next iterator call. func (iter *Iterator) ReadStringAsSlice() (ret []byte) { c := iter.nextToken() if c == '"' { for i := iter.head; i < iter.tail; i++ { // require ascii string and no escape // for: field name, base64, number if iter.buf[i] == '"' { // fast path: reuse the underlying buffer ret = iter.buf[iter.head:i] iter.head = i + 1 return ret } } readLen := iter.tail - iter.head copied := make([]byte, readLen, readLen*2) copy(copied, iter.buf[iter.head:iter.tail]) iter.head = iter.tail for iter.Error == nil { c := iter.readByte() if c == '"' { return copied } copied = append(copied, c) } return copied } iter.ReportError("ReadStringAsSlice", `expects " or n, but found `+string([]byte{c})) return } func (iter *Iterator) readU4() (ret rune) { for i := 0; i < 4; i++ { c := iter.readByte() if iter.Error != nil { return } if c >= '0' && c <= '9' { ret = ret*16 + rune(c-'0') } else if c >= 'a' && c <= 'f' { ret = ret*16 + rune(c-'a'+10) } else if c >= 'A' && c <= 'F' { ret = ret*16 + rune(c-'A'+10) } else { iter.ReportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c})) return } } return ret } const ( t1 = 0x00 // 0000 0000 tx = 0x80 // 1000 0000 t2 = 0xC0 // 1100 0000 t3 = 0xE0 // 1110 0000 t4 = 0xF0 // 1111 0000 t5 = 0xF8 // 1111 1000 maskx = 0x3F // 0011 1111 mask2 = 0x1F // 0001 1111 mask3 = 0x0F // 0000 1111 mask4 = 0x07 // 0000 0111 rune1Max = 1<<7 - 1 rune2Max = 1<<11 - 1 rune3Max = 1<<16 - 1 surrogateMin = 0xD800 surrogateMax = 0xDFFF maxRune = '\U0010FFFF' // Maximum valid Unicode code point. runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character" ) func appendRune(p []byte, r rune) []byte { // Negative values are erroneous. Making it unsigned addresses the problem. switch i := uint32(r); { case i <= rune1Max: p = append(p, byte(r)) return p case i <= rune2Max: p = append(p, t2|byte(r>>6)) p = append(p, tx|byte(r)&maskx) return p case i > maxRune, surrogateMin <= i && i <= surrogateMax: r = runeError fallthrough case i <= rune3Max: p = append(p, t3|byte(r>>12)) p = append(p, tx|byte(r>>6)&maskx) p = append(p, tx|byte(r)&maskx) return p default: p = append(p, t4|byte(r>>18)) p = append(p, tx|byte(r>>12)&maskx) p = append(p, tx|byte(r>>6)&maskx) p = append(p, tx|byte(r)&maskx) return p } }
package jsoniter import ( "io" ) // IteratorPool a thread safe pool of iterators with same configuration type IteratorPool interface { BorrowIterator(data []byte) *Iterator ReturnIterator(iter *Iterator) } // StreamPool a thread safe pool of streams with same configuration type StreamPool interface { BorrowStream(writer io.Writer) *Stream ReturnStream(stream *Stream) } func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { stream := cfg.streamPool.Get().(*Stream) stream.Reset(writer) return stream } func (cfg *frozenConfig) ReturnStream(stream *Stream) { stream.out = nil stream.Error = nil stream.Attachment = nil cfg.streamPool.Put(stream) } func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator { iter := cfg.iteratorPool.Get().(*Iterator) iter.ResetBytes(data) return iter } func (cfg *frozenConfig) ReturnIterator(iter *Iterator) { iter.Error = nil iter.Attachment = nil cfg.iteratorPool.Put(iter) }
package jsoniter import ( "fmt" "reflect" "unsafe" "github.com/modern-go/reflect2" ) // ValDecoder is an internal type registered to cache as needed. // Don't confuse jsoniter.ValDecoder with json.Decoder. // For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link). // // Reflection on type to create decoders, which is then cached // Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions // 1. create instance of new value, for example *int will need a int to be allocated // 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New // 3. assignment to map, both key and value will be reflect.Value // For a simple struct binding, it will be reflect.Value free and allocation free type ValDecoder interface { Decode(ptr unsafe.Pointer, iter *Iterator) } // ValEncoder is an internal type registered to cache as needed. // Don't confuse jsoniter.ValEncoder with json.Encoder. // For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link). type ValEncoder interface { IsEmpty(ptr unsafe.Pointer) bool Encode(ptr unsafe.Pointer, stream *Stream) } type checkIsEmpty interface { IsEmpty(ptr unsafe.Pointer) bool } type ctx struct { *frozenConfig prefix string encoders map[reflect2.Type]ValEncoder decoders map[reflect2.Type]ValDecoder } func (b *ctx) caseSensitive() bool { if b.frozenConfig == nil { // default is case-insensitive return false } return b.frozenConfig.caseSensitive } func (b *ctx) append(prefix string) *ctx { return &ctx{ frozenConfig: b.frozenConfig, prefix: b.prefix + " " + prefix, encoders: b.encoders, decoders: b.decoders, } } // ReadVal copy the underlying JSON into go interface, same as json.Unmarshal func (iter *Iterator) ReadVal(obj interface{}) { depth := iter.depth cacheKey := reflect2.RTypeOf(obj) decoder := iter.cfg.getDecoderFromCache(cacheKey) if decoder == nil { typ := reflect2.TypeOf(obj) if typ == nil || typ.Kind() != reflect.Ptr { iter.ReportError("ReadVal", "can only unmarshal into pointer") return } decoder = iter.cfg.DecoderOf(typ) } ptr := reflect2.PtrOf(obj) if ptr == nil { iter.ReportError("ReadVal", "can not read into nil pointer") return } decoder.Decode(ptr, iter) if iter.depth != depth { iter.ReportError("ReadVal", "unexpected mismatched nesting") return } } // WriteVal copy the go interface into underlying JSON, same as json.Marshal func (stream *Stream) WriteVal(val interface{}) { if nil == val { stream.WriteNil() return } cacheKey := reflect2.RTypeOf(val) encoder := stream.cfg.getEncoderFromCache(cacheKey) if encoder == nil { typ := reflect2.TypeOf(val) encoder = stream.cfg.EncoderOf(typ) } encoder.Encode(reflect2.PtrOf(val), stream) } func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder { cacheKey := typ.RType() decoder := cfg.getDecoderFromCache(cacheKey) if decoder != nil { return decoder } ctx := &ctx{ frozenConfig: cfg, prefix: "", decoders: map[reflect2.Type]ValDecoder{}, encoders: map[reflect2.Type]ValEncoder{}, } ptrType := typ.(*reflect2.UnsafePtrType) decoder = decoderOfType(ctx, ptrType.Elem()) cfg.addDecoderToCache(cacheKey, decoder) return decoder } func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { decoder := getTypeDecoderFromExtension(ctx, typ) if decoder != nil { return decoder } decoder = createDecoderOfType(ctx, typ) for _, extension := range extensions { decoder = extension.DecorateDecoder(typ, decoder) } decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) for _, extension := range ctx.extraExtensions { decoder = extension.DecorateDecoder(typ, decoder) } return decoder } func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { decoder := ctx.decoders[typ] if decoder != nil { return decoder } placeholder := &placeholderDecoder{} ctx.decoders[typ] = placeholder decoder = _createDecoderOfType(ctx, typ) placeholder.decoder = decoder return decoder } func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { decoder := createDecoderOfJsonRawMessage(ctx, typ) if decoder != nil { return decoder } decoder = createDecoderOfJsonNumber(ctx, typ) if decoder != nil { return decoder } decoder = createDecoderOfMarshaler(ctx, typ) if decoder != nil { return decoder } decoder = createDecoderOfAny(ctx, typ) if decoder != nil { return decoder } decoder = createDecoderOfNative(ctx, typ) if decoder != nil { return decoder } switch typ.Kind() { case reflect.Interface: ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType) if isIFace { return &ifaceDecoder{valType: ifaceType} } return &efaceDecoder{} case reflect.Struct: return decoderOfStruct(ctx, typ) case reflect.Array: return decoderOfArray(ctx, typ) case reflect.Slice: return decoderOfSlice(ctx, typ) case reflect.Map: return decoderOfMap(ctx, typ) case reflect.Ptr: return decoderOfOptional(ctx, typ) default: return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} } } func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder { cacheKey := typ.RType() encoder := cfg.getEncoderFromCache(cacheKey) if encoder != nil { return encoder } ctx := &ctx{ frozenConfig: cfg, prefix: "", decoders: map[reflect2.Type]ValDecoder{}, encoders: map[reflect2.Type]ValEncoder{}, } encoder = encoderOfType(ctx, typ) if typ.LikePtr() { encoder = &onePtrEncoder{encoder} } cfg.addEncoderToCache(cacheKey, encoder) return encoder } type onePtrEncoder struct { encoder ValEncoder } func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) } func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) } func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { encoder := getTypeEncoderFromExtension(ctx, typ) if encoder != nil { return encoder } encoder = createEncoderOfType(ctx, typ) for _, extension := range extensions { encoder = extension.DecorateEncoder(typ, encoder) } encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) for _, extension := range ctx.extraExtensions { encoder = extension.DecorateEncoder(typ, encoder) } return encoder } func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { encoder := ctx.encoders[typ] if encoder != nil { return encoder } placeholder := &placeholderEncoder{} ctx.encoders[typ] = placeholder encoder = _createEncoderOfType(ctx, typ) placeholder.encoder = encoder return encoder } func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { encoder := createEncoderOfJsonRawMessage(ctx, typ) if encoder != nil { return encoder } encoder = createEncoderOfJsonNumber(ctx, typ) if encoder != nil { return encoder } encoder = createEncoderOfMarshaler(ctx, typ) if encoder != nil { return encoder } encoder = createEncoderOfAny(ctx, typ) if encoder != nil { return encoder } encoder = createEncoderOfNative(ctx, typ) if encoder != nil { return encoder } kind := typ.Kind() switch kind { case reflect.Interface: return &dynamicEncoder{typ} case reflect.Struct: return encoderOfStruct(ctx, typ) case reflect.Array: return encoderOfArray(ctx, typ) case reflect.Slice: return encoderOfSlice(ctx, typ) case reflect.Map: return encoderOfMap(ctx, typ) case reflect.Ptr: return encoderOfOptional(ctx, typ) default: return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} } } type lazyErrorDecoder struct { err error } func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.WhatIsNext() != NilValue { if iter.Error == nil { iter.Error = decoder.err } } else { iter.Skip() } } type lazyErrorEncoder struct { err error } func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if ptr == nil { stream.WriteNil() } else if stream.Error == nil { stream.Error = encoder.err } } func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } type placeholderDecoder struct { decoder ValDecoder } func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.decoder.Decode(ptr, iter) } type placeholderEncoder struct { encoder ValEncoder } func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { encoder.encoder.Encode(ptr, stream) } func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.encoder.IsEmpty(ptr) }
package jsoniter import ( "fmt" "github.com/modern-go/reflect2" "io" "unsafe" ) func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder { arrayType := typ.(*reflect2.UnsafeArrayType) decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) return &arrayDecoder{arrayType, decoder} } func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder { arrayType := typ.(*reflect2.UnsafeArrayType) if arrayType.Len() == 0 { return emptyArrayEncoder{} } encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) return &arrayEncoder{arrayType, encoder} } type emptyArrayEncoder struct{} func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteEmptyArray() } func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { return true } type arrayEncoder struct { arrayType *reflect2.UnsafeArrayType elemEncoder ValEncoder } func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteArrayStart() elemPtr := unsafe.Pointer(ptr) encoder.elemEncoder.Encode(elemPtr, stream) for i := 1; i < encoder.arrayType.Len(); i++ { stream.WriteMore() elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i) encoder.elemEncoder.Encode(elemPtr, stream) } stream.WriteArrayEnd() if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error()) } } func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } type arrayDecoder struct { arrayType *reflect2.UnsafeArrayType elemDecoder ValDecoder } func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.doDecode(ptr, iter) if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error()) } } func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { c := iter.nextToken() arrayType := decoder.arrayType if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') return } if c != '[' { iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c})) return } c = iter.nextToken() if c == ']' { return } iter.unreadByte() elemPtr := arrayType.UnsafeGetIndex(ptr, 0) decoder.elemDecoder.Decode(elemPtr, iter) length := 1 for c = iter.nextToken(); c == ','; c = iter.nextToken() { if length >= arrayType.Len() { iter.Skip() continue } idx := length length += 1 elemPtr = arrayType.UnsafeGetIndex(ptr, idx) decoder.elemDecoder.Decode(elemPtr, iter) } if c != ']' { iter.ReportError("decode array", "expect ], but found "+string([]byte{c})) return } }
package jsoniter import ( "github.com/modern-go/reflect2" "reflect" "unsafe" ) type dynamicEncoder struct { valType reflect2.Type } func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { obj := encoder.valType.UnsafeIndirect(ptr) stream.WriteVal(obj) } func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.valType.UnsafeIndirect(ptr) == nil } type efaceDecoder struct { } func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { pObj := (*interface{})(ptr) obj := *pObj if obj == nil { *pObj = iter.Read() return } typ := reflect2.TypeOf(obj) if typ.Kind() != reflect.Ptr { *pObj = iter.Read() return } ptrType := typ.(*reflect2.UnsafePtrType) ptrElemType := ptrType.Elem() if iter.WhatIsNext() == NilValue { if ptrElemType.Kind() != reflect.Ptr { iter.skipFourBytes('n', 'u', 'l', 'l') *pObj = nil return } } if reflect2.IsNil(obj) { obj := ptrElemType.New() iter.ReadVal(obj) *pObj = obj return } iter.ReadVal(obj) } type ifaceDecoder struct { valType *reflect2.UnsafeIFaceType } func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.ReadNil() { decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew()) return } obj := decoder.valType.UnsafeIndirect(ptr) if reflect2.IsNil(obj) { iter.ReportError("decode non empty interface", "can not unmarshal into nil") return } iter.ReadVal(obj) }
package jsoniter import ( "fmt" "github.com/modern-go/reflect2" "reflect" "sort" "strings" "unicode" "unsafe" ) var typeDecoders = map[string]ValDecoder{} var fieldDecoders = map[string]ValDecoder{} var typeEncoders = map[string]ValEncoder{} var fieldEncoders = map[string]ValEncoder{} var extensions = []Extension{} // StructDescriptor describe how should we encode/decode the struct type StructDescriptor struct { Type reflect2.Type Fields []*Binding } // GetField get one field from the descriptor by its name. // Can not use map here to keep field orders. func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding { for _, binding := range structDescriptor.Fields { if binding.Field.Name() == fieldName { return binding } } return nil } // Binding describe how should we encode/decode the struct field type Binding struct { levels []int Field reflect2.StructField FromNames []string ToNames []string Encoder ValEncoder Decoder ValDecoder } // Extension the one for all SPI. Customize encoding/decoding by specifying alternate encoder/decoder. // Can also rename fields by UpdateStructDescriptor. type Extension interface { UpdateStructDescriptor(structDescriptor *StructDescriptor) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder CreateMapKeyEncoder(typ reflect2.Type) ValEncoder CreateDecoder(typ reflect2.Type) ValDecoder CreateEncoder(typ reflect2.Type) ValEncoder DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder } // DummyExtension embed this type get dummy implementation for all methods of Extension type DummyExtension struct { } // UpdateStructDescriptor No-op func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { } // CreateMapKeyDecoder No-op func (extension *DummyExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { return nil } // CreateMapKeyEncoder No-op func (extension *DummyExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { return nil } // CreateDecoder No-op func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder { return nil } // CreateEncoder No-op func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder { return nil } // DecorateDecoder No-op func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { return decoder } // DecorateEncoder No-op func (extension *DummyExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { return encoder } type EncoderExtension map[reflect2.Type]ValEncoder // UpdateStructDescriptor No-op func (extension EncoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { } // CreateDecoder No-op func (extension EncoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { return nil } // CreateEncoder get encoder from map func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { return extension[typ] } // CreateMapKeyDecoder No-op func (extension EncoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { return nil } // CreateMapKeyEncoder No-op func (extension EncoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { return nil } // DecorateDecoder No-op func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { return decoder } // DecorateEncoder No-op func (extension EncoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { return encoder } type DecoderExtension map[reflect2.Type]ValDecoder // UpdateStructDescriptor No-op func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { } // CreateMapKeyDecoder No-op func (extension DecoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { return nil } // CreateMapKeyEncoder No-op func (extension DecoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { return nil } // CreateDecoder get decoder from map func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { return extension[typ] } // CreateEncoder No-op func (extension DecoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { return nil } // DecorateDecoder No-op func (extension DecoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { return decoder } // DecorateEncoder No-op func (extension DecoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { return encoder } type funcDecoder struct { fun DecoderFunc } func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.fun(ptr, iter) } type funcEncoder struct { fun EncoderFunc isEmptyFunc func(ptr unsafe.Pointer) bool } func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { encoder.fun(ptr, stream) } func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool { if encoder.isEmptyFunc == nil { return false } return encoder.isEmptyFunc(ptr) } // DecoderFunc the function form of TypeDecoder type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) // EncoderFunc the function form of TypeEncoder type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) // RegisterTypeDecoderFunc register TypeDecoder for a type with function func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) { typeDecoders[typ] = &funcDecoder{fun} } // RegisterTypeDecoder register TypeDecoder for a typ func RegisterTypeDecoder(typ string, decoder ValDecoder) { typeDecoders[typ] = decoder } // RegisterFieldDecoderFunc register TypeDecoder for a struct field with function func RegisterFieldDecoderFunc(typ string, field string, fun DecoderFunc) { RegisterFieldDecoder(typ, field, &funcDecoder{fun}) } // RegisterFieldDecoder register TypeDecoder for a struct field func RegisterFieldDecoder(typ string, field string, decoder ValDecoder) { fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = decoder } // RegisterTypeEncoderFunc register TypeEncoder for a type with encode/isEmpty function func RegisterTypeEncoderFunc(typ string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { typeEncoders[typ] = &funcEncoder{fun, isEmptyFunc} } // RegisterTypeEncoder register TypeEncoder for a type func RegisterTypeEncoder(typ string, encoder ValEncoder) { typeEncoders[typ] = encoder } // RegisterFieldEncoderFunc register TypeEncoder for a struct field with encode/isEmpty function func RegisterFieldEncoderFunc(typ string, field string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { RegisterFieldEncoder(typ, field, &funcEncoder{fun, isEmptyFunc}) } // RegisterFieldEncoder register TypeEncoder for a struct field func RegisterFieldEncoder(typ string, field string, encoder ValEncoder) { fieldEncoders[fmt.Sprintf("%s/%s", typ, field)] = encoder } // RegisterExtension register extension func RegisterExtension(extension Extension) { extensions = append(extensions, extension) } func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { decoder := _getTypeDecoderFromExtension(ctx, typ) if decoder != nil { for _, extension := range extensions { decoder = extension.DecorateDecoder(typ, decoder) } decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) for _, extension := range ctx.extraExtensions { decoder = extension.DecorateDecoder(typ, decoder) } } return decoder } func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { for _, extension := range extensions { decoder := extension.CreateDecoder(typ) if decoder != nil { return decoder } } decoder := ctx.decoderExtension.CreateDecoder(typ) if decoder != nil { return decoder } for _, extension := range ctx.extraExtensions { decoder := extension.CreateDecoder(typ) if decoder != nil { return decoder } } typeName := typ.String() decoder = typeDecoders[typeName] if decoder != nil { return decoder } if typ.Kind() == reflect.Ptr { ptrType := typ.(*reflect2.UnsafePtrType) decoder := typeDecoders[ptrType.Elem().String()] if decoder != nil { return &OptionalDecoder{ptrType.Elem(), decoder} } } return nil } func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { encoder := _getTypeEncoderFromExtension(ctx, typ) if encoder != nil { for _, extension := range extensions { encoder = extension.DecorateEncoder(typ, encoder) } encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) for _, extension := range ctx.extraExtensions { encoder = extension.DecorateEncoder(typ, encoder) } } return encoder } func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { for _, extension := range extensions { encoder := extension.CreateEncoder(typ) if encoder != nil { return encoder } } encoder := ctx.encoderExtension.CreateEncoder(typ) if encoder != nil { return encoder } for _, extension := range ctx.extraExtensions { encoder := extension.CreateEncoder(typ) if encoder != nil { return encoder } } typeName := typ.String() encoder = typeEncoders[typeName] if encoder != nil { return encoder } if typ.Kind() == reflect.Ptr { typePtr := typ.(*reflect2.UnsafePtrType) encoder := typeEncoders[typePtr.Elem().String()] if encoder != nil { return &OptionalEncoder{encoder} } } return nil } func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor { structType := typ.(*reflect2.UnsafeStructType) embeddedBindings := []*Binding{} bindings := []*Binding{} for i := 0; i < structType.NumField(); i++ { field := structType.Field(i) tag, hastag := field.Tag().Lookup(ctx.getTagKey()) if ctx.onlyTaggedField && !hastag && !field.Anonymous() { continue } if tag == "-" || field.Name() == "_" { continue } tagParts := strings.Split(tag, ",") if field.Anonymous() && (tag == "" || tagParts[0] == "") { if field.Type().Kind() == reflect.Struct { structDescriptor := describeStruct(ctx, field.Type()) for _, binding := range structDescriptor.Fields { binding.levels = append([]int{i}, binding.levels...) omitempty := binding.Encoder.(*structFieldEncoder).omitempty binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} binding.Decoder = &structFieldDecoder{field, binding.Decoder} embeddedBindings = append(embeddedBindings, binding) } continue } else if field.Type().Kind() == reflect.Ptr { ptrType := field.Type().(*reflect2.UnsafePtrType) if ptrType.Elem().Kind() == reflect.Struct { structDescriptor := describeStruct(ctx, ptrType.Elem()) for _, binding := range structDescriptor.Fields { binding.levels = append([]int{i}, binding.levels...) omitempty := binding.Encoder.(*structFieldEncoder).omitempty binding.Encoder = &dereferenceEncoder{binding.Encoder} binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder} binding.Decoder = &structFieldDecoder{field, binding.Decoder} embeddedBindings = append(embeddedBindings, binding) } continue } } } fieldNames := calcFieldNames(field.Name(), tagParts[0], tag) fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name()) decoder := fieldDecoders[fieldCacheKey] if decoder == nil { decoder = decoderOfType(ctx.append(field.Name()), field.Type()) } encoder := fieldEncoders[fieldCacheKey] if encoder == nil { encoder = encoderOfType(ctx.append(field.Name()), field.Type()) } binding := &Binding{ Field: field, FromNames: fieldNames, ToNames: fieldNames, Decoder: decoder, Encoder: encoder, } binding.levels = []int{i} bindings = append(bindings, binding) } return createStructDescriptor(ctx, typ, bindings, embeddedBindings) } func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { structDescriptor := &StructDescriptor{ Type: typ, Fields: bindings, } for _, extension := range extensions { extension.UpdateStructDescriptor(structDescriptor) } ctx.encoderExtension.UpdateStructDescriptor(structDescriptor) ctx.decoderExtension.UpdateStructDescriptor(structDescriptor) for _, extension := range ctx.extraExtensions { extension.UpdateStructDescriptor(structDescriptor) } processTags(structDescriptor, ctx.frozenConfig) // merge normal & embedded bindings & sort with original order allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) sort.Sort(allBindings) structDescriptor.Fields = allBindings return structDescriptor } type sortableBindings []*Binding func (bindings sortableBindings) Len() int { return len(bindings) } func (bindings sortableBindings) Less(i, j int) bool { left := bindings[i].levels right := bindings[j].levels k := 0 for { if left[k] < right[k] { return true } else if left[k] > right[k] { return false } k++ } } func (bindings sortableBindings) Swap(i, j int) { bindings[i], bindings[j] = bindings[j], bindings[i] } func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) { for _, binding := range structDescriptor.Fields { shouldOmitEmpty := false tagParts := strings.Split(binding.Field.Tag().Get(cfg.getTagKey()), ",") for _, tagPart := range tagParts[1:] { if tagPart == "omitempty" { shouldOmitEmpty = true } else if tagPart == "string" { if binding.Field.Type().Kind() == reflect.String { binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg} binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg} } else { binding.Decoder = &stringModeNumberDecoder{binding.Decoder} binding.Encoder = &stringModeNumberEncoder{binding.Encoder} } } } binding.Decoder = &structFieldDecoder{binding.Field, binding.Decoder} binding.Encoder = &structFieldEncoder{binding.Field, binding.Encoder, shouldOmitEmpty} } } func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string { // ignore? if wholeTag == "-" { return []string{} } // rename? var fieldNames []string if tagProvidedFieldName == "" { fieldNames = []string{originalFieldName} } else { fieldNames = []string{tagProvidedFieldName} } // private? isNotExported := unicode.IsLower(rune(originalFieldName[0])) || originalFieldName[0] == '_' if isNotExported { fieldNames = []string{} } return fieldNames }
package jsoniter import ( "encoding/json" "github.com/modern-go/reflect2" "strconv" "unsafe" ) type Number string // String returns the literal text of the number. func (n Number) String() string { return string(n) } // Float64 returns the number as a float64. func (n Number) Float64() (float64, error) { return strconv.ParseFloat(string(n), 64) } // Int64 returns the number as an int64. func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } func CastJsonNumber(val interface{}) (string, bool) { switch typedVal := val.(type) { case json.Number: return string(typedVal), true case Number: return string(typedVal), true } return "", false } var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem() var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem() func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder { if typ.AssignableTo(jsonNumberType) { return &jsonNumberCodec{} } if typ.AssignableTo(jsoniterNumberType) { return &jsoniterNumberCodec{} } return nil } func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder { if typ.AssignableTo(jsonNumberType) { return &jsonNumberCodec{} } if typ.AssignableTo(jsoniterNumberType) { return &jsoniterNumberCodec{} } return nil } type jsonNumberCodec struct { } func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { switch iter.WhatIsNext() { case StringValue: *((*json.Number)(ptr)) = json.Number(iter.ReadString()) case NilValue: iter.skipFourBytes('n', 'u', 'l', 'l') *((*json.Number)(ptr)) = "" default: *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) } } func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { number := *((*json.Number)(ptr)) if len(number) == 0 { stream.writeByte('0') } else { stream.WriteRaw(string(number)) } } func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*json.Number)(ptr))) == 0 } type jsoniterNumberCodec struct { } func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { switch iter.WhatIsNext() { case StringValue: *((*Number)(ptr)) = Number(iter.ReadString()) case NilValue: iter.skipFourBytes('n', 'u', 'l', 'l') *((*Number)(ptr)) = "" default: *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) } } func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { number := *((*Number)(ptr)) if len(number) == 0 { stream.writeByte('0') } else { stream.WriteRaw(string(number)) } } func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*Number)(ptr))) == 0 }
package jsoniter import ( "encoding/json" "github.com/modern-go/reflect2" "unsafe" ) var jsonRawMessageType = reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem() var jsoniterRawMessageType = reflect2.TypeOfPtr((*RawMessage)(nil)).Elem() func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValEncoder { if typ == jsonRawMessageType { return &jsonRawMessageCodec{} } if typ == jsoniterRawMessageType { return &jsoniterRawMessageCodec{} } return nil } func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValDecoder { if typ == jsonRawMessageType { return &jsonRawMessageCodec{} } if typ == jsoniterRawMessageType { return &jsoniterRawMessageCodec{} } return nil } type jsonRawMessageCodec struct { } func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.ReadNil() { *((*json.RawMessage)(ptr)) = nil } else { *((*json.RawMessage)(ptr)) = iter.SkipAndReturnBytes() } } func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { if *((*json.RawMessage)(ptr)) == nil { stream.WriteNil() } else { stream.WriteRaw(string(*((*json.RawMessage)(ptr)))) } } func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*json.RawMessage)(ptr))) == 0 } type jsoniterRawMessageCodec struct { } func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.ReadNil() { *((*RawMessage)(ptr)) = nil } else { *((*RawMessage)(ptr)) = iter.SkipAndReturnBytes() } } func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { if *((*RawMessage)(ptr)) == nil { stream.WriteNil() } else { stream.WriteRaw(string(*((*RawMessage)(ptr)))) } } func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*RawMessage)(ptr))) == 0 }
package jsoniter import ( "fmt" "io" "reflect" "sort" "unsafe" "github.com/modern-go/reflect2" ) func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder { mapType := typ.(*reflect2.UnsafeMapType) keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()) elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem()) return &mapDecoder{ mapType: mapType, keyType: mapType.Key(), elemType: mapType.Elem(), keyDecoder: keyDecoder, elemDecoder: elemDecoder, } } func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder { mapType := typ.(*reflect2.UnsafeMapType) if ctx.sortMapKeys { return &sortKeysMapEncoder{ mapType: mapType, keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), } } return &mapEncoder{ mapType: mapType, keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), } } func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder { decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ) if decoder != nil { return decoder } for _, extension := range ctx.extraExtensions { decoder := extension.CreateMapKeyDecoder(typ) if decoder != nil { return decoder } } ptrType := reflect2.PtrTo(typ) if ptrType.Implements(unmarshalerType) { return &referenceDecoder{ &unmarshalerDecoder{ valType: ptrType, }, } } if typ.Implements(unmarshalerType) { return &unmarshalerDecoder{ valType: typ, } } if ptrType.Implements(textUnmarshalerType) { return &referenceDecoder{ &textUnmarshalerDecoder{ valType: ptrType, }, } } if typ.Implements(textUnmarshalerType) { return &textUnmarshalerDecoder{ valType: typ, } } switch typ.Kind() { case reflect.String: return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) case reflect.Bool, reflect.Uint8, reflect.Int8, reflect.Uint16, reflect.Int16, reflect.Uint32, reflect.Int32, reflect.Uint64, reflect.Int64, reflect.Uint, reflect.Int, reflect.Float32, reflect.Float64, reflect.Uintptr: typ = reflect2.DefaultTypeOfKind(typ.Kind()) return &numericMapKeyDecoder{decoderOfType(ctx, typ)} default: return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)} } } func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder { encoder := ctx.encoderExtension.CreateMapKeyEncoder(typ) if encoder != nil { return encoder } for _, extension := range ctx.extraExtensions { encoder := extension.CreateMapKeyEncoder(typ) if encoder != nil { return encoder } } if typ.Kind() != reflect.String { if typ == textMarshalerType { return &directTextMarshalerEncoder{ stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), } } if typ.Implements(textMarshalerType) { return &textMarshalerEncoder{ valType: typ, stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), } } } switch typ.Kind() { case reflect.String: return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) case reflect.Bool, reflect.Uint8, reflect.Int8, reflect.Uint16, reflect.Int16, reflect.Uint32, reflect.Int32, reflect.Uint64, reflect.Int64, reflect.Uint, reflect.Int, reflect.Float32, reflect.Float64, reflect.Uintptr: typ = reflect2.DefaultTypeOfKind(typ.Kind()) return &numericMapKeyEncoder{encoderOfType(ctx, typ)} default: if typ.Kind() == reflect.Interface { return &dynamicMapKeyEncoder{ctx, typ} } return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)} } } type mapDecoder struct { mapType *reflect2.UnsafeMapType keyType reflect2.Type elemType reflect2.Type keyDecoder ValDecoder elemDecoder ValDecoder } func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { mapType := decoder.mapType c := iter.nextToken() if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') *(*unsafe.Pointer)(ptr) = nil mapType.UnsafeSet(ptr, mapType.UnsafeNew()) return } if mapType.UnsafeIsNil(ptr) { mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0)) } if c != '{' { iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) return } c = iter.nextToken() if c == '}' { return } iter.unreadByte() key := decoder.keyType.UnsafeNew() decoder.keyDecoder.Decode(key, iter) c = iter.nextToken() if c != ':' { iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) return } elem := decoder.elemType.UnsafeNew() decoder.elemDecoder.Decode(elem, iter) decoder.mapType.UnsafeSetIndex(ptr, key, elem) for c = iter.nextToken(); c == ','; c = iter.nextToken() { key := decoder.keyType.UnsafeNew() decoder.keyDecoder.Decode(key, iter) c = iter.nextToken() if c != ':' { iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) return } elem := decoder.elemType.UnsafeNew() decoder.elemDecoder.Decode(elem, iter) decoder.mapType.UnsafeSetIndex(ptr, key, elem) } if c != '}' { iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c})) } } type numericMapKeyDecoder struct { decoder ValDecoder } func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { c := iter.nextToken() if c != '"' { iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) return } decoder.decoder.Decode(ptr, iter) c = iter.nextToken() if c != '"' { iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) return } } type numericMapKeyEncoder struct { encoder ValEncoder } func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.writeByte('"') encoder.encoder.Encode(ptr, stream) stream.writeByte('"') } func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } type dynamicMapKeyEncoder struct { ctx *ctx valType reflect2.Type } func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { obj := encoder.valType.UnsafeIndirect(ptr) encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) } func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { obj := encoder.valType.UnsafeIndirect(ptr) return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) } type mapEncoder struct { mapType *reflect2.UnsafeMapType keyEncoder ValEncoder elemEncoder ValEncoder } func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if *(*unsafe.Pointer)(ptr) == nil { stream.WriteNil() return } stream.WriteObjectStart() iter := encoder.mapType.UnsafeIterate(ptr) for i := 0; iter.HasNext(); i++ { if i != 0 { stream.WriteMore() } key, elem := iter.UnsafeNext() encoder.keyEncoder.Encode(key, stream) if stream.indention > 0 { stream.writeTwoBytes(byte(':'), byte(' ')) } else { stream.writeByte(':') } encoder.elemEncoder.Encode(elem, stream) } stream.WriteObjectEnd() } func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool { iter := encoder.mapType.UnsafeIterate(ptr) return !iter.HasNext() } type sortKeysMapEncoder struct { mapType *reflect2.UnsafeMapType keyEncoder ValEncoder elemEncoder ValEncoder } func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if *(*unsafe.Pointer)(ptr) == nil { stream.WriteNil() return } stream.WriteObjectStart() mapIter := encoder.mapType.UnsafeIterate(ptr) subStream := stream.cfg.BorrowStream(nil) subStream.Attachment = stream.Attachment subIter := stream.cfg.BorrowIterator(nil) keyValues := encodedKeyValues{} for mapIter.HasNext() { key, elem := mapIter.UnsafeNext() subStreamIndex := subStream.Buffered() encoder.keyEncoder.Encode(key, subStream) if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil { stream.Error = subStream.Error } encodedKey := subStream.Buffer()[subStreamIndex:] subIter.ResetBytes(encodedKey) decodedKey := subIter.ReadString() if stream.indention > 0 { subStream.writeTwoBytes(byte(':'), byte(' ')) } else { subStream.writeByte(':') } encoder.elemEncoder.Encode(elem, subStream) keyValues = append(keyValues, encodedKV{ key: decodedKey, keyValue: subStream.Buffer()[subStreamIndex:], }) } sort.Sort(keyValues) for i, keyValue := range keyValues { if i != 0 { stream.WriteMore() } stream.Write(keyValue.keyValue) } if subStream.Error != nil && stream.Error == nil { stream.Error = subStream.Error } stream.WriteObjectEnd() stream.cfg.ReturnStream(subStream) stream.cfg.ReturnIterator(subIter) } func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool { iter := encoder.mapType.UnsafeIterate(ptr) return !iter.HasNext() } type encodedKeyValues []encodedKV type encodedKV struct { key string keyValue []byte } func (sv encodedKeyValues) Len() int { return len(sv) } func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }
package jsoniter import ( "encoding" "encoding/json" "unsafe" "github.com/modern-go/reflect2" ) var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem() var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem() var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem() var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem() func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder { ptrType := reflect2.PtrTo(typ) if ptrType.Implements(unmarshalerType) { return &referenceDecoder{ &unmarshalerDecoder{ptrType}, } } if ptrType.Implements(textUnmarshalerType) { return &referenceDecoder{ &textUnmarshalerDecoder{ptrType}, } } return nil } func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder { if typ == marshalerType { checkIsEmpty := createCheckIsEmpty(ctx, typ) var encoder ValEncoder = &directMarshalerEncoder{ checkIsEmpty: checkIsEmpty, } return encoder } if typ.Implements(marshalerType) { checkIsEmpty := createCheckIsEmpty(ctx, typ) var encoder ValEncoder = &marshalerEncoder{ valType: typ, checkIsEmpty: checkIsEmpty, } return encoder } ptrType := reflect2.PtrTo(typ) if ctx.prefix != "" && ptrType.Implements(marshalerType) { checkIsEmpty := createCheckIsEmpty(ctx, ptrType) var encoder ValEncoder = &marshalerEncoder{ valType: ptrType, checkIsEmpty: checkIsEmpty, } return &referenceEncoder{encoder} } if typ == textMarshalerType { checkIsEmpty := createCheckIsEmpty(ctx, typ) var encoder ValEncoder = &directTextMarshalerEncoder{ checkIsEmpty: checkIsEmpty, stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), } return encoder } if typ.Implements(textMarshalerType) { checkIsEmpty := createCheckIsEmpty(ctx, typ) var encoder ValEncoder = &textMarshalerEncoder{ valType: typ, stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), checkIsEmpty: checkIsEmpty, } return encoder } // if prefix is empty, the type is the root type if ctx.prefix != "" && ptrType.Implements(textMarshalerType) { checkIsEmpty := createCheckIsEmpty(ctx, ptrType) var encoder ValEncoder = &textMarshalerEncoder{ valType: ptrType, stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), checkIsEmpty: checkIsEmpty, } return &referenceEncoder{encoder} } return nil } type marshalerEncoder struct { checkIsEmpty checkIsEmpty valType reflect2.Type } func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { obj := encoder.valType.UnsafeIndirect(ptr) if encoder.valType.IsNullable() && reflect2.IsNil(obj) { stream.WriteNil() return } marshaler := obj.(json.Marshaler) bytes, err := marshaler.MarshalJSON() if err != nil { stream.Error = err } else { // html escape was already done by jsoniter // but the extra '\n' should be trimed l := len(bytes) if l > 0 && bytes[l-1] == '\n' { bytes = bytes[:l-1] } stream.Write(bytes) } } func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.checkIsEmpty.IsEmpty(ptr) } type directMarshalerEncoder struct { checkIsEmpty checkIsEmpty } func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { marshaler := *(*json.Marshaler)(ptr) if marshaler == nil { stream.WriteNil() return } bytes, err := marshaler.MarshalJSON() if err != nil { stream.Error = err } else { stream.Write(bytes) } } func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.checkIsEmpty.IsEmpty(ptr) } type textMarshalerEncoder struct { valType reflect2.Type stringEncoder ValEncoder checkIsEmpty checkIsEmpty } func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { obj := encoder.valType.UnsafeIndirect(ptr) if encoder.valType.IsNullable() && reflect2.IsNil(obj) { stream.WriteNil() return } marshaler := (obj).(encoding.TextMarshaler) bytes, err := marshaler.MarshalText() if err != nil { stream.Error = err } else { str := string(bytes) encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) } } func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.checkIsEmpty.IsEmpty(ptr) } type directTextMarshalerEncoder struct { stringEncoder ValEncoder checkIsEmpty checkIsEmpty } func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { marshaler := *(*encoding.TextMarshaler)(ptr) if marshaler == nil { stream.WriteNil() return } bytes, err := marshaler.MarshalText() if err != nil { stream.Error = err } else { str := string(bytes) encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) } } func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.checkIsEmpty.IsEmpty(ptr) } type unmarshalerDecoder struct { valType reflect2.Type } func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { valType := decoder.valType obj := valType.UnsafeIndirect(ptr) unmarshaler := obj.(json.Unmarshaler) iter.nextToken() iter.unreadByte() // skip spaces bytes := iter.SkipAndReturnBytes() err := unmarshaler.UnmarshalJSON(bytes) if err != nil { iter.ReportError("unmarshalerDecoder", err.Error()) } } type textUnmarshalerDecoder struct { valType reflect2.Type } func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { valType := decoder.valType obj := valType.UnsafeIndirect(ptr) if reflect2.IsNil(obj) { ptrType := valType.(*reflect2.UnsafePtrType) elemType := ptrType.Elem() elem := elemType.UnsafeNew() ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem)) obj = valType.UnsafeIndirect(ptr) } unmarshaler := (obj).(encoding.TextUnmarshaler) str := iter.ReadString() err := unmarshaler.UnmarshalText([]byte(str)) if err != nil { iter.ReportError("textUnmarshalerDecoder", err.Error()) } }
package jsoniter import ( "encoding/base64" "reflect" "strconv" "unsafe" "github.com/modern-go/reflect2" ) const ptrSize = 32 << uintptr(^uintptr(0)>>63) func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder { if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { sliceDecoder := decoderOfSlice(ctx, typ) return &base64Codec{sliceDecoder: sliceDecoder} } typeName := typ.String() kind := typ.Kind() switch kind { case reflect.String: if typeName != "string" { return encoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) } return &stringCodec{} case reflect.Int: if typeName != "int" { return encoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) } if strconv.IntSize == 32 { return &int32Codec{} } return &int64Codec{} case reflect.Int8: if typeName != "int8" { return encoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) } return &int8Codec{} case reflect.Int16: if typeName != "int16" { return encoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) } return &int16Codec{} case reflect.Int32: if typeName != "int32" { return encoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) } return &int32Codec{} case reflect.Int64: if typeName != "int64" { return encoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) } return &int64Codec{} case reflect.Uint: if typeName != "uint" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) } if strconv.IntSize == 32 { return &uint32Codec{} } return &uint64Codec{} case reflect.Uint8: if typeName != "uint8" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) } return &uint8Codec{} case reflect.Uint16: if typeName != "uint16" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) } return &uint16Codec{} case reflect.Uint32: if typeName != "uint32" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) } return &uint32Codec{} case reflect.Uintptr: if typeName != "uintptr" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) } if ptrSize == 32 { return &uint32Codec{} } return &uint64Codec{} case reflect.Uint64: if typeName != "uint64" { return encoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) } return &uint64Codec{} case reflect.Float32: if typeName != "float32" { return encoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) } return &float32Codec{} case reflect.Float64: if typeName != "float64" { return encoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) } return &float64Codec{} case reflect.Bool: if typeName != "bool" { return encoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) } return &boolCodec{} } return nil } func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder { if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { sliceDecoder := decoderOfSlice(ctx, typ) return &base64Codec{sliceDecoder: sliceDecoder} } typeName := typ.String() switch typ.Kind() { case reflect.String: if typeName != "string" { return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) } return &stringCodec{} case reflect.Int: if typeName != "int" { return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) } if strconv.IntSize == 32 { return &int32Codec{} } return &int64Codec{} case reflect.Int8: if typeName != "int8" { return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) } return &int8Codec{} case reflect.Int16: if typeName != "int16" { return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) } return &int16Codec{} case reflect.Int32: if typeName != "int32" { return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) } return &int32Codec{} case reflect.Int64: if typeName != "int64" { return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) } return &int64Codec{} case reflect.Uint: if typeName != "uint" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) } if strconv.IntSize == 32 { return &uint32Codec{} } return &uint64Codec{} case reflect.Uint8: if typeName != "uint8" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) } return &uint8Codec{} case reflect.Uint16: if typeName != "uint16" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) } return &uint16Codec{} case reflect.Uint32: if typeName != "uint32" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) } return &uint32Codec{} case reflect.Uintptr: if typeName != "uintptr" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) } if ptrSize == 32 { return &uint32Codec{} } return &uint64Codec{} case reflect.Uint64: if typeName != "uint64" { return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) } return &uint64Codec{} case reflect.Float32: if typeName != "float32" { return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) } return &float32Codec{} case reflect.Float64: if typeName != "float64" { return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) } return &float64Codec{} case reflect.Bool: if typeName != "bool" { return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) } return &boolCodec{} } return nil } type stringCodec struct { } func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { *((*string)(ptr)) = iter.ReadString() } func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) { str := *((*string)(ptr)) stream.WriteString(str) } func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool { return *((*string)(ptr)) == "" } type int8Codec struct { } func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*int8)(ptr)) = iter.ReadInt8() } } func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteInt8(*((*int8)(ptr))) } func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*int8)(ptr)) == 0 } type int16Codec struct { } func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*int16)(ptr)) = iter.ReadInt16() } } func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteInt16(*((*int16)(ptr))) } func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*int16)(ptr)) == 0 } type int32Codec struct { } func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*int32)(ptr)) = iter.ReadInt32() } } func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteInt32(*((*int32)(ptr))) } func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*int32)(ptr)) == 0 } type int64Codec struct { } func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*int64)(ptr)) = iter.ReadInt64() } } func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteInt64(*((*int64)(ptr))) } func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*int64)(ptr)) == 0 } type uint8Codec struct { } func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*uint8)(ptr)) = iter.ReadUint8() } } func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteUint8(*((*uint8)(ptr))) } func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*uint8)(ptr)) == 0 } type uint16Codec struct { } func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*uint16)(ptr)) = iter.ReadUint16() } } func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteUint16(*((*uint16)(ptr))) } func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*uint16)(ptr)) == 0 } type uint32Codec struct { } func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*uint32)(ptr)) = iter.ReadUint32() } } func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteUint32(*((*uint32)(ptr))) } func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*uint32)(ptr)) == 0 } type uint64Codec struct { } func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*uint64)(ptr)) = iter.ReadUint64() } } func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteUint64(*((*uint64)(ptr))) } func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*uint64)(ptr)) == 0 } type float32Codec struct { } func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*float32)(ptr)) = iter.ReadFloat32() } } func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteFloat32(*((*float32)(ptr))) } func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*float32)(ptr)) == 0 } type float64Codec struct { } func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*float64)(ptr)) = iter.ReadFloat64() } } func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteFloat64(*((*float64)(ptr))) } func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool { return *((*float64)(ptr)) == 0 } type boolCodec struct { } func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.ReadNil() { *((*bool)(ptr)) = iter.ReadBool() } } func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteBool(*((*bool)(ptr))) } func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool { return !(*((*bool)(ptr))) } type base64Codec struct { sliceType *reflect2.UnsafeSliceType sliceDecoder ValDecoder } func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.ReadNil() { codec.sliceType.UnsafeSetNil(ptr) return } switch iter.WhatIsNext() { case StringValue: src := iter.ReadString() dst, err := base64.StdEncoding.DecodeString(src) if err != nil { iter.ReportError("decode base64", err.Error()) } else { codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) } case ArrayValue: codec.sliceDecoder.Decode(ptr, iter) default: iter.ReportError("base64Codec", "invalid input") } } func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { if codec.sliceType.UnsafeIsNil(ptr) { stream.WriteNil() return } src := *((*[]byte)(ptr)) encoding := base64.StdEncoding stream.writeByte('"') if len(src) != 0 { size := encoding.EncodedLen(len(src)) buf := make([]byte, size) encoding.Encode(buf, src) stream.buf = append(stream.buf, buf...) } stream.writeByte('"') } func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*[]byte)(ptr))) == 0 }
package jsoniter import ( "github.com/modern-go/reflect2" "unsafe" ) func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder { ptrType := typ.(*reflect2.UnsafePtrType) elemType := ptrType.Elem() decoder := decoderOfType(ctx, elemType) return &OptionalDecoder{elemType, decoder} } func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder { ptrType := typ.(*reflect2.UnsafePtrType) elemType := ptrType.Elem() elemEncoder := encoderOfType(ctx, elemType) encoder := &OptionalEncoder{elemEncoder} return encoder } type OptionalDecoder struct { ValueType reflect2.Type ValueDecoder ValDecoder } func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.ReadNil() { *((*unsafe.Pointer)(ptr)) = nil } else { if *((*unsafe.Pointer)(ptr)) == nil { //pointer to null, we have to allocate memory to hold the value newPtr := decoder.ValueType.UnsafeNew() decoder.ValueDecoder.Decode(newPtr, iter) *((*unsafe.Pointer)(ptr)) = newPtr } else { //reuse existing instance decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) } } } type dereferenceDecoder struct { // only to deference a pointer valueType reflect2.Type valueDecoder ValDecoder } func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if *((*unsafe.Pointer)(ptr)) == nil { //pointer to null, we have to allocate memory to hold the value newPtr := decoder.valueType.UnsafeNew() decoder.valueDecoder.Decode(newPtr, iter) *((*unsafe.Pointer)(ptr)) = newPtr } else { //reuse existing instance decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) } } type OptionalEncoder struct { ValueEncoder ValEncoder } func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if *((*unsafe.Pointer)(ptr)) == nil { stream.WriteNil() } else { encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) } } func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { return *((*unsafe.Pointer)(ptr)) == nil } type dereferenceEncoder struct { ValueEncoder ValEncoder } func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if *((*unsafe.Pointer)(ptr)) == nil { stream.WriteNil() } else { encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) } } func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { dePtr := *((*unsafe.Pointer)(ptr)) if dePtr == nil { return true } return encoder.ValueEncoder.IsEmpty(dePtr) } func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { deReferenced := *((*unsafe.Pointer)(ptr)) if deReferenced == nil { return true } isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil) if !converted { return false } fieldPtr := unsafe.Pointer(deReferenced) return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) } type referenceEncoder struct { encoder ValEncoder } func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) } func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) } type referenceDecoder struct { decoder ValDecoder } func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.decoder.Decode(unsafe.Pointer(&ptr), iter) }
package jsoniter import ( "fmt" "github.com/modern-go/reflect2" "io" "unsafe" ) func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder { sliceType := typ.(*reflect2.UnsafeSliceType) decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) return &sliceDecoder{sliceType, decoder} } func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder { sliceType := typ.(*reflect2.UnsafeSliceType) encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) return &sliceEncoder{sliceType, encoder} } type sliceEncoder struct { sliceType *reflect2.UnsafeSliceType elemEncoder ValEncoder } func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if encoder.sliceType.UnsafeIsNil(ptr) { stream.WriteNil() return } length := encoder.sliceType.UnsafeLengthOf(ptr) if length == 0 { stream.WriteEmptyArray() return } stream.WriteArrayStart() encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream) for i := 1; i < length; i++ { stream.WriteMore() elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i) encoder.elemEncoder.Encode(elemPtr, stream) } stream.WriteArrayEnd() if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error()) } } func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.sliceType.UnsafeLengthOf(ptr) == 0 } type sliceDecoder struct { sliceType *reflect2.UnsafeSliceType elemDecoder ValDecoder } func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.doDecode(ptr, iter) if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error()) } } func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { c := iter.nextToken() sliceType := decoder.sliceType if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') sliceType.UnsafeSetNil(ptr) return } if c != '[' { iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c})) return } c = iter.nextToken() if c == ']' { sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0)) return } iter.unreadByte() sliceType.UnsafeGrow(ptr, 1) elemPtr := sliceType.UnsafeGetIndex(ptr, 0) decoder.elemDecoder.Decode(elemPtr, iter) length := 1 for c = iter.nextToken(); c == ','; c = iter.nextToken() { idx := length length += 1 sliceType.UnsafeGrow(ptr, length) elemPtr = sliceType.UnsafeGetIndex(ptr, idx) decoder.elemDecoder.Decode(elemPtr, iter) } if c != ']' { iter.ReportError("decode slice", "expect ], but found "+string([]byte{c})) return } }
package jsoniter import ( "fmt" "io" "strings" "unsafe" "github.com/modern-go/reflect2" ) func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { bindings := map[string]*Binding{} structDescriptor := describeStruct(ctx, typ) for _, binding := range structDescriptor.Fields { for _, fromName := range binding.FromNames { old := bindings[fromName] if old == nil { bindings[fromName] = binding continue } ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding) if ignoreOld { delete(bindings, fromName) } if !ignoreNew { bindings[fromName] = binding } } } fields := map[string]*structFieldDecoder{} for k, binding := range bindings { fields[k] = binding.Decoder.(*structFieldDecoder) } if !ctx.caseSensitive() { for k, binding := range bindings { if _, found := fields[strings.ToLower(k)]; !found { fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) } } } return createStructDecoder(ctx, typ, fields) } func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder { if ctx.disallowUnknownFields { return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true} } knownHash := map[int64]struct{}{ 0: {}, } switch len(fields) { case 0: return &skipObjectDecoder{typ} case 1: for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder} } case 2: var fieldHash1 int64 var fieldHash2 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldHash1 == 0 { fieldHash1 = fieldHash fieldDecoder1 = fieldDecoder } else { fieldHash2 = fieldHash fieldDecoder2 = fieldDecoder } } return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2} case 3: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } } return &threeFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3} case 4: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } } return &fourFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4} case 5: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } } return &fiveFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5} case 6: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldName6 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } } return &sixFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6} case 7: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldName6 int64 var fieldName7 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } } return &sevenFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7} case 8: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldName6 int64 var fieldName7 int64 var fieldName8 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } } return &eightFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8} case 9: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldName6 int64 var fieldName7 int64 var fieldName8 int64 var fieldName9 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else if fieldName8 == 0 { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } else { fieldName9 = fieldHash fieldDecoder9 = fieldDecoder } } return &nineFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9} case 10: var fieldName1 int64 var fieldName2 int64 var fieldName3 int64 var fieldName4 int64 var fieldName5 int64 var fieldName6 int64 var fieldName7 int64 var fieldName8 int64 var fieldName9 int64 var fieldName10 int64 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder var fieldDecoder10 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} } knownHash[fieldHash] = struct{}{} if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else if fieldName8 == 0 { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } else if fieldName9 == 0 { fieldName9 = fieldHash fieldDecoder9 = fieldDecoder } else { fieldName10 = fieldHash fieldDecoder10 = fieldDecoder } } return &tenFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, fieldName10, fieldDecoder10} } return &generalStructDecoder{typ, fields, false} } type generalStructDecoder struct { typ reflect2.Type fields map[string]*structFieldDecoder disallowUnknownFields bool } func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } var c byte for c = ','; c == ','; c = iter.nextToken() { decoder.decodeOneField(ptr, iter) } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } if c != '}' { iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c})) } iter.decrementDepth() } func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) { var field string var fieldDecoder *structFieldDecoder if iter.cfg.objectFieldMustBeSimpleString { fieldBytes := iter.ReadStringAsSlice() field = *(*string)(unsafe.Pointer(&fieldBytes)) fieldDecoder = decoder.fields[field] if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } else { field = iter.ReadString() fieldDecoder = decoder.fields[field] if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } if fieldDecoder == nil { if decoder.disallowUnknownFields { msg := "found unknown field: " + field iter.ReportError("ReadObject", msg) } c := iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } iter.Skip() return } c := iter.nextToken() if c != ':' { iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) } fieldDecoder.Decode(ptr, iter) } type skipObjectDecoder struct { typ reflect2.Type } func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { valueType := iter.WhatIsNext() if valueType != ObjectValue && valueType != NilValue { iter.ReportError("skipObjectDecoder", "expect object or null") return } iter.Skip() } type oneFieldStructDecoder struct { typ reflect2.Type fieldHash int64 fieldDecoder *structFieldDecoder } func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { if iter.readFieldHash() == decoder.fieldHash { decoder.fieldDecoder.Decode(ptr, iter) } else { iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type twoFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder } func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type threeFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder } func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type fourFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder } func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type fiveFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder } func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type sixFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder fieldHash6 int64 fieldDecoder6 *structFieldDecoder } func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type sevenFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder fieldHash6 int64 fieldDecoder6 *structFieldDecoder fieldHash7 int64 fieldDecoder7 *structFieldDecoder } func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.Decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type eightFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder fieldHash6 int64 fieldDecoder6 *structFieldDecoder fieldHash7 int64 fieldDecoder7 *structFieldDecoder fieldHash8 int64 fieldDecoder8 *structFieldDecoder } func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.Decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.Decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type nineFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder fieldHash6 int64 fieldDecoder6 *structFieldDecoder fieldHash7 int64 fieldDecoder7 *structFieldDecoder fieldHash8 int64 fieldDecoder8 *structFieldDecoder fieldHash9 int64 fieldDecoder9 *structFieldDecoder } func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.Decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.Decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.Decode(ptr, iter) case decoder.fieldHash9: decoder.fieldDecoder9.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type tenFieldsStructDecoder struct { typ reflect2.Type fieldHash1 int64 fieldDecoder1 *structFieldDecoder fieldHash2 int64 fieldDecoder2 *structFieldDecoder fieldHash3 int64 fieldDecoder3 *structFieldDecoder fieldHash4 int64 fieldDecoder4 *structFieldDecoder fieldHash5 int64 fieldDecoder5 *structFieldDecoder fieldHash6 int64 fieldDecoder6 *structFieldDecoder fieldHash7 int64 fieldDecoder7 *structFieldDecoder fieldHash8 int64 fieldDecoder8 *structFieldDecoder fieldHash9 int64 fieldDecoder9 *structFieldDecoder fieldHash10 int64 fieldDecoder10 *structFieldDecoder } func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } if !iter.incrementDepth() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.Decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.Decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.Decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.Decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.Decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.Decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.Decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.Decode(ptr, iter) case decoder.fieldHash9: decoder.fieldDecoder9.Decode(ptr, iter) case decoder.fieldHash10: decoder.fieldDecoder10.Decode(ptr, iter) default: iter.Skip() } if iter.isObjectEnd() { break } } if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } iter.decrementDepth() } type structFieldDecoder struct { field reflect2.StructField fieldDecoder ValDecoder } func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { fieldPtr := decoder.field.UnsafeGet(ptr) decoder.fieldDecoder.Decode(fieldPtr, iter) if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error()) } } type stringModeStringDecoder struct { elemDecoder ValDecoder cfg *frozenConfig } func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.elemDecoder.Decode(ptr, iter) str := *((*string)(ptr)) tempIter := decoder.cfg.BorrowIterator([]byte(str)) defer decoder.cfg.ReturnIterator(tempIter) *((*string)(ptr)) = tempIter.ReadString() } type stringModeNumberDecoder struct { elemDecoder ValDecoder } func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { if iter.WhatIsNext() == NilValue { decoder.elemDecoder.Decode(ptr, iter) return } c := iter.nextToken() if c != '"' { iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) return } decoder.elemDecoder.Decode(ptr, iter) if iter.Error != nil { return } c = iter.readByte() if c != '"' { iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) return } }
package jsoniter import ( "fmt" "github.com/modern-go/reflect2" "io" "reflect" "unsafe" ) func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder { type bindingTo struct { binding *Binding toName string ignored bool } orderedBindings := []*bindingTo{} structDescriptor := describeStruct(ctx, typ) for _, binding := range structDescriptor.Fields { for _, toName := range binding.ToNames { new := &bindingTo{ binding: binding, toName: toName, } for _, old := range orderedBindings { if old.toName != toName { continue } old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding) } orderedBindings = append(orderedBindings, new) } } if len(orderedBindings) == 0 { return &emptyStructEncoder{} } finalOrderedFields := []structFieldTo{} for _, bindingTo := range orderedBindings { if !bindingTo.ignored { finalOrderedFields = append(finalOrderedFields, structFieldTo{ encoder: bindingTo.binding.Encoder.(*structFieldEncoder), toName: bindingTo.toName, }) } } return &structEncoder{typ, finalOrderedFields} } func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty { encoder := createEncoderOfNative(ctx, typ) if encoder != nil { return encoder } kind := typ.Kind() switch kind { case reflect.Interface: return &dynamicEncoder{typ} case reflect.Struct: return &structEncoder{typ: typ} case reflect.Array: return &arrayEncoder{} case reflect.Slice: return &sliceEncoder{} case reflect.Map: return encoderOfMap(ctx, typ) case reflect.Ptr: return &OptionalEncoder{} default: return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)} } } func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) { newTagged := new.Field.Tag().Get(cfg.getTagKey()) != "" oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != "" if newTagged { if oldTagged { if len(old.levels) > len(new.levels) { return true, false } else if len(new.levels) > len(old.levels) { return false, true } else { return true, true } } else { return true, false } } else { if oldTagged { return true, false } if len(old.levels) > len(new.levels) { return true, false } else if len(new.levels) > len(old.levels) { return false, true } else { return true, true } } } type structFieldEncoder struct { field reflect2.StructField fieldEncoder ValEncoder omitempty bool } func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { fieldPtr := encoder.field.UnsafeGet(ptr) encoder.fieldEncoder.Encode(fieldPtr, stream) if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error()) } } func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool { fieldPtr := encoder.field.UnsafeGet(ptr) return encoder.fieldEncoder.IsEmpty(fieldPtr) } func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil) if !converted { return false } fieldPtr := encoder.field.UnsafeGet(ptr) return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) } type IsEmbeddedPtrNil interface { IsEmbeddedPtrNil(ptr unsafe.Pointer) bool } type structEncoder struct { typ reflect2.Type fields []structFieldTo } type structFieldTo struct { encoder *structFieldEncoder toName string } func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteObjectStart() isNotFirst := false for _, field := range encoder.fields { if field.encoder.omitempty && field.encoder.IsEmpty(ptr) { continue } if field.encoder.IsEmbeddedPtrNil(ptr) { continue } if isNotFirst { stream.WriteMore() } stream.WriteObjectField(field.toName) field.encoder.Encode(ptr, stream) isNotFirst = true } stream.WriteObjectEnd() if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error()) } } func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } type emptyStructEncoder struct { } func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteEmptyObject() } func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } type stringModeNumberEncoder struct { elemEncoder ValEncoder } func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { stream.writeByte('"') encoder.elemEncoder.Encode(ptr, stream) stream.writeByte('"') } func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.elemEncoder.IsEmpty(ptr) } type stringModeStringEncoder struct { elemEncoder ValEncoder cfg *frozenConfig } func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { tempStream := encoder.cfg.BorrowStream(nil) tempStream.Attachment = stream.Attachment defer encoder.cfg.ReturnStream(tempStream) encoder.elemEncoder.Encode(ptr, tempStream) stream.WriteString(string(tempStream.Buffer())) } func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.elemEncoder.IsEmpty(ptr) }
package jsoniter import ( "io" ) // stream is a io.Writer like object, with JSON specific write functions. // Error is not returned as return value, but stored as Error member on this stream instance. type Stream struct { cfg *frozenConfig out io.Writer buf []byte Error error indention int Attachment interface{} // open for customized encoder } // NewStream create new stream instance. // cfg can be jsoniter.ConfigDefault. // out can be nil if write to internal buffer. // bufSize is the initial size for the internal buffer in bytes. func NewStream(cfg API, out io.Writer, bufSize int) *Stream { return &Stream{ cfg: cfg.(*frozenConfig), out: out, buf: make([]byte, 0, bufSize), Error: nil, indention: 0, } } // Pool returns a pool can provide more stream with same configuration func (stream *Stream) Pool() StreamPool { return stream.cfg } // Reset reuse this stream instance by assign a new writer func (stream *Stream) Reset(out io.Writer) { stream.out = out stream.buf = stream.buf[:0] } // Available returns how many bytes are unused in the buffer. func (stream *Stream) Available() int { return cap(stream.buf) - len(stream.buf) } // Buffered returns the number of bytes that have been written into the current buffer. func (stream *Stream) Buffered() int { return len(stream.buf) } // Buffer if writer is nil, use this method to take the result func (stream *Stream) Buffer() []byte { return stream.buf } // SetBuffer allows to append to the internal buffer directly func (stream *Stream) SetBuffer(buf []byte) { stream.buf = buf } // Write writes the contents of p into the buffer. // It returns the number of bytes written. // If nn < len(p), it also returns an error explaining // why the write is short. func (stream *Stream) Write(p []byte) (nn int, err error) { stream.buf = append(stream.buf, p...) if stream.out != nil { nn, err = stream.out.Write(stream.buf) stream.buf = stream.buf[nn:] return } return len(p), nil } // WriteByte writes a single byte. func (stream *Stream) writeByte(c byte) { stream.buf = append(stream.buf, c) } func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) { stream.buf = append(stream.buf, c1, c2) } func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) { stream.buf = append(stream.buf, c1, c2, c3) } func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) { stream.buf = append(stream.buf, c1, c2, c3, c4) } func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) { stream.buf = append(stream.buf, c1, c2, c3, c4, c5) } // Flush writes any buffered data to the underlying io.Writer. func (stream *Stream) Flush() error { if stream.out == nil { return nil } if stream.Error != nil { return stream.Error } _, err := stream.out.Write(stream.buf) if err != nil { if stream.Error == nil { stream.Error = err } return err } stream.buf = stream.buf[:0] return nil } // WriteRaw write string out without quotes, just like []byte func (stream *Stream) WriteRaw(s string) { stream.buf = append(stream.buf, s...) } // WriteNil write null to stream func (stream *Stream) WriteNil() { stream.writeFourBytes('n', 'u', 'l', 'l') } // WriteTrue write true to stream func (stream *Stream) WriteTrue() { stream.writeFourBytes('t', 'r', 'u', 'e') } // WriteFalse write false to stream func (stream *Stream) WriteFalse() { stream.writeFiveBytes('f', 'a', 'l', 's', 'e') } // WriteBool write true or false into stream func (stream *Stream) WriteBool(val bool) { if val { stream.WriteTrue() } else { stream.WriteFalse() } } // WriteObjectStart write { with possible indention func (stream *Stream) WriteObjectStart() { stream.indention += stream.cfg.indentionStep stream.writeByte('{') stream.writeIndention(0) } // WriteObjectField write "field": with possible indention func (stream *Stream) WriteObjectField(field string) { stream.WriteString(field) if stream.indention > 0 { stream.writeTwoBytes(':', ' ') } else { stream.writeByte(':') } } // WriteObjectEnd write } with possible indention func (stream *Stream) WriteObjectEnd() { stream.writeIndention(stream.cfg.indentionStep) stream.indention -= stream.cfg.indentionStep stream.writeByte('}') } // WriteEmptyObject write {} func (stream *Stream) WriteEmptyObject() { stream.writeByte('{') stream.writeByte('}') } // WriteMore write , with possible indention func (stream *Stream) WriteMore() { stream.writeByte(',') stream.writeIndention(0) } // WriteArrayStart write [ with possible indention func (stream *Stream) WriteArrayStart() { stream.indention += stream.cfg.indentionStep stream.writeByte('[') stream.writeIndention(0) } // WriteEmptyArray write [] func (stream *Stream) WriteEmptyArray() { stream.writeTwoBytes('[', ']') } // WriteArrayEnd write ] with possible indention func (stream *Stream) WriteArrayEnd() { stream.writeIndention(stream.cfg.indentionStep) stream.indention -= stream.cfg.indentionStep stream.writeByte(']') } func (stream *Stream) writeIndention(delta int) { if stream.indention == 0 { return } stream.writeByte('\n') toWrite := stream.indention - delta for i := 0; i < toWrite; i++ { stream.buf = append(stream.buf, ' ') } }
package jsoniter import ( "fmt" "math" "strconv" ) var pow10 []uint64 func init() { pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000} } // WriteFloat32 write float32 to stream func (stream *Stream) WriteFloat32(val float32) { if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) { stream.Error = fmt.Errorf("unsupported value: %f", val) return } abs := math.Abs(float64(val)) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. if abs != 0 { if float32(abs) < 1e-6 || float32(abs) >= 1e21 { fmt = 'e' } } stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32) if fmt == 'e' { // clean up e-09 to e-9 n := len(stream.buf) if n >= 4 && stream.buf[n-4] == 'e' && stream.buf[n-3] == '-' && stream.buf[n-2] == '0' { stream.buf[n-2] = stream.buf[n-1] stream.buf = stream.buf[:n-1] } } } // WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster func (stream *Stream) WriteFloat32Lossy(val float32) { if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) { stream.Error = fmt.Errorf("unsupported value: %f", val) return } if val < 0 { stream.writeByte('-') val = -val } if val > 0x4ffffff { stream.WriteFloat32(val) return } precision := 6 exp := uint64(1000000) // 6 lval := uint64(float64(val)*float64(exp) + 0.5) stream.WriteUint64(lval / exp) fval := lval % exp if fval == 0 { return } stream.writeByte('.') for p := precision - 1; p > 0 && fval < pow10[p]; p-- { stream.writeByte('0') } stream.WriteUint64(fval) for stream.buf[len(stream.buf)-1] == '0' { stream.buf = stream.buf[:len(stream.buf)-1] } } // WriteFloat64 write float64 to stream func (stream *Stream) WriteFloat64(val float64) { if math.IsInf(val, 0) || math.IsNaN(val) { stream.Error = fmt.Errorf("unsupported value: %f", val) return } abs := math.Abs(val) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. if abs != 0 { if abs < 1e-6 || abs >= 1e21 { fmt = 'e' } } stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64) if fmt == 'e' { // clean up e-09 to e-9 n := len(stream.buf) if n >= 4 && stream.buf[n-4] == 'e' && stream.buf[n-3] == '-' && stream.buf[n-2] == '0' { stream.buf[n-2] = stream.buf[n-1] stream.buf = stream.buf[:n-1] } } } // WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster func (stream *Stream) WriteFloat64Lossy(val float64) { if math.IsInf(val, 0) || math.IsNaN(val) { stream.Error = fmt.Errorf("unsupported value: %f", val) return } if val < 0 { stream.writeByte('-') val = -val } if val > 0x4ffffff { stream.WriteFloat64(val) return } precision := 6 exp := uint64(1000000) // 6 lval := uint64(val*float64(exp) + 0.5) stream.WriteUint64(lval / exp) fval := lval % exp if fval == 0 { return } stream.writeByte('.') for p := precision - 1; p > 0 && fval < pow10[p]; p-- { stream.writeByte('0') } stream.WriteUint64(fval) for stream.buf[len(stream.buf)-1] == '0' { stream.buf = stream.buf[:len(stream.buf)-1] } }
package jsoniter var digits []uint32 func init() { digits = make([]uint32, 1000) for i := uint32(0); i < 1000; i++ { digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0' if i < 10 { digits[i] += 2 << 24 } else if i < 100 { digits[i] += 1 << 24 } } } func writeFirstBuf(space []byte, v uint32) []byte { start := v >> 24 if start == 0 { space = append(space, byte(v>>16), byte(v>>8)) } else if start == 1 { space = append(space, byte(v>>8)) } space = append(space, byte(v)) return space } func writeBuf(buf []byte, v uint32) []byte { return append(buf, byte(v>>16), byte(v>>8), byte(v)) } // WriteUint8 write uint8 to stream func (stream *Stream) WriteUint8(val uint8) { stream.buf = writeFirstBuf(stream.buf, digits[val]) } // WriteInt8 write int8 to stream func (stream *Stream) WriteInt8(nval int8) { var val uint8 if nval < 0 { val = uint8(-nval) stream.buf = append(stream.buf, '-') } else { val = uint8(nval) } stream.buf = writeFirstBuf(stream.buf, digits[val]) } // WriteUint16 write uint16 to stream func (stream *Stream) WriteUint16(val uint16) { q1 := val / 1000 if q1 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[val]) return } r1 := val - q1*1000 stream.buf = writeFirstBuf(stream.buf, digits[q1]) stream.buf = writeBuf(stream.buf, digits[r1]) return } // WriteInt16 write int16 to stream func (stream *Stream) WriteInt16(nval int16) { var val uint16 if nval < 0 { val = uint16(-nval) stream.buf = append(stream.buf, '-') } else { val = uint16(nval) } stream.WriteUint16(val) } // WriteUint32 write uint32 to stream func (stream *Stream) WriteUint32(val uint32) { q1 := val / 1000 if q1 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[val]) return } r1 := val - q1*1000 q2 := q1 / 1000 if q2 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q1]) stream.buf = writeBuf(stream.buf, digits[r1]) return } r2 := q1 - q2*1000 q3 := q2 / 1000 if q3 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q2]) } else { r3 := q2 - q3*1000 stream.buf = append(stream.buf, byte(q3+'0')) stream.buf = writeBuf(stream.buf, digits[r3]) } stream.buf = writeBuf(stream.buf, digits[r2]) stream.buf = writeBuf(stream.buf, digits[r1]) } // WriteInt32 write int32 to stream func (stream *Stream) WriteInt32(nval int32) { var val uint32 if nval < 0 { val = uint32(-nval) stream.buf = append(stream.buf, '-') } else { val = uint32(nval) } stream.WriteUint32(val) } // WriteUint64 write uint64 to stream func (stream *Stream) WriteUint64(val uint64) { q1 := val / 1000 if q1 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[val]) return } r1 := val - q1*1000 q2 := q1 / 1000 if q2 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q1]) stream.buf = writeBuf(stream.buf, digits[r1]) return } r2 := q1 - q2*1000 q3 := q2 / 1000 if q3 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q2]) stream.buf = writeBuf(stream.buf, digits[r2]) stream.buf = writeBuf(stream.buf, digits[r1]) return } r3 := q2 - q3*1000 q4 := q3 / 1000 if q4 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q3]) stream.buf = writeBuf(stream.buf, digits[r3]) stream.buf = writeBuf(stream.buf, digits[r2]) stream.buf = writeBuf(stream.buf, digits[r1]) return } r4 := q3 - q4*1000 q5 := q4 / 1000 if q5 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q4]) stream.buf = writeBuf(stream.buf, digits[r4]) stream.buf = writeBuf(stream.buf, digits[r3]) stream.buf = writeBuf(stream.buf, digits[r2]) stream.buf = writeBuf(stream.buf, digits[r1]) return } r5 := q4 - q5*1000 q6 := q5 / 1000 if q6 == 0 { stream.buf = writeFirstBuf(stream.buf, digits[q5]) } else { stream.buf = writeFirstBuf(stream.buf, digits[q6]) r6 := q5 - q6*1000 stream.buf = writeBuf(stream.buf, digits[r6]) } stream.buf = writeBuf(stream.buf, digits[r5]) stream.buf = writeBuf(stream.buf, digits[r4]) stream.buf = writeBuf(stream.buf, digits[r3]) stream.buf = writeBuf(stream.buf, digits[r2]) stream.buf = writeBuf(stream.buf, digits[r1]) } // WriteInt64 write int64 to stream func (stream *Stream) WriteInt64(nval int64) { var val uint64 if nval < 0 { val = uint64(-nval) stream.buf = append(stream.buf, '-') } else { val = uint64(nval) } stream.WriteUint64(val) } // WriteInt write int to stream func (stream *Stream) WriteInt(val int) { stream.WriteInt64(int64(val)) } // WriteUint write uint to stream func (stream *Stream) WriteUint(val uint) { stream.WriteUint64(uint64(val)) }
package jsoniter import ( "unicode/utf8" ) // htmlSafeSet holds the value true if the ASCII character with the given // array position can be safely represented inside a JSON string, embedded // inside of HTML <script> tags, without any additional escaping. // // All values are true except for the ASCII control characters (0-31), the // double quote ("), the backslash character ("\"), HTML opening and closing // tags ("<" and ">"), and the ampersand ("&"). var htmlSafeSet = [utf8.RuneSelf]bool{ ' ': true, '!': true, '"': false, '#': true, '$': true, '%': true, '&': false, '\'': true, '(': true, ')': true, '*': true, '+': true, ',': true, '-': true, '.': true, '/': true, '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, ':': true, ';': true, '<': false, '=': true, '>': false, '?': true, '@': true, 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true, '[': true, '\\': false, ']': true, '^': true, '_': true, '`': true, 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true, 'y': true, 'z': true, '{': true, '|': true, '}': true, '~': true, '\u007f': true, } // safeSet holds the value true if the ASCII character with the given array // position can be represented inside a JSON string without any further // escaping. // // All values are true except for the ASCII control characters (0-31), the // double quote ("), and the backslash character ("\"). var safeSet = [utf8.RuneSelf]bool{ ' ': true, '!': true, '"': false, '#': true, '$': true, '%': true, '&': true, '\'': true, '(': true, ')': true, '*': true, '+': true, ',': true, '-': true, '.': true, '/': true, '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, ':': true, ';': true, '<': true, '=': true, '>': true, '?': true, '@': true, 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true, '[': true, '\\': false, ']': true, '^': true, '_': true, '`': true, 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true, 'y': true, 'z': true, '{': true, '|': true, '}': true, '~': true, '\u007f': true, } var hex = "0123456789abcdef" // WriteStringWithHTMLEscaped write string to stream with html special characters escaped func (stream *Stream) WriteStringWithHTMLEscaped(s string) { valLen := len(s) stream.buf = append(stream.buf, '"') // write string, the fast path, without utf8 and escape support i := 0 for ; i < valLen; i++ { c := s[i] if c < utf8.RuneSelf && htmlSafeSet[c] { stream.buf = append(stream.buf, c) } else { break } } if i == valLen { stream.buf = append(stream.buf, '"') return } writeStringSlowPathWithHTMLEscaped(stream, i, s, valLen) } func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen int) { start := i // for the remaining parts, we process them char by char for i < valLen { if b := s[i]; b < utf8.RuneSelf { if htmlSafeSet[b] { i++ continue } if start < i { stream.WriteRaw(s[start:i]) } switch b { case '\\', '"': stream.writeTwoBytes('\\', b) case '\n': stream.writeTwoBytes('\\', 'n') case '\r': stream.writeTwoBytes('\\', 'r') case '\t': stream.writeTwoBytes('\\', 't') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. stream.WriteRaw(`\u00`) stream.writeTwoBytes(hex[b>>4], hex[b&0xF]) } i++ start = i continue } c, size := utf8.DecodeRuneInString(s[i:]) if c == utf8.RuneError && size == 1 { if start < i { stream.WriteRaw(s[start:i]) } stream.WriteRaw(`\ufffd`) i++ start = i continue } // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. if c == '\u2028' || c == '\u2029' { if start < i { stream.WriteRaw(s[start:i]) } stream.WriteRaw(`\u202`) stream.writeByte(hex[c&0xF]) i += size start = i continue } i += size } if start < len(s) { stream.WriteRaw(s[start:]) } stream.writeByte('"') } // WriteString write string to stream without html escape func (stream *Stream) WriteString(s string) { valLen := len(s) stream.buf = append(stream.buf, '"') // write string, the fast path, without utf8 and escape support i := 0 for ; i < valLen; i++ { c := s[i] if c > 31 && c != '"' && c != '\\' { stream.buf = append(stream.buf, c) } else { break } } if i == valLen { stream.buf = append(stream.buf, '"') return } writeStringSlowPath(stream, i, s, valLen) } func writeStringSlowPath(stream *Stream, i int, s string, valLen int) { start := i // for the remaining parts, we process them char by char for i < valLen { if b := s[i]; b < utf8.RuneSelf { if safeSet[b] { i++ continue } if start < i { stream.WriteRaw(s[start:i]) } switch b { case '\\', '"': stream.writeTwoBytes('\\', b) case '\n': stream.writeTwoBytes('\\', 'n') case '\r': stream.writeTwoBytes('\\', 'r') case '\t': stream.writeTwoBytes('\\', 't') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. stream.WriteRaw(`\u00`) stream.writeTwoBytes(hex[b>>4], hex[b&0xF]) } i++ start = i continue } i++ continue } if start < len(s) { stream.WriteRaw(s[start:]) } stream.writeByte('"') }