1
0
Fork 0

Custom resource definition

Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Ludovic Fernandez 2019-03-14 15:56:06 +01:00 committed by Traefiker Bot
parent cfaf47c8a2
commit 4c060a78cc
1348 changed files with 92364 additions and 55766 deletions

View file

@ -16,15 +16,6 @@ func Unmarshal(data []byte, v interface{}) error {
return ConfigDefault.Unmarshal(data, v)
}
func lastNotSpacePos(data []byte) int {
for i := len(data) - 1; i >= 0; i-- {
if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
return i + 1
}
}
return 0
}
// UnmarshalFromString convenient method to read from string instead of []byte
func UnmarshalFromString(str string, v interface{}) error {
return ConfigDefault.UnmarshalFromString(str, v)
@ -86,7 +77,16 @@ func (adapter *Decoder) Decode(obj interface{}) error {
// More is there more?
func (adapter *Decoder) More() bool {
return adapter.iter.head != adapter.iter.tail
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
@ -95,11 +95,21 @@ func (adapter *Decoder) Buffered() io.Reader {
return bytes.NewReader(remaining)
}
// UseNumber for number JSON element, use float64 or json.NumberValue (alias of string)
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
// Number instead of as a float64.
func (adapter *Decoder) UseNumber() {
origCfg := adapter.iter.cfg.configBeforeFrozen
origCfg.UseNumber = true
adapter.iter.cfg = origCfg.Froze().(*frozenConfig)
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
@ -122,14 +132,16 @@ func (adapter *Encoder) Encode(val interface{}) error {
// SetIndent set the indention. Prefix is not supported
func (adapter *Encoder) SetIndent(prefix, indent string) {
adapter.stream.cfg.indentionStep = len(indent)
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.Froze().(*frozenConfig)
adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions)
}
// Valid reports whether data is a valid JSON encoding.

View file

@ -3,8 +3,11 @@ package jsoniter
import (
"errors"
"fmt"
"github.com/modern-go/reflect2"
"io"
"reflect"
"strconv"
"unsafe"
)
// Any generic object representation.
@ -25,7 +28,6 @@ type Any interface {
ToString() string
ToVal(val interface{})
Get(path ...interface{}) Any
// TODO: add Set
Size() int
Keys() []string
GetInterface() interface{}
@ -35,7 +37,7 @@ type Any interface {
type baseAny struct{}
func (any *baseAny) Get(path ...interface{}) Any {
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *baseAny) Size() int {
@ -89,7 +91,7 @@ func Wrap(val interface{}) Any {
if isAny {
return asAny
}
typ := reflect.TypeOf(val)
typ := reflect2.TypeOf(val)
switch typ.Kind() {
case reflect.Slice:
return wrapArray(val)
@ -100,6 +102,9 @@ func Wrap(val interface{}) Any {
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)))
@ -110,7 +115,15 @@ func Wrap(val interface{}) Any {
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:
@ -243,3 +256,70 @@ func locatePath(iter *Iterator, path []interface{}) Any {
}
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
}

View file

@ -1,8 +1,8 @@
package jsoniter
import (
"unsafe"
"io"
"unsafe"
)
type numberLazyAny struct {

View file

@ -14,7 +14,7 @@ func (any *stringAny) Get(path ...interface{}) Any {
if len(path) == 0 {
return any
}
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *stringAny) Parse() *Iterator {

View file

@ -2,10 +2,13 @@ package jsoniter
import (
"encoding/json"
"errors"
"io"
"reflect"
"sync"
"unsafe"
"github.com/modern-go/concurrent"
"github.com/modern-go/reflect2"
)
// Config customize how the API should behave.
@ -16,10 +19,12 @@ type Config struct {
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.
@ -37,6 +42,8 @@ type API interface {
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
@ -58,35 +65,121 @@ var ConfigFastest = Config{
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 {
// TODO: cache frozen config
frozenConfig := &frozenConfig{
api := &frozenConfig{
sortMapKeys: cfg.SortMapKeys,
indentionStep: cfg.IndentionStep,
objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
onlyTaggedField: cfg.OnlyTaggedField,
streamPool: make(chan *Stream, 16),
iteratorPool: make(chan *Iterator, 16),
disallowUnknownFields: cfg.DisallowUnknownFields,
caseSensitive: cfg.CaseSensitive,
}
frozenConfig.initCache()
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 {
frozenConfig.marshalFloatWith6Digits()
api.marshalFloatWith6Digits(encoderExtension)
}
if cfg.EscapeHTML {
frozenConfig.escapeHTML()
api.escapeHTML(encoderExtension)
}
if cfg.UseNumber {
frozenConfig.useNumber()
api.useNumber(decoderExtension)
}
if cfg.ValidateJsonRawMessage {
frozenConfig.validateJsonRawMessage()
api.validateJsonRawMessage(encoderExtension)
}
frozenConfig.configBeforeFrozen = cfg
return frozenConfig
api.encoderExtension = encoderExtension
api.decoderExtension = decoderExtension
api.configBeforeFrozen = cfg
return api
}
func (cfg *frozenConfig) validateJsonRawMessage() {
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))
@ -98,20 +191,25 @@ func (cfg *frozenConfig) validateJsonRawMessage() {
stream.WriteRaw(string(rawMessage))
}
}, func(ptr unsafe.Pointer) bool {
return false
return len(*((*json.RawMessage)(ptr))) == 0
}}
cfg.addEncoderToCache(reflect.TypeOf((*json.RawMessage)(nil)).Elem(), encoder)
cfg.addEncoderToCache(reflect.TypeOf((*RawMessage)(nil)).Elem(), encoder)
extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
}
func (cfg *frozenConfig) useNumber() {
cfg.addDecoderToCache(reflect.TypeOf((*interface{})(nil)).Elem(), &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
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
@ -122,7 +220,9 @@ func (cfg *frozenConfig) getTagKey() string {
}
func (cfg *frozenConfig) RegisterExtension(extension Extension) {
cfg.extensions = append(cfg.extensions, extension)
cfg.extraExtensions = append(cfg.extraExtensions, extension)
copied := cfg.configBeforeFrozen
cfg.configBeforeFrozen = copied
}
type lossyFloat32Encoder struct {
@ -132,10 +232,6 @@ func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat32Lossy(*((*float32)(ptr)))
}
func (encoder *lossyFloat32Encoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float32)(ptr)) == 0
}
@ -147,20 +243,16 @@ func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat64Lossy(*((*float64)(ptr)))
}
func (encoder *lossyFloat64Encoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
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() {
func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
// for better performance
cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &lossyFloat32Encoder{})
cfg.addEncoderToCache(reflect.TypeOf((*float64)(nil)).Elem(), &lossyFloat64Encoder{})
extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
}
type htmlEscapedStringEncoder struct {
@ -171,16 +263,12 @@ func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stre
stream.WriteStringWithHTMLEscaped(str)
}
func (encoder *htmlEscapedStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
func (cfg *frozenConfig) escapeHTML() {
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
}
func (cfg *frozenConfig) cleanDecoders() {
@ -229,24 +317,22 @@ func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]
}
newCfg := cfg.configBeforeFrozen
newCfg.IndentionStep = len(indent)
return newCfg.Froze().Marshal(v)
return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v)
}
func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
data := []byte(str)
data = data[:lastNotSpacePos(data)]
iter := cfg.BorrowIterator(data)
defer cfg.ReturnIterator(iter)
iter.ReadVal(v)
if iter.head == iter.tail {
iter.loadMore()
}
if iter.Error == io.EOF {
return nil
}
if iter.Error == nil {
iter.ReportError("UnmarshalFromString", "there are bytes left after unmarshal")
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
}
@ -257,24 +343,17 @@ func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
}
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
data = data[:lastNotSpacePos(data)]
iter := cfg.BorrowIterator(data)
defer cfg.ReturnIterator(iter)
typ := reflect.TypeOf(v)
if typ.Kind() != reflect.Ptr {
// return non-pointer error
return errors.New("the second param must be ptr type")
}
iter.ReadVal(v)
if iter.head == iter.tail {
iter.loadMore()
}
if iter.Error == io.EOF {
return nil
}
if iter.Error == nil {
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
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
}

View file

@ -1,51 +0,0 @@
//+build go1.9
package jsoniter
import (
"reflect"
"sync"
)
type frozenConfig struct {
configBeforeFrozen Config
sortMapKeys bool
indentionStep int
objectFieldMustBeSimpleString bool
onlyTaggedField bool
decoderCache sync.Map
encoderCache sync.Map
extensions []Extension
streamPool chan *Stream
iteratorPool chan *Iterator
}
func (cfg *frozenConfig) initCache() {
cfg.decoderCache = sync.Map{}
cfg.encoderCache = sync.Map{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
cfg.decoderCache.Store(cacheKey, decoder)
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
cfg.encoderCache.Store(cacheKey, encoder)
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
decoder, found := cfg.decoderCache.Load(cacheKey)
if found {
return decoder.(ValDecoder)
}
return nil
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
encoder, found := cfg.encoderCache.Load(cacheKey)
if found {
return encoder.(ValEncoder)
}
return nil
}

View file

@ -1,54 +0,0 @@
//+build !go1.9
package jsoniter
import (
"reflect"
"sync"
)
type frozenConfig struct {
configBeforeFrozen Config
sortMapKeys bool
indentionStep int
objectFieldMustBeSimpleString bool
onlyTaggedField bool
cacheLock *sync.RWMutex
decoderCache map[reflect.Type]ValDecoder
encoderCache map[reflect.Type]ValEncoder
extensions []Extension
streamPool chan *Stream
iteratorPool chan *Iterator
}
func (cfg *frozenConfig) initCache() {
cfg.cacheLock = &sync.RWMutex{}
cfg.decoderCache = map[reflect.Type]ValDecoder{}
cfg.encoderCache = map[reflect.Type]ValEncoder{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
cfg.cacheLock.Lock()
cfg.decoderCache[cacheKey] = decoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
cfg.cacheLock.Lock()
cfg.encoderCache[cacheKey] = encoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
cfg.cacheLock.RLock()
decoder, _ := cfg.decoderCache[cacheKey].(ValDecoder)
cfg.cacheLock.RUnlock()
return decoder
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
cfg.cacheLock.RLock()
encoder, _ := cfg.encoderCache[cacheKey].(ValEncoder)
cfg.cacheLock.RUnlock()
return encoder
}

View file

@ -1,31 +0,0 @@
package jsoniter
import (
"encoding/json"
"strconv"
)
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
}

View file

@ -1,607 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/json"
"fmt"
"reflect"
"time"
"unsafe"
)
// 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)
EncodeInterface(val interface{}, stream *Stream)
}
type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
// WriteToStream the default implementation for TypeEncoder method EncodeInterface
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
stream.WriteNil()
return
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
var jsonNumberType reflect.Type
var jsoniterNumberType reflect.Type
var jsonRawMessageType reflect.Type
var jsoniterRawMessageType reflect.Type
var anyType reflect.Type
var marshalerType reflect.Type
var unmarshalerType reflect.Type
var textMarshalerType reflect.Type
var textUnmarshalerType reflect.Type
func init() {
jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
anyType = reflect.TypeOf((*Any)(nil)).Elem()
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
}
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
func (iter *Iterator) ReadVal(obj interface{}) {
typ := reflect.TypeOf(obj)
cacheKey := typ.Elem()
decoder := decoderOfType(iter.cfg, "", cacheKey)
e := (*emptyInterface)(unsafe.Pointer(&obj))
if e.word == nil {
iter.ReportError("ReadVal", "can not read into nil pointer")
return
}
decoder.Decode(e.word, iter)
}
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
func (stream *Stream) WriteVal(val interface{}) {
if nil == val {
stream.WriteNil()
return
}
typ := reflect.TypeOf(val)
cacheKey := typ
encoder := encoderOfType(stream.cfg, "", cacheKey)
encoder.EncodeInterface(val, stream)
}
func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
cacheKey := typ
decoder := cfg.getDecoderFromCache(cacheKey)
if decoder != nil {
return decoder
}
decoder = getTypeDecoderFromExtension(cfg, typ)
if decoder != nil {
cfg.addDecoderToCache(cacheKey, decoder)
return decoder
}
decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
cfg.addDecoderToCache(cacheKey, decoder)
decoder = createDecoderOfType(cfg, prefix, typ)
for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
for _, extension := range cfg.extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
cfg.addDecoderToCache(cacheKey, decoder)
return decoder
}
func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
typeName := typ.String()
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}
}
if typ.Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() == reflect.Ptr {
decoder = &OptionalDecoder{typ.Elem(), decoder}
}
return decoder
}
if reflect.PtrTo(typ).Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
return decoder
}
if typ.Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() == reflect.Ptr {
decoder = &OptionalDecoder{typ.Elem(), decoder}
}
return decoder
}
if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
return decoder
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(cfg, prefix, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
if typ.Implements(anyType) {
return &anyCodec{}
}
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}
}
return &nonEmptyInterfaceCodec{}
case reflect.Struct:
return decoderOfStruct(cfg, prefix, typ)
case reflect.Array:
return decoderOfArray(cfg, prefix, typ)
case reflect.Slice:
return decoderOfSlice(cfg, prefix, typ)
case reflect.Map:
return decoderOfMap(cfg, prefix, typ)
case reflect.Ptr:
return decoderOfOptional(cfg, prefix, typ)
default:
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
}
}
func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
cacheKey := typ
encoder := cfg.getEncoderFromCache(cacheKey)
if encoder != nil {
return encoder
}
encoder = getTypeEncoderFromExtension(cfg, typ)
if encoder != nil {
cfg.addEncoderToCache(cacheKey, encoder)
return encoder
}
encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
cfg.addEncoderToCache(cacheKey, encoder)
encoder = createEncoderOfType(cfg, prefix, typ)
for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
for _, extension := range cfg.extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
cfg.addEncoderToCache(cacheKey, encoder)
return encoder
}
func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}
}
if typ.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, typ)
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &marshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &OptionalEncoder{encoder}
}
return encoder
}
if reflect.PtrTo(typ).Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, reflect.PtrTo(typ))
templateInterface := reflect.New(typ).Interface()
var encoder ValEncoder = &marshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
return encoder
}
if typ.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, typ)
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &textMarshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &OptionalEncoder{encoder}
}
return encoder
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{}
}
if typ.Implements(anyType) {
return &anyCodec{}
}
return createEncoderOfSimpleType(cfg, prefix, typ)
}
func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty {
kind := typ.Kind()
switch kind {
case reflect.String:
return &stringCodec{}
case reflect.Int:
return &intCodec{}
case reflect.Int8:
return &int8Codec{}
case reflect.Int16:
return &int16Codec{}
case reflect.Int32:
return &int32Codec{}
case reflect.Int64:
return &int64Codec{}
case reflect.Uint:
return &uintCodec{}
case reflect.Uint8:
return &uint8Codec{}
case reflect.Uint16:
return &uint16Codec{}
case reflect.Uint32:
return &uint32Codec{}
case reflect.Uintptr:
return &uintptrCodec{}
case reflect.Uint64:
return &uint64Codec{}
case reflect.Float32:
return &float32Codec{}
case reflect.Float64:
return &float64Codec{}
case reflect.Bool:
return &boolCodec{}
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}
}
return &nonEmptyInterfaceCodec{}
case reflect.Struct:
return &structEncoder{typ: typ}
case reflect.Array:
return &arrayEncoder{}
case reflect.Slice:
return &sliceEncoder{}
case reflect.Map:
return encoderOfMap(cfg, "", typ)
case reflect.Ptr:
return &OptionalEncoder{}
default:
return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)}
}
}
func createEncoderOfSimpleType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
typeName := typ.String()
kind := typ.Kind()
switch kind {
case reflect.String:
if typeName != "string" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}
case reflect.Int8:
if typeName != "int8" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}
case reflect.Uint8:
if typeName != "uint8" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}
case reflect.Uint64:
if typeName != "uint64" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return encoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}
}
return &nonEmptyInterfaceCodec{}
case reflect.Struct:
return encoderOfStruct(cfg, prefix, typ)
case reflect.Array:
return encoderOfArray(cfg, prefix, typ)
case reflect.Slice:
return encoderOfSlice(cfg, prefix, typ)
case reflect.Map:
return encoderOfMap(cfg, prefix, typ)
case reflect.Ptr:
return encoderOfOptional(cfg, prefix, typ)
default:
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
}
}
type placeholderEncoder struct {
cfg *frozenConfig
cacheKey reflect.Type
}
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.getRealEncoder().Encode(ptr, stream)
}
func (encoder *placeholderEncoder) EncodeInterface(val interface{}, stream *Stream) {
encoder.getRealEncoder().EncodeInterface(val, stream)
}
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.getRealEncoder().IsEmpty(ptr)
}
func (encoder *placeholderEncoder) getRealEncoder() ValEncoder {
for i := 0; i < 500; i++ {
realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderEncoder)
if isPlaceholder {
time.Sleep(10 * time.Millisecond)
} else {
return realDecoder
}
}
panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
}
type placeholderDecoder struct {
cfg *frozenConfig
cacheKey reflect.Type
}
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for i := 0; i < 500; i++ {
realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderDecoder)
if isPlaceholder {
time.Sleep(10 * time.Millisecond)
} else {
realDecoder.Decode(ptr, iter)
return
}
}
panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
}
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) EncodeInterface(val interface{}, stream *Stream) {
if val == nil {
stream.WriteNil()
} else if stream.Error == nil {
stream.Error = encoder.err
}
}
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
func extractInterface(val interface{}) emptyInterface {
return *((*emptyInterface)(unsafe.Pointer(&val)))
}
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ unsafe.Pointer
word unsafe.Pointer
}
// emptyInterface is the header for an interface with method (not interface{})
type nonEmptyInterface struct {
// see ../runtime/iface.go:/Itab
itab *struct {
ityp unsafe.Pointer // static interface type
typ unsafe.Pointer // dynamic concrete type
link unsafe.Pointer
bad int32
unused int32
fun [100000]unsafe.Pointer // method table
}
word unsafe.Pointer
}

View file

@ -1,110 +0,0 @@
package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
)
func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem())
return &arrayDecoder{typ, typ.Elem(), decoder}
}
func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
if typ.Len() == 0 {
return emptyArrayEncoder{}
}
encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return &arrayEncoder{typ, typ.Elem(), encoder}
}
type emptyArrayEncoder struct{}
func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteEmptyArray()
}
func (encoder emptyArrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteEmptyArray()
}
func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return true
}
type arrayEncoder struct {
arrayType reflect.Type
elemType reflect.Type
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 = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
encoder.elemEncoder.Encode(unsafe.Pointer(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) EncodeInterface(val interface{}, stream *Stream) {
// special optimization for interface{}
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
stream.WriteArrayStart()
stream.WriteNil()
stream.WriteArrayEnd()
return
}
elemType := encoder.arrayType.Elem()
if encoder.arrayType.Len() == 1 && (elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map) {
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type arrayDecoder struct {
arrayType reflect.Type
elemType reflect.Type
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) {
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
if offset < decoder.arrayType.Size() {
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(ptr)+offset), iter)
offset += decoder.elemType.Size()
} else {
iter.Skip()
}
return true
})
}

View file

@ -1,260 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/json"
"reflect"
"sort"
"strconv"
"unsafe"
)
func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[map]->", typ.Elem())
mapInterface := reflect.New(typ).Interface()
return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}
}
func encoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
elemType := typ.Elem()
encoder := encoderOfType(cfg, prefix+"[map]->", elemType)
mapInterface := reflect.New(typ).Elem().Interface()
if cfg.sortMapKeys {
return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
}
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
}
type mapDecoder struct {
mapType reflect.Type
keyType reflect.Type
elemType reflect.Type
elemDecoder ValDecoder
mapInterface emptyInterface
}
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
// dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
mapInterface := decoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface).Elem()
if iter.ReadNil() {
realVal.Set(reflect.Zero(decoder.mapType))
return
}
if realVal.IsNil() {
realVal.Set(reflect.MakeMap(realVal.Type()))
}
iter.ReadMapCB(func(iter *Iterator, keyStr string) bool {
elem := reflect.New(decoder.elemType)
decoder.elemDecoder.Decode(extractInterface(elem.Interface()).word, iter)
// to put into map, we have to use reflection
keyType := decoder.keyType
// TODO: remove this from loop
switch {
case keyType.Kind() == reflect.String:
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
return true
case keyType.Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType.Elem()).Interface().(encoding.TextUnmarshaler)
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
if err != nil {
iter.ReportError("read map key as TextUnmarshaler", err.Error())
return false
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
return true
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType).Interface().(encoding.TextUnmarshaler)
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
if err != nil {
iter.ReportError("read map key as TextUnmarshaler", err.Error())
return false
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler).Elem(), elem.Elem())
return true
default:
switch keyType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(keyStr, 10, 64)
if err != nil || reflect.Zero(keyType).OverflowInt(n) {
iter.ReportError("read map key as int64", "read int64 failed")
return false
}
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
return true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(keyStr, 10, 64)
if err != nil || reflect.Zero(keyType).OverflowUint(n) {
iter.ReportError("read map key as uint64", "read uint64 failed")
return false
}
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
return true
}
}
iter.ReportError("read map key", "unexpected map key type "+keyType.String())
return true
})
}
type mapEncoder struct {
mapType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
mapInterface emptyInterface
}
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
stream.WriteObjectStart()
for i, key := range realVal.MapKeys() {
if i != 0 {
stream.WriteMore()
}
encodeMapKey(key, stream)
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
val := realVal.MapIndex(key).Interface()
encoder.elemEncoder.EncodeInterface(val, stream)
}
stream.WriteObjectEnd()
}
func encodeMapKey(key reflect.Value, stream *Stream) {
if key.Kind() == reflect.String {
stream.WriteString(key.String())
return
}
if tm, ok := key.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
if err != nil {
stream.Error = err
return
}
stream.writeByte('"')
stream.Write(buf)
stream.writeByte('"')
return
}
switch key.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
stream.writeByte('"')
stream.WriteInt64(key.Int())
stream.writeByte('"')
return
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
stream.writeByte('"')
stream.WriteUint64(key.Uint())
stream.writeByte('"')
return
}
stream.Error = &json.UnsupportedTypeError{Type: key.Type()}
}
func (encoder *mapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
return realVal.Len() == 0
}
type sortKeysMapEncoder struct {
mapType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
mapInterface emptyInterface
}
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
// Extract and sort the keys.
keys := realVal.MapKeys()
sv := stringValues(make([]reflectWithString, len(keys)))
for i, v := range keys {
sv[i].v = v
if err := sv[i].resolve(); err != nil {
stream.Error = err
return
}
}
sort.Sort(sv)
stream.WriteObjectStart()
for i, key := range sv {
if i != 0 {
stream.WriteMore()
}
stream.WriteVal(key.s) // might need html escape, so can not WriteString directly
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
val := realVal.MapIndex(key.v).Interface()
encoder.elemEncoder.EncodeInterface(val, stream)
}
stream.WriteObjectEnd()
}
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflectWithString
type reflectWithString struct {
v reflect.Value
s string
}
func (w *reflectWithString) resolve() error {
if w.v.Kind() == reflect.String {
w.s = w.v.String()
return nil
}
if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
w.s = string(buf)
return err
}
switch w.v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
w.s = strconv.FormatInt(w.v.Int(), 10)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
w.s = strconv.FormatUint(w.v.Uint(), 10)
return nil
}
return &json.UnsupportedTypeError{Type: w.v.Type()}
}
func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv[i].s < sv[j].s }
func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
return realVal.Len() == 0
}

View file

@ -1,789 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/base64"
"encoding/json"
"reflect"
"unsafe"
)
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
type intCodec struct {
}
func (codec *intCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int)(ptr)) = iter.ReadInt()
}
}
func (codec *intCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt(*((*int)(ptr)))
}
func (codec *intCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *intCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int)(ptr)) == 0
}
type uintptrCodec struct {
}
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
}
}
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
}
func (codec *uintptrCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uintptrCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uintptr)(ptr)) == 0
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int64)(ptr)) == 0
}
type uintCodec struct {
}
func (codec *uintCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint)(ptr)) = iter.ReadUint()
return
}
}
func (codec *uintCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint(*((*uint)(ptr)))
}
func (codec *uintCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uintCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint)(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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool {
return !(*((*bool)(ptr)))
}
type emptyInterfaceCodec struct {
}
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
existing := *((*interface{})(ptr))
// Checking for both typed and untyped nil pointers.
if existing != nil &&
reflect.TypeOf(existing).Kind() == reflect.Ptr &&
!reflect.ValueOf(existing).IsNil() {
var ptrToExisting interface{}
for {
elem := reflect.ValueOf(existing).Elem()
if elem.Kind() != reflect.Ptr || elem.IsNil() {
break
}
ptrToExisting = existing
existing = elem.Interface()
}
if iter.ReadNil() {
if ptrToExisting != nil {
nilPtr := reflect.Zero(reflect.TypeOf(ptrToExisting).Elem())
reflect.ValueOf(ptrToExisting).Elem().Set(nilPtr)
} else {
*((*interface{})(ptr)) = nil
}
} else {
iter.ReadVal(existing)
}
return
}
if iter.ReadNil() {
*((*interface{})(ptr)) = nil
} else {
*((*interface{})(ptr)) = iter.Read()
}
}
func (codec *emptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteVal(*((*interface{})(ptr)))
}
func (codec *emptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteVal(val)
}
func (codec *emptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
emptyInterface := (*emptyInterface)(ptr)
return emptyInterface.typ == nil
}
type nonEmptyInterfaceCodec struct {
}
func (codec *nonEmptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == NilValue {
iter.skipFourBytes('n', 'u', 'l', 'l')
*((*interface{})(ptr)) = nil
return
}
nonEmptyInterface := (*nonEmptyInterface)(ptr)
if nonEmptyInterface.itab == nil {
iter.ReportError("read non-empty interface", "do not know which concrete type to decode to")
return
}
var i interface{}
e := (*emptyInterface)(unsafe.Pointer(&i))
e.typ = nonEmptyInterface.itab.typ
e.word = nonEmptyInterface.word
iter.ReadVal(&i)
if e.word == nil {
nonEmptyInterface.itab = nil
}
nonEmptyInterface.word = e.word
}
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
nonEmptyInterface := (*nonEmptyInterface)(ptr)
var i interface{}
if nonEmptyInterface.itab != nil {
e := (*emptyInterface)(unsafe.Pointer(&i))
e.typ = nonEmptyInterface.itab.typ
e.word = nonEmptyInterface.word
}
stream.WriteVal(i)
}
func (codec *nonEmptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteVal(val)
}
func (codec *nonEmptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
nonEmptyInterface := (*nonEmptyInterface)(ptr)
return nonEmptyInterface.word == nil
}
type anyCodec struct {
}
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*Any)(ptr)) = iter.ReadAny()
}
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
(*((*Any)(ptr))).WriteTo(stream)
}
func (codec *anyCodec) EncodeInterface(val interface{}, stream *Stream) {
(val.(Any)).WriteTo(stream)
}
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
return (*((*Any)(ptr))).Size() == 0
}
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.WriteRaw("0")
} else {
stream.WriteRaw(string(number))
}
}
func (codec *jsonNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
number := val.(json.Number)
if len(number) == 0 {
stream.WriteRaw("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.WriteRaw("0")
} else {
stream.WriteRaw(string(number))
}
}
func (codec *jsoniterNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
number := val.(Number)
if len(number) == 0 {
stream.WriteRaw("0")
} else {
stream.WriteRaw(string(number))
}
}
func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*Number)(ptr))) == 0
}
type jsonRawMessageCodec struct {
}
func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
}
func (codec *jsonRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(json.RawMessage)))
}
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) {
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
}
func (codec *jsoniterRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(RawMessage)))
}
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*RawMessage)(ptr))) == 0
}
type base64Codec struct {
sliceDecoder ValDecoder
}
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Len = 0
ptrSlice.Cap = 0
ptrSlice.Data = nil
return
}
switch iter.WhatIsNext() {
case StringValue:
encoding := base64.StdEncoding
src := iter.SkipAndReturnBytes()
src = src[1 : len(src)-1]
decodedLen := encoding.DecodedLen(len(src))
dst := make([]byte, decodedLen)
len, err := encoding.Decode(dst, src)
if err != nil {
iter.ReportError("decode base64", err.Error())
} else {
dst = dst[:len]
dstSlice := (*sliceHeader)(unsafe.Pointer(&dst))
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Data = dstSlice.Data
ptrSlice.Cap = dstSlice.Cap
ptrSlice.Len = dstSlice.Len
}
case ArrayValue:
codec.sliceDecoder.Decode(ptr, iter)
default:
iter.ReportError("base64Codec", "invalid input")
}
}
func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
stream.n += toGrow
stream.writeByte('"')
}
func (codec *base64Codec) EncodeInterface(val interface{}, stream *Stream) {
ptr := extractInterface(val).word
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
stream.n += toGrow
stream.writeByte('"')
}
func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*[]byte)(ptr))) == 0
}
type stringModeNumberDecoder struct {
elemDecoder ValDecoder
}
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
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
}
}
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 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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
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)
defer encoder.cfg.ReturnStream(tempStream)
encoder.elemEncoder.Encode(ptr, tempStream)
stream.WriteString(string(tempStream.Buffer()))
}
func (encoder *stringModeStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type marshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
templateInterface := encoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
marshaler, ok := (*realInterface).(json.Marshaler)
if !ok {
stream.WriteVal(nil)
return
}
bytes, err := marshaler.MarshalJSON()
if err != nil {
stream.Error = err
} else {
stream.Write(bytes)
}
}
func (encoder *marshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type textMarshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
templateInterface := encoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
marshaler := (*realInterface).(encoding.TextMarshaler)
bytes, err := marshaler.MarshalText()
if err != nil {
stream.Error = err
} else {
stream.WriteString(string(bytes))
}
}
func (encoder *textMarshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type unmarshalerDecoder struct {
templateInterface emptyInterface
}
func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface := decoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(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 {
templateInterface emptyInterface
}
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface := decoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(encoding.TextUnmarshaler)
str := iter.ReadString()
err := unmarshaler.UnmarshalText([]byte(str))
if err != nil {
iter.ReportError("textUnmarshalerDecoder", err.Error())
}
}

View file

@ -1,143 +0,0 @@
package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
)
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
return &sliceDecoder{typ, typ.Elem(), decoder}
}
func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem())
if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return &sliceEncoder{typ, typ.Elem(), encoder}
}
type sliceEncoder struct {
sliceType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
}
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
slice := (*sliceHeader)(ptr)
if slice.Data == nil {
stream.WriteNil()
return
}
if slice.Len == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(slice.Data)
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
for i := 1; i < slice.Len; i++ {
stream.WriteMore()
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
encoder.elemEncoder.Encode(unsafe.Pointer(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) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
slice := (*sliceHeader)(ptr)
return slice.Len == 0
}
type sliceDecoder struct {
sliceType reflect.Type
elemType reflect.Type
elemDecoder ValDecoder
}
// sliceHeader is a safe version of SliceHeader used within this package.
type sliceHeader struct {
Data unsafe.Pointer
Len int
Cap int
}
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) {
slice := (*sliceHeader)(ptr)
if iter.ReadNil() {
slice.Len = 0
slice.Cap = 0
slice.Data = nil
return
}
reuseSlice(slice, decoder.sliceType, 4)
slice.Len = 0
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
growOne(slice, decoder.sliceType, decoder.elemType)
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
offset += decoder.elemType.Size()
return true
})
}
// grow grows the slice s so that it can hold extra more values, allocating
// more capacity if needed. It also returns the old and new slice lengths.
func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
newLen := slice.Len + 1
if newLen <= slice.Cap {
slice.Len = newLen
return
}
newCap := slice.Cap
if newCap == 0 {
newCap = 1
} else {
for newCap < newLen {
if slice.Len < 1024 {
newCap += newCap
} else {
newCap += newCap / 4
}
}
}
newVal := reflect.MakeSlice(sliceType, newLen, newCap).Interface()
newValPtr := extractInterface(newVal).word
dst := (*sliceHeader)(newValPtr).Data
// copy old array into new array
originalBytesCount := slice.Len * int(elementType.Size())
srcSliceHeader := (unsafe.Pointer)(&sliceHeader{slice.Data, originalBytesCount, originalBytesCount})
dstSliceHeader := (unsafe.Pointer)(&sliceHeader{dst, originalBytesCount, originalBytesCount})
copy(*(*[]byte)(dstSliceHeader), *(*[]byte)(srcSliceHeader))
slice.Data = dst
slice.Len = newLen
slice.Cap = newCap
}
func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
if expectedCap <= slice.Cap {
return
}
newVal := reflect.MakeSlice(sliceType, 0, expectedCap).Interface()
newValPtr := extractInterface(newVal).word
dst := (*sliceHeader)(newValPtr).Data
slice.Data = dst
slice.Cap = expectedCap
}

View file

@ -1,320 +0,0 @@
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(buf []byte, v uint32, n int) int {
start := v >> 24
if start == 0 {
buf[n] = byte(v >> 16)
n++
buf[n] = byte(v >> 8)
n++
} else if start == 1 {
buf[n] = byte(v >> 8)
n++
}
buf[n] = byte(v)
n++
return n
}
func writeBuf(buf []byte, v uint32, n int) {
buf[n] = byte(v >> 16)
buf[n+1] = byte(v >> 8)
buf[n+2] = byte(v)
}
// WriteUint8 write uint8 to stream
func (stream *Stream) WriteUint8(val uint8) {
stream.ensure(3)
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
}
// WriteInt8 write int8 to stream
func (stream *Stream) WriteInt8(nval int8) {
stream.ensure(4)
n := stream.n
var val uint8
if nval < 0 {
val = uint8(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint8(nval)
}
stream.n = writeFirstBuf(stream.buf, digits[val], n)
}
// WriteUint16 write uint16 to stream
func (stream *Stream) WriteUint16(val uint16) {
stream.ensure(5)
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
return
}
r1 := val - q1*1000
n := writeFirstBuf(stream.buf, digits[q1], stream.n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
// WriteInt16 write int16 to stream
func (stream *Stream) WriteInt16(nval int16) {
stream.ensure(6)
n := stream.n
var val uint16
if nval < 0 {
val = uint16(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint16(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
n = writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
// WriteUint32 write uint32 to stream
func (stream *Stream) WriteUint32(val uint32) {
stream.ensure(10)
n := stream.n
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
} else {
r3 := q2 - q3*1000
stream.buf[n] = byte(q3 + '0')
n++
writeBuf(stream.buf, digits[r3], n)
n += 3
}
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
}
// WriteInt32 write int32 to stream
func (stream *Stream) WriteInt32(nval int32) {
stream.ensure(11)
n := stream.n
var val uint32
if nval < 0 {
val = uint32(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint32(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
} else {
r3 := q2 - q3*1000
stream.buf[n] = byte(q3 + '0')
n++
writeBuf(stream.buf, digits[r3], n)
n += 3
}
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
}
// WriteUint64 write uint64 to stream
func (stream *Stream) WriteUint64(val uint64) {
stream.ensure(20)
n := stream.n
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
n = writeFirstBuf(stream.buf, digits[q3], n)
writeBuf(stream.buf, digits[r3], n)
writeBuf(stream.buf, digits[r2], n+3)
writeBuf(stream.buf, digits[r1], n+6)
stream.n = n + 9
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
n = writeFirstBuf(stream.buf, digits[q4], n)
writeBuf(stream.buf, digits[r4], n)
writeBuf(stream.buf, digits[r3], n+3)
writeBuf(stream.buf, digits[r2], n+6)
writeBuf(stream.buf, digits[r1], n+9)
stream.n = n + 12
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
n = writeFirstBuf(stream.buf, digits[q5], n)
} else {
n = writeFirstBuf(stream.buf, digits[q6], n)
r6 := q5 - q6*1000
writeBuf(stream.buf, digits[r6], n)
n += 3
}
writeBuf(stream.buf, digits[r5], n)
writeBuf(stream.buf, digits[r4], n+3)
writeBuf(stream.buf, digits[r3], n+6)
writeBuf(stream.buf, digits[r2], n+9)
writeBuf(stream.buf, digits[r1], n+12)
stream.n = n + 15
}
// WriteInt64 write int64 to stream
func (stream *Stream) WriteInt64(nval int64) {
stream.ensure(20)
n := stream.n
var val uint64
if nval < 0 {
val = uint64(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint64(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
n = writeFirstBuf(stream.buf, digits[q3], n)
writeBuf(stream.buf, digits[r3], n)
writeBuf(stream.buf, digits[r2], n+3)
writeBuf(stream.buf, digits[r1], n+6)
stream.n = n + 9
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
n = writeFirstBuf(stream.buf, digits[q4], n)
writeBuf(stream.buf, digits[r4], n)
writeBuf(stream.buf, digits[r3], n+3)
writeBuf(stream.buf, digits[r2], n+6)
writeBuf(stream.buf, digits[r1], n+9)
stream.n = n + 12
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
n = writeFirstBuf(stream.buf, digits[q5], n)
} else {
stream.buf[n] = byte(q6 + '0')
n++
r6 := q5 - q6*1000
writeBuf(stream.buf, digits[r6], n)
n += 3
}
writeBuf(stream.buf, digits[r5], n)
writeBuf(stream.buf, digits[r4], n+3)
writeBuf(stream.buf, digits[r3], n+6)
writeBuf(stream.buf, digits[r2], n+9)
writeBuf(stream.buf, digits[r1], n+12)
stream.n = n + 15
}
// 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))
}

View file

@ -77,14 +77,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
}
func (iter *Iterator) readPositiveFloat32() (ret float32) {
value := uint64(0)
c := byte(' ')
i := iter.head
// first char
if i == iter.tail {
return iter.readFloat32SlowPath()
}
c = iter.buf[i]
c := iter.buf[i]
i++
ind := floatDigits[c]
switch ind {
@ -107,7 +105,7 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
return
}
}
value = uint64(ind)
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < iter.tail; i++ {
@ -145,9 +143,7 @@ non_decimal_loop:
}
// too many decimal places
return iter.readFloat32SlowPath()
case invalidCharForNumber:
fallthrough
case dotInNumber:
case invalidCharForNumber, dotInNumber:
return iter.readFloat32SlowPath()
}
decimalPlaces++
@ -218,14 +214,12 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
}
func (iter *Iterator) readPositiveFloat64() (ret float64) {
value := uint64(0)
c := byte(' ')
i := iter.head
// first char
if i == iter.tail {
return iter.readFloat64SlowPath()
}
c = iter.buf[i]
c := iter.buf[i]
i++
ind := floatDigits[c]
switch ind {
@ -248,7 +242,7 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
return
}
}
value = uint64(ind)
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < iter.tail; i++ {
@ -286,9 +280,7 @@ non_decimal_loop:
}
// too many decimal places
return iter.readFloat64SlowPath()
case invalidCharForNumber:
fallthrough
case dotInNumber:
case invalidCharForNumber, dotInNumber:
return iter.readFloat64SlowPath()
}
decimalPlaces++

View file

@ -22,11 +22,17 @@ func init() {
// 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())
}

View file

@ -2,8 +2,7 @@ package jsoniter
import (
"fmt"
"unicode"
"unsafe"
"strings"
)
// ReadObject read one field from object.
@ -19,26 +18,6 @@ func (iter *Iterator) ReadObject() (ret string) {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
if iter.cfg.objectFieldMustBeSimpleString {
return string(iter.readObjectFieldAsBytes())
} else {
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 ',':
if iter.cfg.objectFieldMustBeSimpleString {
return string(iter.readObjectFieldAsBytes())
} else {
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
@ -46,6 +25,18 @@ func (iter *Iterator) ReadObject() (ret string) {
}
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:
@ -54,97 +45,90 @@ func (iter *Iterator) ReadObject() (ret string) {
}
}
func (iter *Iterator) readFieldHash() int32 {
// CaseInsensitive
func (iter *Iterator) readFieldHash() int64 {
hash := int64(0x811c9dc5)
c := iter.nextToken()
if c == '"' {
for {
for i := iter.head; i < iter.tail; i++ {
// require ascii string and no escape
b := iter.buf[i]
if !iter.cfg.objectFieldMustBeSimpleString && b == '\\' {
iter.head = i
for _, b := range iter.readStringSlowPath() {
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
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'
}
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return int32(hash)
hash ^= int64(b)
hash *= 0x1000193
}
if b == '"' {
iter.head = i + 1
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return int32(hash)
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
return hash
}
if !iter.loadMore() {
iter.ReportError("readFieldHash", `incomplete field name`)
return 0
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
}
}
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
return 0
}
func calcHash(str string) int32 {
func calcHash(str string, caseSensitive bool) int64 {
if !caseSensitive {
str = strings.ToLower(str)
}
hash := int64(0x811c9dc5)
for _, b := range str {
hash ^= int64(unicode.ToLower(b))
for _, b := range []byte(str) {
hash ^= int64(b)
hash *= 0x1000193
}
return int32(hash)
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 fieldBytes []byte
var field string
if c == '{' {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{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) {
return false
}
c = iter.nextToken()
for c == ',' {
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{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) {
return false

View file

@ -2,12 +2,22 @@
package jsoniter
import "fmt"
import (
"fmt"
"io"
)
func (iter *Iterator) skipNumber() {
if !iter.trySkipNumber() {
iter.unreadByte()
iter.ReadFloat32()
if iter.Error != nil && iter.Error != io.EOF {
return
}
iter.ReadFloat64()
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = nil
iter.ReadBigFloat()
}
}
}

View file

@ -17,43 +17,26 @@ type StreamPool interface {
}
func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
select {
case stream := <-cfg.streamPool:
stream.Reset(writer)
return stream
default:
return NewStream(cfg, writer, 512)
}
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
select {
case cfg.streamPool <- stream:
return
default:
return
}
cfg.streamPool.Put(stream)
}
func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator {
select {
case iter := <-cfg.iteratorPool:
iter.ResetBytes(data)
return iter
default:
return ParseBytes(cfg, data)
}
iter := cfg.iteratorPool.Get().(*Iterator)
iter.ResetBytes(data)
return iter
}
func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
iter.Error = nil
iter.Attachment = nil
select {
case cfg.iteratorPool <- iter:
return
default:
return
}
cfg.iteratorPool.Put(iter)
}

332
vendor/github.com/json-iterator/go/reflect.go generated vendored Normal file
View file

@ -0,0 +1,332 @@
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{}) {
cacheKey := reflect2.RTypeOf(obj)
decoder := iter.cfg.getDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(obj)
if 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)
}
// 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)
}

104
vendor/github.com/json-iterator/go/reflect_array.go generated vendored Normal file
View file

@ -0,0 +1,104 @@
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
}
}

70
vendor/github.com/json-iterator/go/reflect_dynamic.go generated vendored Normal file
View file

@ -0,0 +1,70 @@
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)
}

View file

@ -2,6 +2,7 @@ package jsoniter
import (
"fmt"
"github.com/modern-go/reflect2"
"reflect"
"sort"
"strings"
@ -17,17 +18,15 @@ var extensions = []Extension{}
// StructDescriptor describe how should we encode/decode the struct
type StructDescriptor struct {
onePtrEmbedded bool
onePtrOptimization bool
Type reflect.Type
Fields []*Binding
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 {
if binding.Field.Name() == fieldName {
return binding
}
}
@ -37,7 +36,7 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
// Binding describe how should we encode/decode the struct field
type Binding struct {
levels []int
Field *reflect.StructField
Field reflect2.StructField
FromNames []string
ToNames []string
Encoder ValEncoder
@ -48,10 +47,12 @@ type Binding struct {
// Can also rename fields by UpdateStructDescriptor.
type Extension interface {
UpdateStructDescriptor(structDescriptor *StructDescriptor)
CreateDecoder(typ reflect.Type) ValDecoder
CreateEncoder(typ reflect.Type) ValEncoder
DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder
DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder
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
@ -62,23 +63,105 @@ type DummyExtension struct {
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 reflect.Type) ValDecoder {
func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateEncoder No-op
func (extension *DummyExtension) CreateEncoder(typ reflect.Type) ValEncoder {
func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension *DummyExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension *DummyExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
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
}
@ -99,10 +182,6 @@ func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.fun(ptr, stream)
}
func (encoder *funcEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
if encoder.isEmptyFunc == nil {
return false
@ -161,78 +240,90 @@ func RegisterExtension(extension Extension) {
extensions = append(extensions, extension)
}
func getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(cfg, typ)
func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(ctx, typ)
if decoder != nil {
for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
for _, extension := range cfg.extensions {
decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder)
for _, extension := range ctx.extraExtensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
}
return decoder
}
func _getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder {
func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
for _, extension := range extensions {
decoder := extension.CreateDecoder(typ)
if decoder != nil {
return decoder
}
}
for _, extension := range cfg.extensions {
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]
decoder = typeDecoders[typeName]
if decoder != nil {
return decoder
}
if typ.Kind() == reflect.Ptr {
decoder := typeDecoders[typ.Elem().String()]
ptrType := typ.(*reflect2.UnsafePtrType)
decoder := typeDecoders[ptrType.Elem().String()]
if decoder != nil {
return &OptionalDecoder{typ.Elem(), decoder}
return &OptionalDecoder{ptrType.Elem(), decoder}
}
}
return nil
}
func getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(cfg, typ)
func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(ctx, typ)
if encoder != nil {
for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
for _, extension := range cfg.extensions {
encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder)
for _, extension := range ctx.extraExtensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
}
return encoder
}
func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder {
func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
for _, extension := range extensions {
encoder := extension.CreateEncoder(typ)
if encoder != nil {
return encoder
}
}
for _, extension := range cfg.extensions {
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]
encoder = typeEncoders[typeName]
if encoder != nil {
return encoder
}
if typ.Kind() == reflect.Ptr {
encoder := typeEncoders[typ.Elem().String()]
typePtr := typ.(*reflect2.UnsafePtrType)
encoder := typeEncoders[typePtr.Elem().String()]
if encoder != nil {
return &OptionalEncoder{encoder}
}
@ -240,61 +331,60 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode
return nil
}
func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor {
func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
structType := typ.(*reflect2.UnsafeStructType)
embeddedBindings := []*Binding{}
bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tag, hastag := field.Tag.Lookup(cfg.getTagKey())
if cfg.onlyTaggedField && !hastag {
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
}
tagParts := strings.Split(tag, ",")
if tag == "-" {
continue
}
if field.Anonymous && (tag == "" || tagParts[0] == "") {
if field.Type.Kind() == reflect.Struct {
structDescriptor := describeStruct(cfg, prefix, field.Type)
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}
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 && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(cfg, prefix, field.Type.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{field.Type.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
} 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
}
continue
}
}
fieldNames := calcFieldNames(field.Name, tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
fieldNames := calcFieldNames(field.Name(), tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name())
decoder := fieldDecoders[fieldCacheKey]
if decoder == nil {
decoder = decoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
decoder = decoderOfType(ctx.append(field.Name()), field.Type())
}
encoder := fieldEncoders[fieldCacheKey]
if encoder == nil {
encoder = encoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
// map is stored as pointer in the struct,
// and treat nil or empty map as empty field
if encoder != nil && field.Type.Kind() == reflect.Map {
encoder = &optionalMapEncoder{encoder}
}
encoder = encoderOfType(ctx.append(field.Name()), field.Type())
}
binding := &Binding{
Field: &field,
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
@ -303,38 +393,22 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
binding.levels = []int{i}
bindings = append(bindings, binding)
}
return createStructDescriptor(cfg, typ, bindings, embeddedBindings)
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
}
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
onePtrEmbedded := false
onePtrOptimization := false
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
if firstField.Anonymous && firstField.Type.Elem().Kind() == reflect.Struct {
onePtrEmbedded = true
}
fallthrough
case reflect.Map:
onePtrOptimization = true
case reflect.Struct:
onePtrOptimization = isStructOnePtr(firstField.Type)
}
}
func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{
onePtrEmbedded: onePtrEmbedded,
onePtrOptimization: onePtrOptimization,
Type: typ,
Fields: bindings,
Type: typ,
Fields: bindings,
}
for _, extension := range extensions {
extension.UpdateStructDescriptor(structDescriptor)
}
for _, extension := range cfg.extensions {
ctx.encoderExtension.UpdateStructDescriptor(structDescriptor)
ctx.decoderExtension.UpdateStructDescriptor(structDescriptor)
for _, extension := range ctx.extraExtensions {
extension.UpdateStructDescriptor(structDescriptor)
}
processTags(structDescriptor, cfg)
processTags(structDescriptor, ctx.frozenConfig)
// merge normal & embedded bindings & sort with original order
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings)
@ -342,21 +416,6 @@ func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Bin
return structDescriptor
}
func isStructOnePtr(typ reflect.Type) bool {
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
return true
case reflect.Map:
return true
case reflect.Struct:
return isStructOnePtr(firstField.Type)
}
}
return false
}
type sortableBindings []*Binding
func (bindings sortableBindings) Len() int {
@ -384,12 +443,12 @@ func (bindings sortableBindings) Swap(i, j int) {
func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) {
for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false
tagParts := strings.Split(binding.Field.Tag.Get(cfg.getTagKey()), ",")
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 {
if binding.Field.Type().Kind() == reflect.String {
binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg}
binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg}
} else {

View file

@ -0,0 +1,112 @@
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
}

View file

@ -0,0 +1,60 @@
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) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
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) {
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
}
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*RawMessage)(ptr))) == 0
}

338
vendor/github.com/json-iterator/go/reflect_map.go generated vendored Normal file
View file

@ -0,0 +1,338 @@
package jsoniter
import (
"fmt"
"github.com/modern-go/reflect2"
"io"
"reflect"
"sort"
"unsafe"
)
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
}
}
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:
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,
}
}
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
}
}
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 == textMarshalerType {
return &directTextMarshalerEncoder{
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
if typ.Implements(textMarshalerType) {
return &textMarshalerEncoder{
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
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
}
if c != '"' {
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{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) {
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)
subIter := stream.cfg.BorrowIterator(nil)
keyValues := encodedKeyValues{}
for mapIter.HasNext() {
subStream.buf = make([]byte, 0, 64)
key, elem := mapIter.UnsafeNext()
encoder.keyEncoder.Encode(key, subStream)
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
stream.Error = subStream.Error
}
encodedKey := subStream.Buffer()
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(),
})
}
sort.Sort(keyValues)
for i, keyValue := range keyValues {
if i != 0 {
stream.WriteMore()
}
stream.Write(keyValue.keyValue)
}
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 }

217
vendor/github.com/json-iterator/go/reflect_marshaler.go generated vendored Normal file
View file

@ -0,0 +1,217 @@
package jsoniter
import (
"encoding"
"encoding/json"
"github.com/modern-go/reflect2"
"unsafe"
)
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
}
bytes, err := json.Marshal(obj)
if err != nil {
stream.Error = err
} else {
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())
}
}

451
vendor/github.com/json-iterator/go/reflect_native.go generated vendored Normal file
View file

@ -0,0 +1,451 @@
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) {
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
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
}

View file

@ -1,28 +1,31 @@
package jsoniter
import (
"github.com/modern-go/reflect2"
"reflect"
"unsafe"
)
func decoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
elemType := typ.Elem()
decoder := decoderOfType(cfg, prefix, elemType)
func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
decoder := decoderOfType(ctx, elemType)
if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
return &dereferenceDecoder{elemType, decoder}
}
return &OptionalDecoder{elemType, decoder}
}
func encoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
elemType := typ.Elem()
elemEncoder := encoderOfType(cfg, prefix, elemType)
func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
elemEncoder := encoderOfType(ctx, elemType)
encoder := &OptionalEncoder{elemEncoder}
if elemType.Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return encoder
}
type OptionalDecoder struct {
ValueType reflect.Type
ValueType reflect2.Type
ValueDecoder ValDecoder
}
@ -32,10 +35,9 @@ func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.ValueType)
newPtr := extractInterface(value.Interface()).word
newPtr := decoder.ValueType.UnsafeNew()
decoder.ValueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
//reuse existing instance
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
@ -45,17 +47,16 @@ func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
type dereferenceDecoder struct {
// only to deference a pointer
valueType reflect.Type
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
value := reflect.New(decoder.valueType)
newPtr := extractInterface(value.Interface()).word
newPtr := decoder.valueType.UnsafeNew()
decoder.valueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
@ -74,10 +75,6 @@ func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
}
}
func (encoder *OptionalEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
@ -94,31 +91,43 @@ func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
}
}
func (encoder *dereferenceEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.ValueEncoder.IsEmpty(*((*unsafe.Pointer)(ptr)))
}
type optionalMapEncoder struct {
valueEncoder ValEncoder
}
func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
dePtr := *((*unsafe.Pointer)(ptr))
if dePtr == nil {
return true
}
return encoder.ValueEncoder.IsEmpty(dePtr)
}
func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
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)
}
func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
p := *((*unsafe.Pointer)(ptr))
return p == nil || encoder.valueEncoder.IsEmpty(p)
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)
}

99
vendor/github.com/json-iterator/go/reflect_slice.go generated vendored Normal file
View file

@ -0,0 +1,99 @@
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
}
}

View file

@ -3,38 +3,78 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"strings"
"unsafe"
"github.com/modern-go/reflect2"
)
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
knownHash := map[int32]struct{}{
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)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
}
case 2:
var fieldHash1 int32
var fieldHash2 int32
var fieldHash1 int64
var fieldHash2 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldHash1 == 0 {
@ -47,17 +87,17 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}
case 3:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
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)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -76,19 +116,19 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3}
case 4:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
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)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -111,21 +151,21 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}
case 5:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
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)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -152,12 +192,12 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5}
case 6:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
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
@ -165,10 +205,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -199,13 +239,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6}
case 7:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
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
@ -214,10 +254,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
var fieldDecoder6 *structFieldDecoder
var fieldDecoder7 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -252,14 +292,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}
case 8:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
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
@ -269,10 +309,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
var fieldDecoder7 *structFieldDecoder
var fieldDecoder8 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -311,15 +351,15 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8}
case 9:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
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
@ -330,10 +370,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
var fieldDecoder8 *structFieldDecoder
var fieldDecoder9 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -376,16 +416,16 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName8, fieldDecoder8,
fieldName9, fieldDecoder9}
case 10:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
var fieldName10 int32
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
@ -397,10 +437,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
var fieldDecoder9 *structFieldDecoder
var fieldDecoder10 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -447,61 +487,69 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}
}
return &generalStructDecoder{typ, fields}
return &generalStructDecoder{typ, fields, false}
}
type generalStructDecoder struct {
typ reflect.Type
fields map[string]*structFieldDecoder
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
var fieldBytes []byte
var field string
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c := iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
}
fieldDecoder := decoder.fields[strings.ToLower(field)]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.Decode(ptr, iter)
}
for iter.nextToken() == ',' {
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes := iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c := iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
}
fieldDecoder = decoder.fields[strings.ToLower(field)]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.Decode(ptr, iter)
}
var c byte
for c = ','; c == ','; c = iter.nextToken() {
decoder.decodeOneField(ptr, iter)
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
if c != '}' {
iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c}))
}
}
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 {
msg := "found unknown field: " + field
if decoder.disallowUnknownFields {
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 reflect.Type
typ reflect2.Type
}
func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
@ -514,8 +562,8 @@ func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
type oneFieldStructDecoder struct {
typ reflect.Type
fieldHash int32
typ reflect2.Type
fieldHash int64
fieldDecoder *structFieldDecoder
}
@ -539,10 +587,10 @@ func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
}
type twoFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
}
@ -569,12 +617,12 @@ func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type threeFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
}
@ -603,14 +651,14 @@ func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type fourFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
}
@ -641,16 +689,16 @@ func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type fiveFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
}
@ -683,18 +731,18 @@ func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type sixFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
}
@ -729,20 +777,20 @@ func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type sevenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
}
@ -779,22 +827,22 @@ func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type eightFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
}
@ -833,24 +881,24 @@ func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type nineFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldHash9 int64
fieldDecoder9 *structFieldDecoder
}
@ -891,26 +939,26 @@ func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type tenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldHash9 int64
fieldDecoder9 *structFieldDecoder
fieldHash10 int32
fieldHash10 int64
fieldDecoder10 *structFieldDecoder
}
@ -953,14 +1001,48 @@ func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type structFieldDecoder struct {
field *reflect.StructField
field reflect2.StructField
fieldDecoder ValDecoder
}
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + decoder.field.Offset)
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())
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) {
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
}
}

View file

@ -2,20 +2,20 @@ package jsoniter
import (
"fmt"
"github.com/modern-go/reflect2"
"io"
"reflect"
"strings"
"unsafe"
)
func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
type bindingTo struct {
binding *Binding
toName string
ignored bool
}
orderedBindings := []*bindingTo{}
structDescriptor := describeStruct(cfg, prefix, typ)
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames {
new := &bindingTo{
@ -26,7 +26,7 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
if old.toName != toName {
continue
}
old.ignored, new.ignored = resolveConflictBinding(cfg, old.binding, new.binding)
old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
}
orderedBindings = append(orderedBindings, new)
}
@ -43,13 +43,36 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
})
}
}
return &structEncoder{typ, structDescriptor.onePtrEmbedded,
structDescriptor.onePtrOptimization, finalOrderedFields}
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()) != ""
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) {
@ -76,60 +99,41 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig
}
}
func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
bindings := map[string]*Binding{}
structDescriptor := describeStruct(cfg, prefix, typ)
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
}
}
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(typ, fields)
}
type structFieldEncoder struct {
field *reflect.StructField
field reflect2.StructField
fieldEncoder ValEncoder
omitempty bool
}
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
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())
stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error())
}
}
func (encoder *structFieldEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
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 reflect.Type
onePtrEmbedded bool
onePtrOptimization bool
fields []structFieldTo
typ reflect2.Type
fields []structFieldTo
}
type structFieldTo struct {
@ -144,6 +148,9 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
continue
}
if field.encoder.IsEmbeddedPtrNil(ptr) {
continue
}
if isNotFirst {
stream.WriteMore()
}
@ -157,24 +164,6 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
}
}
func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if encoder.onePtrOptimization {
if e.word == nil && encoder.onePtrEmbedded {
stream.WriteObjectStart()
stream.WriteObjectEnd()
return
}
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
@ -186,10 +175,36 @@ func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteEmptyObject()
}
func (encoder *emptyStructEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
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)
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)
}

View file

@ -10,7 +10,6 @@ type Stream struct {
cfg *frozenConfig
out io.Writer
buf []byte
n int
Error error
indention int
Attachment interface{} // open for customized encoder
@ -24,8 +23,7 @@ func NewStream(cfg API, out io.Writer, bufSize int) *Stream {
return &Stream{
cfg: cfg.(*frozenConfig),
out: out,
buf: make([]byte, bufSize),
n: 0,
buf: make([]byte, 0, bufSize),
Error: nil,
indention: 0,
}
@ -39,22 +37,27 @@ func (stream *Stream) Pool() StreamPool {
// Reset reuse this stream instance by assign a new writer
func (stream *Stream) Reset(out io.Writer) {
stream.out = out
stream.n = 0
stream.buf = stream.buf[:0]
}
// Available returns how many bytes are unused in the buffer.
func (stream *Stream) Available() int {
return len(stream.buf) - stream.n
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 stream.n
return len(stream.buf)
}
// Buffer if writer is nil, use this method to take the result
func (stream *Stream) Buffer() []byte {
return stream.buf[:stream.n]
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.
@ -62,97 +65,34 @@ func (stream *Stream) Buffer() []byte {
// 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) {
for len(p) > stream.Available() && stream.Error == nil {
if stream.out == nil {
stream.growAtLeast(len(p))
} else {
var n int
if stream.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, stream.Error = stream.out.Write(p)
} else {
n = copy(stream.buf[stream.n:], p)
stream.n += n
stream.Flush()
}
nn += n
p = p[n:]
}
stream.buf = append(stream.buf, p...)
if stream.out != nil {
nn, err = stream.out.Write(stream.buf)
stream.buf = stream.buf[nn:]
return
}
if stream.Error != nil {
return nn, stream.Error
}
n := copy(stream.buf[stream.n:], p)
stream.n += n
nn += n
return nn, nil
return len(p), nil
}
// WriteByte writes a single byte.
func (stream *Stream) writeByte(c byte) {
if stream.Error != nil {
return
}
if stream.Available() < 1 {
stream.growAtLeast(1)
}
stream.buf[stream.n] = c
stream.n++
stream.buf = append(stream.buf, c)
}
func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 2 {
stream.growAtLeast(2)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.n += 2
stream.buf = append(stream.buf, c1, c2)
}
func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 3 {
stream.growAtLeast(3)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.n += 3
stream.buf = append(stream.buf, c1, c2, c3)
}
func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 4 {
stream.growAtLeast(4)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.buf[stream.n+3] = c4
stream.n += 4
stream.buf = append(stream.buf, c1, c2, c3, c4)
}
func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 5 {
stream.growAtLeast(5)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.buf[stream.n+3] = c4
stream.buf[stream.n+4] = c5
stream.n += 5
stream.buf = append(stream.buf, c1, c2, c3, c4, c5)
}
// Flush writes any buffered data to the underlying io.Writer.
@ -163,56 +103,20 @@ func (stream *Stream) Flush() error {
if stream.Error != nil {
return stream.Error
}
if stream.n == 0 {
return nil
}
n, err := stream.out.Write(stream.buf[0:stream.n])
if n < stream.n && err == nil {
err = io.ErrShortWrite
}
n, err := stream.out.Write(stream.buf)
if err != nil {
if n > 0 && n < stream.n {
copy(stream.buf[0:stream.n-n], stream.buf[n:stream.n])
if stream.Error == nil {
stream.Error = err
}
stream.n -= n
stream.Error = err
return err
}
stream.n = 0
stream.buf = stream.buf[n:]
return nil
}
func (stream *Stream) ensure(minimal int) {
available := stream.Available()
if available < minimal {
stream.growAtLeast(minimal)
}
}
func (stream *Stream) growAtLeast(minimal int) {
if stream.out != nil {
stream.Flush()
if stream.Available() >= minimal {
return
}
}
toGrow := len(stream.buf)
if toGrow < minimal {
toGrow = minimal
}
newBuf := make([]byte, len(stream.buf)+toGrow)
copy(newBuf, stream.Buffer())
stream.buf = newBuf
}
// WriteRaw write string out without quotes, just like []byte
func (stream *Stream) WriteRaw(s string) {
stream.ensure(len(s))
if stream.Error != nil {
return
}
n := copy(stream.buf[stream.n:], s)
stream.n += n
stream.buf = append(stream.buf, s...)
}
// WriteNil write null to stream
@ -273,6 +177,7 @@ func (stream *Stream) WriteEmptyObject() {
func (stream *Stream) WriteMore() {
stream.writeByte(',')
stream.writeIndention(0)
stream.Flush()
}
// WriteArrayStart write [ with possible indention
@ -300,9 +205,7 @@ func (stream *Stream) writeIndention(delta int) {
}
stream.writeByte('\n')
toWrite := stream.indention - delta
stream.ensure(toWrite)
for i := 0; i < toWrite && stream.n < len(stream.buf); i++ {
stream.buf[stream.n] = ' '
stream.n++
for i := 0; i < toWrite; i++ {
stream.buf = append(stream.buf, ' ')
}
}

View file

@ -21,7 +21,7 @@ func (stream *Stream) WriteFloat32(val float32) {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 32))
stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32)
}
// WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster
@ -43,13 +43,12 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
return
}
stream.writeByte('.')
stream.ensure(10)
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
stream.writeByte('0')
}
stream.WriteUint64(fval)
for stream.buf[stream.n-1] == '0' {
stream.n--
for stream.buf[len(stream.buf)-1] == '0' {
stream.buf = stream.buf[:len(stream.buf)-1]
}
}
@ -63,7 +62,7 @@ func (stream *Stream) WriteFloat64(val float64) {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 64))
stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64)
}
// WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster
@ -85,12 +84,11 @@ func (stream *Stream) WriteFloat64Lossy(val float64) {
return
}
stream.writeByte('.')
stream.ensure(10)
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
stream.writeByte('0')
}
stream.WriteUint64(fval)
for stream.buf[stream.n-1] == '0' {
stream.n--
for stream.buf[len(stream.buf)-1] == '0' {
stream.buf = stream.buf[:len(stream.buf)-1]
}
}

190
vendor/github.com/json-iterator/go/stream_int.go generated vendored Normal file
View file

@ -0,0 +1,190 @@
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))
}

View file

@ -219,34 +219,22 @@ var hex = "0123456789abcdef"
// WriteStringWithHTMLEscaped write string to stream with html special characters escaped
func (stream *Stream) WriteStringWithHTMLEscaped(s string) {
stream.ensure(32)
valLen := len(s)
toWriteLen := valLen
bufLengthMinusTwo := len(stream.buf) - 2 // make room for the quotes
if stream.n+toWriteLen > bufLengthMinusTwo {
toWriteLen = bufLengthMinusTwo - stream.n
}
n := stream.n
stream.buf[n] = '"'
n++
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < toWriteLen; i++ {
for ; i < valLen; i++ {
c := s[i]
if c < utf8.RuneSelf && htmlSafeSet[c] {
stream.buf[n] = c
n++
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf[n] = '"'
n++
stream.n = n
stream.buf = append(stream.buf, '"')
return
}
stream.n = n
writeStringSlowPathWithHTMLEscaped(stream, i, s, valLen)
}
@ -321,34 +309,22 @@ func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen
// WriteString write string to stream without html escape
func (stream *Stream) WriteString(s string) {
stream.ensure(32)
valLen := len(s)
toWriteLen := valLen
bufLengthMinusTwo := len(stream.buf) - 2 // make room for the quotes
if stream.n+toWriteLen > bufLengthMinusTwo {
toWriteLen = bufLengthMinusTwo - stream.n
}
n := stream.n
stream.buf[n] = '"'
n++
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < toWriteLen; i++ {
for ; i < valLen; i++ {
c := s[i]
if c > 31 && c != '"' && c != '\\' {
stream.buf[n] = c
n++
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf[n] = '"'
n++
stream.n = n
stream.buf = append(stream.buf, '"')
return
}
stream.n = n
writeStringSlowPath(stream, i, s, valLen)
}