You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	#53 split config into Config and frozenConfig
This commit is contained in:
		| @@ -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) | ||||
| } | ||||
|   | ||||
| @@ -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{} | ||||
| var DEFAULT_CONFIG = Config{}.Froze() | ||||
|  | ||||
| func init() { | ||||
| 	DEFAULT_CONFIG.init() | ||||
| func (cfg Config) Froze() *frozenConfig { | ||||
| 	frozenConfig := &frozenConfig{ | ||||
| 		indentionStep: cfg.IndentionStep, | ||||
| 	} | ||||
|  | ||||
| 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{})) | ||||
| 	atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]Decoder{})) | ||||
| 	atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]Encoder{})) | ||||
| 	if cfg.MarshalFloatWith6Digits { | ||||
| 			cfg.marshalFloatWith6Digits() | ||||
| 		frozenConfig.marshalFloatWith6Digits() | ||||
| 	} | ||||
| 	if cfg.SupportUnexportedStructFields { | ||||
| 			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) | ||||
|   | ||||
| @@ -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)) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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(']') | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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())) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user