|
|
@@ -5,7 +5,6 @@ import (
|
|
|
"errors"
|
|
|
"io"
|
|
|
"reflect"
|
|
|
- "sync/atomic"
|
|
|
"unsafe"
|
|
|
)
|
|
|
|
|
|
@@ -23,19 +22,6 @@ type Config struct {
|
|
|
ObjectFieldMustBeSimpleString bool
|
|
|
}
|
|
|
|
|
|
-type frozenConfig struct {
|
|
|
- configBeforeFrozen Config
|
|
|
- sortMapKeys bool
|
|
|
- indentionStep int
|
|
|
- objectFieldMustBeSimpleString bool
|
|
|
- onlyTaggedField bool
|
|
|
- decoderCache unsafe.Pointer
|
|
|
- encoderCache unsafe.Pointer
|
|
|
- extensions []Extension
|
|
|
- streamPool chan *Stream
|
|
|
- iteratorPool chan *Iterator
|
|
|
-}
|
|
|
-
|
|
|
// API the public interface of this package.
|
|
|
// Primary Marshal and Unmarshal.
|
|
|
type API interface {
|
|
|
@@ -83,8 +69,7 @@ func (cfg Config) Froze() API {
|
|
|
streamPool: make(chan *Stream, 16),
|
|
|
iteratorPool: make(chan *Iterator, 16),
|
|
|
}
|
|
|
- atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]ValDecoder{}))
|
|
|
- atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]ValEncoder{}))
|
|
|
+ frozenConfig.initCache()
|
|
|
if cfg.MarshalFloatWith6Digits {
|
|
|
frozenConfig.marshalFloatWith6Digits()
|
|
|
}
|
|
|
@@ -198,46 +183,6 @@ func (cfg *frozenConfig) escapeHTML() {
|
|
|
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
|
|
|
}
|
|
|
|
|
|
-func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
|
|
|
- done := false
|
|
|
- for !done {
|
|
|
- ptr := atomic.LoadPointer(&cfg.decoderCache)
|
|
|
- cache := *(*map[reflect.Type]ValDecoder)(ptr)
|
|
|
- copied := map[reflect.Type]ValDecoder{}
|
|
|
- for k, v := range cache {
|
|
|
- copied[k] = v
|
|
|
- }
|
|
|
- copied[cacheKey] = decoder
|
|
|
- done = atomic.CompareAndSwapPointer(&cfg.decoderCache, ptr, unsafe.Pointer(&copied))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
|
|
|
- done := false
|
|
|
- for !done {
|
|
|
- ptr := atomic.LoadPointer(&cfg.encoderCache)
|
|
|
- cache := *(*map[reflect.Type]ValEncoder)(ptr)
|
|
|
- copied := map[reflect.Type]ValEncoder{}
|
|
|
- for k, v := range cache {
|
|
|
- copied[k] = v
|
|
|
- }
|
|
|
- copied[cacheKey] = encoder
|
|
|
- done = atomic.CompareAndSwapPointer(&cfg.encoderCache, ptr, unsafe.Pointer(&copied))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
|
|
|
- ptr := atomic.LoadPointer(&cfg.decoderCache)
|
|
|
- cache := *(*map[reflect.Type]ValDecoder)(ptr)
|
|
|
- return cache[cacheKey]
|
|
|
-}
|
|
|
-
|
|
|
-func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
|
|
|
- ptr := atomic.LoadPointer(&cfg.encoderCache)
|
|
|
- cache := *(*map[reflect.Type]ValEncoder)(ptr)
|
|
|
- return cache[cacheKey]
|
|
|
-}
|
|
|
-
|
|
|
func (cfg *frozenConfig) cleanDecoders() {
|
|
|
typeDecoders = map[string]ValDecoder{}
|
|
|
fieldDecoders = map[string]ValDecoder{}
|