Parcourir la source

#53 split config into Config and frozenConfig

Tao Wen il y a 8 ans
Parent
commit
d867c8ba5c

+ 2 - 2
feature_adapter.go

@@ -172,7 +172,7 @@ func (decoder *AdaptedDecoder) UseNumber() {
 }
 
 func NewEncoder(writer io.Writer) *AdaptedEncoder {
-	stream := NewStream(&Config{}, writer, 512)
+	stream := NewStream(Config{}.Froze(), writer, 512)
 	return &AdaptedEncoder{stream}
 }
 
@@ -187,5 +187,5 @@ func (adapter *AdaptedEncoder) Encode(val interface{}) error {
 }
 
 func (adapter *AdaptedEncoder) SetIndent(prefix, indent string) {
-	adapter.stream.cfg.IndentionStep = len(indent)
+	adapter.stream.cfg.indentionStep = len(indent)
 }

+ 29 - 29
feature_config.go

@@ -11,37 +11,38 @@ type Config struct {
 	IndentionStep                 int
 	MarshalFloatWith6Digits       bool
 	SupportUnexportedStructFields bool
+}
+
+type frozenConfig struct {
+	indentionStep                 int
 	decoderCache                  unsafe.Pointer
 	encoderCache                  unsafe.Pointer
 	extensions                    []ExtensionFunc
 }
 
-var DEFAULT_CONFIG = &Config{}
-
-func init() {
-	DEFAULT_CONFIG.init()
-}
+var DEFAULT_CONFIG = Config{}.Froze()
 
-func (cfg *Config) init() *Config {
-	if cfg.encoderCache == nil {
-		atomic.StorePointer(&cfg.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
-		atomic.StorePointer(&cfg.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
-		if cfg.MarshalFloatWith6Digits {
-			cfg.marshalFloatWith6Digits()
-		}
-		if cfg.SupportUnexportedStructFields {
-			cfg.supportUnexportedStructFields()
-		}
+func (cfg Config) Froze() *frozenConfig {
+	frozenConfig := &frozenConfig{
+		indentionStep: cfg.IndentionStep,
+	}
+	atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
+	atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
+	if cfg.MarshalFloatWith6Digits {
+		frozenConfig.marshalFloatWith6Digits()
+	}
+	if cfg.SupportUnexportedStructFields {
+		frozenConfig.supportUnexportedStructFields()
 	}
-	return cfg
+	return frozenConfig
 }
 
 // RegisterExtension can register a custom extension
-func (cfg *Config) RegisterExtension(extension ExtensionFunc) {
+func (cfg *frozenConfig) RegisterExtension(extension ExtensionFunc) {
 	cfg.extensions = append(cfg.extensions, extension)
 }
 
-func (cfg *Config) supportUnexportedStructFields() {
+func (cfg *frozenConfig) supportUnexportedStructFields() {
 	cfg.RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, EncoderFunc, DecoderFunc) {
 		return []string{field.Name}, nil, nil
 	})
@@ -49,7 +50,7 @@ func (cfg *Config) supportUnexportedStructFields() {
 
 // EnableLossyFloatMarshalling keeps 10**(-6) precision
 // for float variables for better performance.
-func (cfg *Config) marshalFloatWith6Digits() {
+func (cfg *frozenConfig) marshalFloatWith6Digits() {
 	// for better performance
 	cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
 		val := *((*float32)(ptr))
@@ -61,7 +62,7 @@ func (cfg *Config) marshalFloatWith6Digits() {
 	}})
 }
 
-func (cfg *Config) addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
+func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
 	done := false
 	for !done {
 		ptr := atomic.LoadPointer(&cfg.decoderCache)
@@ -75,7 +76,7 @@ func (cfg *Config) addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
 	}
 }
 
-func (cfg *Config) addEncoderToCache(cacheKey reflect.Type, encoder Encoder) {
+func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder Encoder) {
 	done := false
 	for !done {
 		ptr := atomic.LoadPointer(&cfg.encoderCache)
@@ -89,33 +90,33 @@ func (cfg *Config) addEncoderToCache(cacheKey reflect.Type, encoder Encoder) {
 	}
 }
 
-func (cfg *Config) getDecoderFromCache(cacheKey reflect.Type) Decoder {
+func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) Decoder {
 	ptr := atomic.LoadPointer(&cfg.decoderCache)
 	cache := *(*map[reflect.Type]Decoder)(ptr)
 	return cache[cacheKey]
 }
 
-func (cfg *Config) getEncoderFromCache(cacheKey reflect.Type) Encoder {
+func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) Encoder {
 	ptr := atomic.LoadPointer(&cfg.encoderCache)
 	cache := *(*map[reflect.Type]Encoder)(ptr)
 	return cache[cacheKey]
 }
 
 // CleanDecoders cleans decoders registered or cached
-func (cfg *Config) CleanDecoders() {
+func (cfg *frozenConfig) CleanDecoders() {
 	typeDecoders = map[string]Decoder{}
 	fieldDecoders = map[string]Decoder{}
 	atomic.StorePointer(&cfg.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
 }
 
 // CleanEncoders cleans encoders registered or cached
-func (cfg *Config) CleanEncoders() {
+func (cfg *frozenConfig) CleanEncoders() {
 	typeEncoders = map[string]Encoder{}
 	fieldEncoders = map[string]Encoder{}
 	atomic.StorePointer(&cfg.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
 }
 
-func (cfg *Config) MarshalToString(v interface{}) (string, error) {
+func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
 	buf, err := cfg.Marshal(v)
 	if err != nil {
 		return "", err
@@ -123,8 +124,7 @@ func (cfg *Config) MarshalToString(v interface{}) (string, error) {
 	return string(buf), nil
 }
 
-func (cfg *Config) Marshal(v interface{}) ([]byte, error) {
-	cfg.init()
+func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
 	stream := NewStream(cfg, nil, 256)
 	stream.WriteVal(v)
 	if stream.Error != nil {
@@ -133,7 +133,7 @@ func (cfg *Config) Marshal(v interface{}) ([]byte, error) {
 	return stream.Buffer(), nil
 }
 
-func (cfg *Config) UnmarshalFromString(str string, v interface{}) error {
+func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
 	data := []byte(str)
 	data = data[:lastNotSpacePos(data)]
 	iter := ParseBytes(cfg, data)

+ 5 - 8
feature_iter.go

@@ -66,7 +66,7 @@ func init() {
 
 // Iterator is a fast and flexible JSON parser
 type Iterator struct {
-	cfg    *Config
+	cfg    *frozenConfig
 	reader io.Reader
 	buf    []byte
 	head   int
@@ -75,8 +75,7 @@ type Iterator struct {
 }
 
 // Create creates an empty Iterator instance
-func NewIterator(cfg *Config) *Iterator {
-	cfg.init()
+func NewIterator(cfg *frozenConfig) *Iterator {
 	return &Iterator{
 		cfg:    cfg,
 		reader: nil,
@@ -87,8 +86,7 @@ func NewIterator(cfg *Config) *Iterator {
 }
 
 // Parse parses a json buffer in io.Reader into an Iterator instance
-func Parse(cfg *Config, reader io.Reader, bufSize int) *Iterator {
-	cfg.init()
+func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator {
 	return &Iterator{
 		cfg:    cfg,
 		reader: reader,
@@ -99,8 +97,7 @@ func Parse(cfg *Config, reader io.Reader, bufSize int) *Iterator {
 }
 
 // ParseBytes parses a json byte slice into an Iterator instance
-func ParseBytes(cfg *Config, input []byte) *Iterator {
-	cfg.init()
+func ParseBytes(cfg *frozenConfig, input []byte) *Iterator {
 	return &Iterator{
 		cfg:    cfg,
 		reader: nil,
@@ -111,7 +108,7 @@ func ParseBytes(cfg *Config, input []byte) *Iterator {
 }
 
 // ParseString parses a json string into an Iterator instance
-func ParseString(cfg *Config, input string) *Iterator {
+func ParseString(cfg *frozenConfig, input string) *Iterator {
 	return ParseBytes(cfg, []byte(input))
 }
 

+ 8 - 8
feature_reflect.go

@@ -264,7 +264,7 @@ func (p prefix) addToEncoder(encoder Encoder, err error) (Encoder, error) {
 	return encoder, err
 }
 
-func decoderOfType(cfg *Config, typ reflect.Type) (Decoder, error) {
+func decoderOfType(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	typeName := typ.String()
 	typeDecoder := typeDecoders[typeName]
 	if typeDecoder != nil {
@@ -289,7 +289,7 @@ func decoderOfType(cfg *Config, typ reflect.Type) (Decoder, error) {
 	return newDecoder, err
 }
 
-func createDecoderOfType(cfg *Config, typ reflect.Type) (Decoder, error) {
+func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	if typ.String() == "[]uint8" {
 		return &base64Codec{}, nil
 	}
@@ -354,7 +354,7 @@ func createDecoderOfType(cfg *Config, typ reflect.Type) (Decoder, error) {
 	}
 }
 
-func encoderOfType(cfg *Config, typ reflect.Type) (Encoder, error) {
+func encoderOfType(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	typeName := typ.String()
 	typeEncoder := typeEncoders[typeName]
 	if typeEncoder != nil {
@@ -379,7 +379,7 @@ func encoderOfType(cfg *Config, typ reflect.Type) (Encoder, error) {
 	return newEncoder, err
 }
 
-func createEncoderOfType(cfg *Config, typ reflect.Type) (Encoder, error) {
+func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	if typ.String() == "[]uint8" {
 		return &base64Codec{}, nil
 	}
@@ -445,7 +445,7 @@ func createEncoderOfType(cfg *Config, typ reflect.Type) (Encoder, error) {
 	}
 }
 
-func decoderOfOptional(cfg *Config, typ reflect.Type) (Decoder, error) {
+func decoderOfOptional(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	elemType := typ.Elem()
 	decoder, err := decoderOfType(cfg, elemType)
 	if err != nil {
@@ -454,7 +454,7 @@ func decoderOfOptional(cfg *Config, typ reflect.Type) (Decoder, error) {
 	return &optionalDecoder{elemType, decoder}, nil
 }
 
-func encoderOfOptional(cfg *Config, typ reflect.Type) (Encoder, error) {
+func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	elemType := typ.Elem()
 	elemEncoder, err := encoderOfType(cfg, elemType)
 	if err != nil {
@@ -467,7 +467,7 @@ func encoderOfOptional(cfg *Config, typ reflect.Type) (Encoder, error) {
 	return encoder, nil
 }
 
-func decoderOfMap(cfg *Config, typ reflect.Type) (Decoder, error) {
+func decoderOfMap(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	decoder, err := decoderOfType(cfg, typ.Elem())
 	if err != nil {
 		return nil, err
@@ -480,7 +480,7 @@ func extractInterface(val interface{}) emptyInterface {
 	return *((*emptyInterface)(unsafe.Pointer(&val)))
 }
 
-func encoderOfMap(cfg *Config, typ reflect.Type) (Encoder, error) {
+func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	elemType := typ.Elem()
 	encoder, err := encoderOfType(cfg, elemType)
 	if err != nil {

+ 2 - 2
feature_reflect_array.go

@@ -7,7 +7,7 @@ import (
 	"unsafe"
 )
 
-func decoderOfSlice(cfg *Config, typ reflect.Type) (Decoder, error) {
+func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	decoder, err := decoderOfType(cfg, typ.Elem())
 	if err != nil {
 		return nil, err
@@ -15,7 +15,7 @@ func decoderOfSlice(cfg *Config, typ reflect.Type) (Decoder, error) {
 	return &sliceDecoder{typ, typ.Elem(), decoder}, nil
 }
 
-func encoderOfSlice(cfg *Config, typ reflect.Type) (Encoder, error) {
+func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	encoder, err := encoderOfType(cfg, typ.Elem())
 	if err != nil {
 		return nil, err

+ 2 - 2
feature_reflect_object.go

@@ -9,7 +9,7 @@ import (
 	"unsafe"
 )
 
-func encoderOfStruct(cfg *Config, typ reflect.Type) (Encoder, error) {
+func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 	structEncoder_ := &structEncoder{}
 	fields := map[string]*structFieldEncoder{}
 	for _, field := range listStructFields(typ) {
@@ -80,7 +80,7 @@ func listStructFields(typ reflect.Type) []*reflect.StructField {
 	return fields
 }
 
-func decoderOfStruct(cfg *Config, typ reflect.Type) (Decoder, error) {
+func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 	fields := map[string]*structFieldDecoder{}
 	for i := 0; i < typ.NumField(); i++ {
 		field := typ.Field(i)

+ 8 - 9
feature_stream.go

@@ -5,7 +5,7 @@ import (
 )
 
 type Stream struct {
-	cfg       *Config
+	cfg       *frozenConfig
 	out       io.Writer
 	buf       []byte
 	n         int
@@ -13,8 +13,7 @@ type Stream struct {
 	indention int
 }
 
-func NewStream(cfg *Config, out io.Writer, bufSize int) *Stream {
-	cfg.init()
+func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream {
 	return &Stream{
 		cfg:       cfg,
 		out:       out,
@@ -277,7 +276,7 @@ func (stream *Stream) WriteBool(val bool) {
 }
 
 func (stream *Stream) WriteObjectStart() {
-	stream.indention += stream.cfg.IndentionStep
+	stream.indention += stream.cfg.indentionStep
 	stream.writeByte('{')
 	stream.writeIndention(0)
 }
@@ -288,8 +287,8 @@ func (stream *Stream) WriteObjectField(field string) {
 }
 
 func (stream *Stream) WriteObjectEnd() {
-	stream.writeIndention(stream.cfg.IndentionStep)
-	stream.indention -= stream.cfg.IndentionStep
+	stream.writeIndention(stream.cfg.indentionStep)
+	stream.indention -= stream.cfg.indentionStep
 	stream.writeByte('}')
 }
 
@@ -304,7 +303,7 @@ func (stream *Stream) WriteMore() {
 }
 
 func (stream *Stream) WriteArrayStart() {
-	stream.indention += stream.cfg.IndentionStep
+	stream.indention += stream.cfg.indentionStep
 	stream.writeByte('[')
 	stream.writeIndention(0)
 }
@@ -315,8 +314,8 @@ func (stream *Stream) WriteEmptyArray() {
 }
 
 func (stream *Stream) WriteArrayEnd() {
-	stream.writeIndention(stream.cfg.IndentionStep)
-	stream.indention -= stream.cfg.IndentionStep
+	stream.writeIndention(stream.cfg.indentionStep)
+	stream.indention -= stream.cfg.indentionStep
 	stream.writeByte(']')
 }
 

+ 1 - 1
jsoniter_array_test.go

@@ -213,7 +213,7 @@ func Test_whitespace_before_comma(t *testing.T) {
 func Test_write_array(t *testing.T) {
 	should := require.New(t)
 	buf := &bytes.Buffer{}
-	stream := NewStream(&Config{IndentionStep: 2}, buf, 4096)
+	stream := NewStream(Config{IndentionStep: 2}.Froze(), buf, 4096)
 	stream.WriteArrayStart()
 	stream.WriteInt(1)
 	stream.WriteMore()

+ 2 - 2
jsoniter_customize_test.go

@@ -60,7 +60,7 @@ func Test_customize_byte_array_encoder(t *testing.T) {
 
 func Test_customize_float_marshal(t *testing.T) {
 	should := require.New(t)
-	json := Config{MarshalFloatWith6Digits: true}
+	json := Config{MarshalFloatWith6Digits: true}.Froze()
 	str, err := json.MarshalToString(float32(1.23456789))
 	should.Nil(err)
 	should.Equal("1.234568", str)
@@ -112,7 +112,7 @@ func Test_customize_field_by_extension(t *testing.T) {
 }
 
 func Test_unexported_fields(t *testing.T) {
-	jsoniter := &Config{SupportUnexportedStructFields: true}
+	jsoniter := Config{SupportUnexportedStructFields: true}.Froze()
 	should := require.New(t)
 	type TestObject struct {
 		field1 string

+ 1 - 1
jsoniter_object_test.go

@@ -210,7 +210,7 @@ func Test_object_wrapper_any_get_all(t *testing.T) {
 func Test_write_object(t *testing.T) {
 	should := require.New(t)
 	buf := &bytes.Buffer{}
-	stream := NewStream(&Config{IndentionStep: 2}, buf, 4096)
+	stream := NewStream(Config{IndentionStep: 2}.Froze(), buf, 4096)
 	stream.WriteObjectStart()
 	stream.WriteObjectField("hello")
 	stream.WriteInt(1)

+ 1 - 1
jsoniter_stream_test.go

@@ -31,7 +31,7 @@ func Test_writeBytes_should_grow_buffer(t *testing.T) {
 
 func Test_writeIndention_should_grow_buffer(t *testing.T) {
 	should := require.New(t)
-	stream := NewStream(&Config{IndentionStep: 2}, nil, 1)
+	stream := NewStream(Config{IndentionStep: 2}.Froze(), nil, 1)
 	stream.WriteVal([]int{1, 2, 3})
 	should.Equal("[\n  1,\n  2,\n  3\n]", string(stream.Buffer()))
 }