You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	document public symbols
This commit is contained in:
		| @@ -160,8 +160,8 @@ type tolerateEmptyArrayDecoder struct { | |||||||
| func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { | func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { | ||||||
| 	if iter.WhatIsNext() == jsoniter.Array { | 	if iter.WhatIsNext() == jsoniter.Array { | ||||||
| 		iter.Skip() | 		iter.Skip() | ||||||
| 		newIter := iter.Config().BorrowIterator([]byte("{}")) | 		newIter := iter.Pool().BorrowIterator([]byte("{}")) | ||||||
| 		defer iter.Config().ReturnIterator(newIter) | 		defer iter.Pool().ReturnIterator(newIter) | ||||||
| 		decoder.valDecoder.Decode(ptr, newIter) | 		decoder.valDecoder.Decode(ptr, newIter) | ||||||
| 	} else { | 	} else { | ||||||
| 		decoder.valDecoder.Decode(ptr, iter) | 		decoder.valDecoder.Decode(ptr, iter) | ||||||
| @@ -202,8 +202,8 @@ func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It | |||||||
| 	default: | 	default: | ||||||
| 		iter.ReportError("fuzzyIntegerDecoder", "not number or string") | 		iter.ReportError("fuzzyIntegerDecoder", "not number or string") | ||||||
| 	} | 	} | ||||||
| 	newIter := iter.Config().BorrowIterator([]byte(str)) | 	newIter := iter.Pool().BorrowIterator([]byte(str)) | ||||||
| 	defer iter.Config().ReturnIterator(newIter) | 	defer iter.Pool().ReturnIterator(newIter) | ||||||
| 	isFloat := strings.IndexByte(str, '.') != -1 | 	isFloat := strings.IndexByte(str, '.') != -1 | ||||||
| 	decoder.fun(isFloat, ptr, newIter) | 	decoder.fun(isFloat, ptr, newIter) | ||||||
| 	if newIter.Error != nil { | 	if newIter.Error != nil { | ||||||
| @@ -222,8 +222,8 @@ func (decoder *fuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It | |||||||
| 		*((*float32)(ptr)) = iter.ReadFloat32() | 		*((*float32)(ptr)) = iter.ReadFloat32() | ||||||
| 	case jsoniter.String: | 	case jsoniter.String: | ||||||
| 		str = iter.ReadString() | 		str = iter.ReadString() | ||||||
| 		newIter := iter.Config().BorrowIterator([]byte(str)) | 		newIter := iter.Pool().BorrowIterator([]byte(str)) | ||||||
| 		defer iter.Config().ReturnIterator(newIter) | 		defer iter.Pool().ReturnIterator(newIter) | ||||||
| 		*((*float32)(ptr)) = newIter.ReadFloat32() | 		*((*float32)(ptr)) = newIter.ReadFloat32() | ||||||
| 		if newIter.Error != nil { | 		if newIter.Error != nil { | ||||||
| 			iter.Error = newIter.Error | 			iter.Error = newIter.Error | ||||||
| @@ -244,8 +244,8 @@ func (decoder *fuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It | |||||||
| 		*((*float64)(ptr)) = iter.ReadFloat64() | 		*((*float64)(ptr)) = iter.ReadFloat64() | ||||||
| 	case jsoniter.String: | 	case jsoniter.String: | ||||||
| 		str = iter.ReadString() | 		str = iter.ReadString() | ||||||
| 		newIter := iter.Config().BorrowIterator([]byte(str)) | 		newIter := iter.Pool().BorrowIterator([]byte(str)) | ||||||
| 		defer iter.Config().ReturnIterator(newIter) | 		defer iter.Pool().ReturnIterator(newIter) | ||||||
| 		*((*float64)(ptr)) = newIter.ReadFloat64() | 		*((*float64)(ptr)) = newIter.ReadFloat64() | ||||||
| 		if newIter.Error != nil { | 		if newIter.Error != nil { | ||||||
| 			iter.Error = newIter.Error | 			iter.Error = newIter.Error | ||||||
|   | |||||||
| @@ -1,14 +1,3 @@ | |||||||
| // Package jsoniter implements encoding and decoding of JSON as defined in |  | ||||||
| // RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json. |  | ||||||
| // Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter |  | ||||||
| // and variable type declarations (if any). |  | ||||||
| // jsoniter interfaces gives 100% compatibility with code using standard lib. |  | ||||||
| // |  | ||||||
| // "JSON and Go" |  | ||||||
| // (https://golang.org/doc/articles/json_and_go.html) |  | ||||||
| // gives a description of how Marshal/Unmarshal operate |  | ||||||
| // between arbitrary or predefined json objects and bytes, |  | ||||||
| // and it applies to jsoniter.Marshal/Unmarshal as well. |  | ||||||
| package jsoniter | package jsoniter | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| @@ -96,7 +85,7 @@ func (adapter *Decoder) Buffered() io.Reader { | |||||||
| func (decoder *Decoder) UseNumber() { | func (decoder *Decoder) UseNumber() { | ||||||
| 	origCfg := decoder.iter.cfg.configBeforeFrozen | 	origCfg := decoder.iter.cfg.configBeforeFrozen | ||||||
| 	origCfg.UseNumber = true | 	origCfg.UseNumber = true | ||||||
| 	decoder.iter.cfg = origCfg.Froze() | 	decoder.iter.cfg = origCfg.Froze().(*frozenConfig) | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewEncoder(writer io.Writer) *Encoder { | func NewEncoder(writer io.Writer) *Encoder { | ||||||
| @@ -119,6 +108,6 @@ func (adapter *Encoder) SetIndent(prefix, indent string) { | |||||||
|  |  | ||||||
| func (adapter *Encoder) SetEscapeHTML(escapeHtml bool) { | func (adapter *Encoder) SetEscapeHTML(escapeHtml bool) { | ||||||
| 	config := adapter.stream.cfg.configBeforeFrozen | 	config := adapter.stream.cfg.configBeforeFrozen | ||||||
| 	config.EscapeHtml = escapeHtml | 	config.EscapeHTML = escapeHtml | ||||||
| 	adapter.stream.cfg = config.Froze() | 	adapter.stream.cfg = config.Froze().(*frozenConfig) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,10 +9,12 @@ import ( | |||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Config customize how the API should behave. | ||||||
|  | // The API is created from Config by Froze. | ||||||
| type Config struct { | type Config struct { | ||||||
| 	IndentionStep           int | 	IndentionStep           int | ||||||
| 	MarshalFloatWith6Digits bool | 	MarshalFloatWith6Digits bool | ||||||
| 	EscapeHtml              bool | 	EscapeHTML              bool | ||||||
| 	SortMapKeys             bool | 	SortMapKeys             bool | ||||||
| 	UseNumber               bool | 	UseNumber               bool | ||||||
| } | } | ||||||
| @@ -28,7 +30,11 @@ type frozenConfig struct { | |||||||
| 	iteratorPool       chan *Iterator | 	iteratorPool       chan *Iterator | ||||||
| } | } | ||||||
|  |  | ||||||
| type Api interface { | // API the public interface of this package. | ||||||
|  | // Primary Marshal and Unmarshal. | ||||||
|  | type API interface { | ||||||
|  | 	IteratorPool | ||||||
|  | 	StreamPool | ||||||
| 	MarshalToString(v interface{}) (string, error) | 	MarshalToString(v interface{}) (string, error) | ||||||
| 	Marshal(v interface{}) ([]byte, error) | 	Marshal(v interface{}) ([]byte, error) | ||||||
| 	MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) | 	MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) | ||||||
| @@ -39,22 +45,25 @@ type Api interface { | |||||||
| 	NewDecoder(reader io.Reader) *Decoder | 	NewDecoder(reader io.Reader) *Decoder | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ConfigDefault the default API | ||||||
| var ConfigDefault = Config{ | var ConfigDefault = Config{ | ||||||
| 	EscapeHtml: true, | 	EscapeHTML: true, | ||||||
| }.Froze() | }.Froze() | ||||||
|  |  | ||||||
| // Trying to be 100% compatible with standard library behavior | // ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior | ||||||
| var ConfigCompatibleWithStandardLibrary = Config{ | var ConfigCompatibleWithStandardLibrary = Config{ | ||||||
| 	EscapeHtml:  true, | 	EscapeHTML:  true, | ||||||
| 	SortMapKeys: true, | 	SortMapKeys: true, | ||||||
| }.Froze() | }.Froze() | ||||||
|  |  | ||||||
|  | // ConfigFastest marshals float with only 6 digits precision | ||||||
| var ConfigFastest = Config{ | var ConfigFastest = Config{ | ||||||
| 	EscapeHtml:              false, | 	EscapeHTML:              false, | ||||||
| 	MarshalFloatWith6Digits: true, | 	MarshalFloatWith6Digits: true, | ||||||
| }.Froze() | }.Froze() | ||||||
|  |  | ||||||
| func (cfg Config) Froze() *frozenConfig { | // Froze forge API from config | ||||||
|  | func (cfg Config) Froze() API { | ||||||
| 	// TODO: cache frozen config | 	// TODO: cache frozen config | ||||||
| 	frozenConfig := &frozenConfig{ | 	frozenConfig := &frozenConfig{ | ||||||
| 		sortMapKeys:   cfg.SortMapKeys, | 		sortMapKeys:   cfg.SortMapKeys, | ||||||
| @@ -67,8 +76,8 @@ func (cfg Config) Froze() *frozenConfig { | |||||||
| 	if cfg.MarshalFloatWith6Digits { | 	if cfg.MarshalFloatWith6Digits { | ||||||
| 		frozenConfig.marshalFloatWith6Digits() | 		frozenConfig.marshalFloatWith6Digits() | ||||||
| 	} | 	} | ||||||
| 	if cfg.EscapeHtml { | 	if cfg.EscapeHTML { | ||||||
| 		frozenConfig.escapeHtml() | 		frozenConfig.escapeHTML() | ||||||
| 	} | 	} | ||||||
| 	if cfg.UseNumber { | 	if cfg.UseNumber { | ||||||
| 		frozenConfig.useNumber() | 		frozenConfig.useNumber() | ||||||
| @@ -145,7 +154,7 @@ func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { | |||||||
| 	return *((*string)(ptr)) == "" | 	return *((*string)(ptr)) == "" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cfg *frozenConfig) escapeHtml() { | func (cfg *frozenConfig) escapeHTML() { | ||||||
| 	cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{}) | 	cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{}) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -189,18 +198,16 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder { | |||||||
| 	return cache[cacheKey] | 	return cache[cacheKey] | ||||||
| } | } | ||||||
|  |  | ||||||
| // cleanDecoders cleans decoders registered or cached |  | ||||||
| func (cfg *frozenConfig) cleanDecoders() { | func (cfg *frozenConfig) cleanDecoders() { | ||||||
| 	typeDecoders = map[string]ValDecoder{} | 	typeDecoders = map[string]ValDecoder{} | ||||||
| 	fieldDecoders = map[string]ValDecoder{} | 	fieldDecoders = map[string]ValDecoder{} | ||||||
| 	*cfg = *cfg.configBeforeFrozen.Froze() | 	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) | ||||||
| } | } | ||||||
|  |  | ||||||
| // cleanEncoders cleans encoders registered or cached |  | ||||||
| func (cfg *frozenConfig) cleanEncoders() { | func (cfg *frozenConfig) cleanEncoders() { | ||||||
| 	typeEncoders = map[string]ValEncoder{} | 	typeEncoders = map[string]ValEncoder{} | ||||||
| 	fieldEncoders = map[string]ValEncoder{} | 	fieldEncoders = map[string]ValEncoder{} | ||||||
| 	*cfg = *cfg.configBeforeFrozen.Froze() | 	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) { | func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) { | ||||||
|   | |||||||
| @@ -1,9 +1,3 @@ | |||||||
| // |  | ||||||
| // Besides, jsoniter.Iterator provides a different set of interfaces |  | ||||||
| // iterating given bytes/string/reader |  | ||||||
| // and yielding parsed elements one by one. |  | ||||||
| // This set of interfaces reads input as required and gives |  | ||||||
| // better performance. |  | ||||||
| package jsoniter | package jsoniter | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| @@ -11,15 +5,23 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // ValueType the type for JSON element | ||||||
| type ValueType int | type ValueType int | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
|  | 	// Invalid invalid JSON element | ||||||
| 	Invalid ValueType = iota | 	Invalid ValueType = iota | ||||||
|  | 	// String JSON element "string" | ||||||
| 	String | 	String | ||||||
|  | 	// Number JSON element 100 or 0.10 | ||||||
| 	Number | 	Number | ||||||
|  | 	// Nil JSON element null | ||||||
| 	Nil | 	Nil | ||||||
|  | 	// Bool JSON element true or false | ||||||
| 	Bool | 	Bool | ||||||
|  | 	// Array JSON element [] | ||||||
| 	Array | 	Array | ||||||
|  | 	// Object JSON element {} | ||||||
| 	Object | 	Object | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -63,7 +65,8 @@ func init() { | |||||||
| 	valueTypes['{'] = Object | 	valueTypes['{'] = Object | ||||||
| } | } | ||||||
|  |  | ||||||
| // Iterator is a fast and flexible JSON parser | // Iterator is a io.Reader like object, with JSON specific read functions. | ||||||
|  | // Error is not returned as return value, but stored as Error member on this iterator instance. | ||||||
| type Iterator struct { | type Iterator struct { | ||||||
| 	cfg              *frozenConfig | 	cfg              *frozenConfig | ||||||
| 	reader           io.Reader | 	reader           io.Reader | ||||||
| @@ -75,10 +78,10 @@ type Iterator struct { | |||||||
| 	Error            error | 	Error            error | ||||||
| } | } | ||||||
|  |  | ||||||
| // Create creates an empty Iterator instance | // NewIterator creates an empty Iterator instance | ||||||
| func NewIterator(cfg *frozenConfig) *Iterator { | func NewIterator(cfg API) *Iterator { | ||||||
| 	return &Iterator{ | 	return &Iterator{ | ||||||
| 		cfg:    cfg, | 		cfg:    cfg.(*frozenConfig), | ||||||
| 		reader: nil, | 		reader: nil, | ||||||
| 		buf:    nil, | 		buf:    nil, | ||||||
| 		head:   0, | 		head:   0, | ||||||
| @@ -86,10 +89,10 @@ func NewIterator(cfg *frozenConfig) *Iterator { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Parse parses a json buffer in io.Reader into an Iterator instance | // Parse creates an Iterator instance from io.Reader | ||||||
| func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator { | func Parse(cfg API, reader io.Reader, bufSize int) *Iterator { | ||||||
| 	return &Iterator{ | 	return &Iterator{ | ||||||
| 		cfg:    cfg, | 		cfg:    cfg.(*frozenConfig), | ||||||
| 		reader: reader, | 		reader: reader, | ||||||
| 		buf:    make([]byte, bufSize), | 		buf:    make([]byte, bufSize), | ||||||
| 		head:   0, | 		head:   0, | ||||||
| @@ -97,10 +100,10 @@ func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // ParseBytes parses a json byte slice into an Iterator instance | // ParseBytes creates an Iterator instance from byte array | ||||||
| func ParseBytes(cfg *frozenConfig, input []byte) *Iterator { | func ParseBytes(cfg API, input []byte) *Iterator { | ||||||
| 	return &Iterator{ | 	return &Iterator{ | ||||||
| 		cfg:    cfg, | 		cfg:    cfg.(*frozenConfig), | ||||||
| 		reader: nil, | 		reader: nil, | ||||||
| 		buf:    input, | 		buf:    input, | ||||||
| 		head:   0, | 		head:   0, | ||||||
| @@ -108,16 +111,17 @@ func ParseBytes(cfg *frozenConfig, input []byte) *Iterator { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // ParseString parses a json string into an Iterator instance | // ParseString creates an Iterator instance from string | ||||||
| func ParseString(cfg *frozenConfig, input string) *Iterator { | func ParseString(cfg API, input string) *Iterator { | ||||||
| 	return ParseBytes(cfg, []byte(input)) | 	return ParseBytes(cfg, []byte(input)) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (iter *Iterator) Config() *frozenConfig { | // Pool returns a pool can provide more iterator with same configuration | ||||||
|  | func (iter *Iterator) Pool() IteratorPool { | ||||||
| 	return iter.cfg | 	return iter.cfg | ||||||
| } | } | ||||||
|  |  | ||||||
| // Reset can reset an Iterator instance for another json buffer in io.Reader | // Reset reuse iterator instance by specifying another reader | ||||||
| func (iter *Iterator) Reset(reader io.Reader) *Iterator { | func (iter *Iterator) Reset(reader io.Reader) *Iterator { | ||||||
| 	iter.reader = reader | 	iter.reader = reader | ||||||
| 	iter.head = 0 | 	iter.head = 0 | ||||||
| @@ -125,7 +129,7 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator { | |||||||
| 	return iter | 	return iter | ||||||
| } | } | ||||||
|  |  | ||||||
| // ResetBytes can reset an Iterator instance for another json byte slice | // ResetBytes reuse iterator instance by specifying another byte array as input | ||||||
| func (iter *Iterator) ResetBytes(input []byte) *Iterator { | func (iter *Iterator) ResetBytes(input []byte) *Iterator { | ||||||
| 	iter.reader = nil | 	iter.reader = nil | ||||||
| 	iter.buf = input | 	iter.buf = input | ||||||
| @@ -134,7 +138,7 @@ func (iter *Iterator) ResetBytes(input []byte) *Iterator { | |||||||
| 	return iter | 	return iter | ||||||
| } | } | ||||||
|  |  | ||||||
| // WhatIsNext gets ValueType of relatively next json object | // WhatIsNext gets ValueType of relatively next json element | ||||||
| func (iter *Iterator) WhatIsNext() ValueType { | func (iter *Iterator) WhatIsNext() ValueType { | ||||||
| 	valueType := valueTypes[iter.nextToken()] | 	valueType := valueTypes[iter.nextToken()] | ||||||
| 	iter.unreadByte() | 	iter.unreadByte() | ||||||
| @@ -184,6 +188,7 @@ func (iter *Iterator) nextToken() byte { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReportError record a error in iterator instance with current position. | ||||||
| func (iter *Iterator) ReportError(operation string, msg string) { | func (iter *Iterator) ReportError(operation string, msg string) { | ||||||
| 	if iter.Error != nil { | 	if iter.Error != nil { | ||||||
| 		if iter.Error != io.EOF { | 		if iter.Error != io.EOF { | ||||||
| @@ -198,7 +203,7 @@ func (iter *Iterator) ReportError(operation string, msg string) { | |||||||
| 		string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) | 		string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) | ||||||
| } | } | ||||||
|  |  | ||||||
| // CurrentBuffer gets current buffer as string | // CurrentBuffer gets current buffer as string for debugging purpose | ||||||
| func (iter *Iterator) CurrentBuffer() string { | func (iter *Iterator) CurrentBuffer() string { | ||||||
| 	peekStart := iter.head - 10 | 	peekStart := iter.head - 10 | ||||||
| 	if peekStart < 0 { | 	if peekStart < 0 { | ||||||
| @@ -261,6 +266,7 @@ func (iter *Iterator) unreadByte() { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Read read the next JSON element as generic interface{}. | ||||||
| func (iter *Iterator) Read() interface{} { | func (iter *Iterator) Read() interface{} { | ||||||
| 	valueType := iter.WhatIsNext() | 	valueType := iter.WhatIsNext() | ||||||
| 	switch valueType { | 	switch valueType { | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| package jsoniter | package jsoniter | ||||||
|  |  | ||||||
|  | // ReadArray read array element, tells if the array has more element to read. | ||||||
| func (iter *Iterator) ReadArray() (ret bool) { | func (iter *Iterator) ReadArray() (ret bool) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	switch c { | 	switch c { | ||||||
| @@ -23,6 +24,7 @@ func (iter *Iterator) ReadArray() (ret bool) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadArrayCB read array with callback | ||||||
| func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) { | func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '[' { | 	if c == '[' { | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ func init() { | |||||||
| 	floatDigits['.'] = dotInNumber | 	floatDigits['.'] = dotInNumber | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadBigFloat read big.Float | ||||||
| func (iter *Iterator) ReadBigFloat() (ret *big.Float) { | func (iter *Iterator) ReadBigFloat() (ret *big.Float) { | ||||||
| 	str := iter.readNumberAsString() | 	str := iter.readNumberAsString() | ||||||
| 	if iter.Error != nil && iter.Error != io.EOF { | 	if iter.Error != nil && iter.Error != io.EOF { | ||||||
| @@ -47,6 +48,7 @@ func (iter *Iterator) ReadBigFloat() (ret *big.Float) { | |||||||
| 	return val | 	return val | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadBigInt read big.Int | ||||||
| func (iter *Iterator) ReadBigInt() (ret *big.Int) { | func (iter *Iterator) ReadBigInt() (ret *big.Int) { | ||||||
| 	str := iter.readNumberAsString() | 	str := iter.readNumberAsString() | ||||||
| 	if iter.Error != nil && iter.Error != io.EOF { | 	if iter.Error != nil && iter.Error != io.EOF { | ||||||
| @@ -62,14 +64,14 @@ func (iter *Iterator) ReadBigInt() (ret *big.Int) { | |||||||
| 	return ret | 	return ret | ||||||
| } | } | ||||||
|  |  | ||||||
|  | //ReadFloat32 read float32 | ||||||
| func (iter *Iterator) ReadFloat32() (ret float32) { | func (iter *Iterator) ReadFloat32() (ret float32) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| 		return -iter.readPositiveFloat32() | 		return -iter.readPositiveFloat32() | ||||||
| 	} else { |  | ||||||
| 		iter.unreadByte() |  | ||||||
| 		return iter.readPositiveFloat32() |  | ||||||
| 	} | 	} | ||||||
|  | 	iter.unreadByte() | ||||||
|  | 	return iter.readPositiveFloat32() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (iter *Iterator) readPositiveFloat32() (ret float32) { | func (iter *Iterator) readPositiveFloat32() (ret float32) { | ||||||
| @@ -165,14 +167,14 @@ func (iter *Iterator) readFloat32SlowPath() (ret float32) { | |||||||
| 	return float32(val) | 	return float32(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadFloat64 read float64 | ||||||
| func (iter *Iterator) ReadFloat64() (ret float64) { | func (iter *Iterator) ReadFloat64() (ret float64) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| 		return -iter.readPositiveFloat64() | 		return -iter.readPositiveFloat64() | ||||||
| 	} else { |  | ||||||
| 		iter.unreadByte() |  | ||||||
| 		return iter.readPositiveFloat64() |  | ||||||
| 	} | 	} | ||||||
|  | 	iter.unreadByte() | ||||||
|  | 	return iter.readPositiveFloat64() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (iter *Iterator) readPositiveFloat64() (ret float64) { | func (iter *Iterator) readPositiveFloat64() (ret float64) { | ||||||
|   | |||||||
| @@ -20,14 +20,17 @@ func init() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadUint read uint | ||||||
| func (iter *Iterator) ReadUint() uint { | func (iter *Iterator) ReadUint() uint { | ||||||
| 	return uint(iter.ReadUint64()) | 	return uint(iter.ReadUint64()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadInt read int | ||||||
| func (iter *Iterator) ReadInt() int { | func (iter *Iterator) ReadInt() int { | ||||||
| 	return int(iter.ReadInt64()) | 	return int(iter.ReadInt64()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadInt8 read int8 | ||||||
| func (iter *Iterator) ReadInt8() (ret int8) { | func (iter *Iterator) ReadInt8() (ret int8) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| @@ -37,16 +40,16 @@ func (iter *Iterator) ReadInt8() (ret int8) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		return -int8(val) | 		return -int8(val) | ||||||
| 	} else { |  | ||||||
| 		val := iter.readUint32(c) |  | ||||||
| 		if val > math.MaxInt8 { |  | ||||||
| 			iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		return int8(val) |  | ||||||
| 	} | 	} | ||||||
|  | 	val := iter.readUint32(c) | ||||||
|  | 	if val > math.MaxInt8 { | ||||||
|  | 		iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	return int8(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadUint8 read uint8 | ||||||
| func (iter *Iterator) ReadUint8() (ret uint8) { | func (iter *Iterator) ReadUint8() (ret uint8) { | ||||||
| 	val := iter.readUint32(iter.nextToken()) | 	val := iter.readUint32(iter.nextToken()) | ||||||
| 	if val > math.MaxUint8 { | 	if val > math.MaxUint8 { | ||||||
| @@ -56,6 +59,7 @@ func (iter *Iterator) ReadUint8() (ret uint8) { | |||||||
| 	return uint8(val) | 	return uint8(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadInt16 read int16 | ||||||
| func (iter *Iterator) ReadInt16() (ret int16) { | func (iter *Iterator) ReadInt16() (ret int16) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| @@ -65,16 +69,16 @@ func (iter *Iterator) ReadInt16() (ret int16) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		return -int16(val) | 		return -int16(val) | ||||||
| 	} else { |  | ||||||
| 		val := iter.readUint32(c) |  | ||||||
| 		if val > math.MaxInt16 { |  | ||||||
| 			iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		return int16(val) |  | ||||||
| 	} | 	} | ||||||
|  | 	val := iter.readUint32(c) | ||||||
|  | 	if val > math.MaxInt16 { | ||||||
|  | 		iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	return int16(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadUint16 read uint16 | ||||||
| func (iter *Iterator) ReadUint16() (ret uint16) { | func (iter *Iterator) ReadUint16() (ret uint16) { | ||||||
| 	val := iter.readUint32(iter.nextToken()) | 	val := iter.readUint32(iter.nextToken()) | ||||||
| 	if val > math.MaxUint16 { | 	if val > math.MaxUint16 { | ||||||
| @@ -84,6 +88,7 @@ func (iter *Iterator) ReadUint16() (ret uint16) { | |||||||
| 	return uint16(val) | 	return uint16(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadInt32 read int32 | ||||||
| func (iter *Iterator) ReadInt32() (ret int32) { | func (iter *Iterator) ReadInt32() (ret int32) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| @@ -93,16 +98,16 @@ func (iter *Iterator) ReadInt32() (ret int32) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		return -int32(val) | 		return -int32(val) | ||||||
| 	} else { |  | ||||||
| 		val := iter.readUint32(c) |  | ||||||
| 		if val > math.MaxInt32 { |  | ||||||
| 			iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		return int32(val) |  | ||||||
| 	} | 	} | ||||||
|  | 	val := iter.readUint32(c) | ||||||
|  | 	if val > math.MaxInt32 { | ||||||
|  | 		iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	return int32(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadUint32 read uint32 | ||||||
| func (iter *Iterator) ReadUint32() (ret uint32) { | func (iter *Iterator) ReadUint32() (ret uint32) { | ||||||
| 	return iter.readUint32(iter.nextToken()) | 	return iter.readUint32(iter.nextToken()) | ||||||
| } | } | ||||||
| @@ -182,10 +187,9 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) { | |||||||
| 				if value2 < value { | 				if value2 < value { | ||||||
| 					iter.ReportError("readUint32", "overflow") | 					iter.ReportError("readUint32", "overflow") | ||||||
| 					return | 					return | ||||||
| 				} else { |  | ||||||
| 					value = value2 |  | ||||||
| 					continue |  | ||||||
| 				} | 				} | ||||||
|  | 				value = value2 | ||||||
|  | 				continue | ||||||
| 			} | 			} | ||||||
| 			value = (value << 3) + (value << 1) + uint32(ind) | 			value = (value << 3) + (value << 1) + uint32(ind) | ||||||
| 		} | 		} | ||||||
| @@ -195,6 +199,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadInt64 read int64 | ||||||
| func (iter *Iterator) ReadInt64() (ret int64) { | func (iter *Iterator) ReadInt64() (ret int64) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '-' { | 	if c == '-' { | ||||||
| @@ -204,16 +209,16 @@ func (iter *Iterator) ReadInt64() (ret int64) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		return -int64(val) | 		return -int64(val) | ||||||
| 	} else { |  | ||||||
| 		val := iter.readUint64(c) |  | ||||||
| 		if val > math.MaxInt64 { |  | ||||||
| 			iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		return int64(val) |  | ||||||
| 	} | 	} | ||||||
|  | 	val := iter.readUint64(c) | ||||||
|  | 	if val > math.MaxInt64 { | ||||||
|  | 		iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	return int64(val) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadUint64 read uint64 | ||||||
| func (iter *Iterator) ReadUint64() uint64 { | func (iter *Iterator) ReadUint64() uint64 { | ||||||
| 	return iter.readUint64(iter.nextToken()) | 	return iter.readUint64(iter.nextToken()) | ||||||
| } | } | ||||||
| @@ -240,10 +245,9 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) { | |||||||
| 				if value2 < value { | 				if value2 < value { | ||||||
| 					iter.ReportError("readUint64", "overflow") | 					iter.ReportError("readUint64", "overflow") | ||||||
| 					return | 					return | ||||||
| 				} else { |  | ||||||
| 					value = value2 |  | ||||||
| 					continue |  | ||||||
| 				} | 				} | ||||||
|  | 				value = value2 | ||||||
|  | 				continue | ||||||
| 			} | 			} | ||||||
| 			value = (value << 3) + (value << 1) + uint64(ind) | 			value = (value << 3) + (value << 1) + uint64(ind) | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -6,6 +6,9 @@ import ( | |||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // ReadObject read one field from object. | ||||||
|  | // If object ended, returns empty string. | ||||||
|  | // Otherwise, returns the field name. | ||||||
| func (iter *Iterator) ReadObject() (ret string) { | func (iter *Iterator) ReadObject() (ret string) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	switch c { | 	switch c { | ||||||
| @@ -74,6 +77,7 @@ func calcHash(str string) int32 { | |||||||
| 	return int32(hash) | 	return int32(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 { | func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '{' { | 	if c == '{' { | ||||||
| @@ -106,6 +110,7 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadMapCB read map with callback, the key can be any string | ||||||
| func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { | func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '{' { | 	if c == '{' { | ||||||
|   | |||||||
| @@ -29,6 +29,8 @@ func (iter *Iterator) ReadBool() (ret bool) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // SkipAndReturnBytes skip next JSON element, and return its content as []byte. | ||||||
|  | // The []byte can be kept, it is a copy of data. | ||||||
| func (iter *Iterator) SkipAndReturnBytes() []byte { | func (iter *Iterator) SkipAndReturnBytes() []byte { | ||||||
| 	iter.startCapture(iter.head) | 	iter.startCapture(iter.head) | ||||||
| 	iter.Skip() | 	iter.Skip() | ||||||
| @@ -58,10 +60,9 @@ func (iter *Iterator) stopCapture() []byte { | |||||||
| 	iter.captured = nil | 	iter.captured = nil | ||||||
| 	if len(captured) == 0 { | 	if len(captured) == 0 { | ||||||
| 		return remaining | 		return remaining | ||||||
| 	} else { |  | ||||||
| 		captured = append(captured, remaining...) |  | ||||||
| 		return captured |  | ||||||
| 	} | 	} | ||||||
|  | 	captured = append(captured, remaining...) | ||||||
|  | 	return captured | ||||||
| } | } | ||||||
|  |  | ||||||
| // Skip skips a json object and positions to relatively the next json object | // Skip skips a json object and positions to relatively the next json object | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"unicode/utf16" | 	"unicode/utf16" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // ReadString read string from iterator | ||||||
| func (iter *Iterator) ReadString() (ret string) { | func (iter *Iterator) ReadString() (ret string) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '"' { | 	if c == '"' { | ||||||
| @@ -96,6 +97,8 @@ func (iter *Iterator) readStringSlowPath() (ret string) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ReadStringAsSlice read string from iterator without copying into string form. | ||||||
|  | // The []byte can not be kept, as it will change after next iterator call. | ||||||
| func (iter *Iterator) ReadStringAsSlice() (ret []byte) { | func (iter *Iterator) ReadStringAsSlice() (ret []byte) { | ||||||
| 	c := iter.nextToken() | 	c := iter.nextToken() | ||||||
| 	if c == '"' { | 	if c == '"' { | ||||||
|   | |||||||
| @@ -4,6 +4,18 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // IteratorPool a thread safe pool of iterators with same configuration | ||||||
|  | type IteratorPool interface { | ||||||
|  | 	BorrowIterator(data []byte) *Iterator | ||||||
|  | 	ReturnIterator(iter *Iterator) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StreamPool a thread safe pool of streams with same configuration | ||||||
|  | type StreamPool interface { | ||||||
|  | 	BorrowStream(writer io.Writer) *Stream | ||||||
|  | 	ReturnStream(stream *Stream) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { | func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { | ||||||
| 	select { | 	select { | ||||||
| 	case stream := <-cfg.streamPool: | 	case stream := <-cfg.streamPool: | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ type checkIsEmpty interface { | |||||||
| 	IsEmpty(ptr unsafe.Pointer) bool | 	IsEmpty(ptr unsafe.Pointer) bool | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // WriteToStream the default implementation for TypeEncoder method EncodeInterface | ||||||
| func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) { | func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) { | ||||||
| 	e := (*emptyInterface)(unsafe.Pointer(&val)) | 	e := (*emptyInterface)(unsafe.Pointer(&val)) | ||||||
| 	if e.word == nil { | 	if e.word == nil { | ||||||
| @@ -49,9 +50,6 @@ func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) |  | ||||||
| type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) |  | ||||||
|  |  | ||||||
| var jsonNumberType reflect.Type | var jsonNumberType reflect.Type | ||||||
| var jsonRawMessageType reflect.Type | var jsonRawMessageType reflect.Type | ||||||
| var jsoniterRawMessageType reflect.Type | var jsoniterRawMessageType reflect.Type | ||||||
| @@ -132,9 +130,8 @@ func (encoder *optionalEncoder) EncodeInterface(val interface{}, stream *Stream) | |||||||
| func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { | func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { | ||||||
| 	if *((*unsafe.Pointer)(ptr)) == nil { | 	if *((*unsafe.Pointer)(ptr)) == nil { | ||||||
| 		return true | 		return true | ||||||
| 	} else { |  | ||||||
| 		return false |  | ||||||
| 	} | 	} | ||||||
|  | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| type placeholderEncoder struct { | type placeholderEncoder struct { | ||||||
| @@ -206,7 +203,7 @@ type nonEmptyInterface struct { | |||||||
| 	word unsafe.Pointer | 	word unsafe.Pointer | ||||||
| } | } | ||||||
|  |  | ||||||
| // Read converts an Iterator instance into go interface, same as json.Unmarshal | // ReadVal copy the underlying JSON into go interface, same as json.Unmarshal | ||||||
| func (iter *Iterator) ReadVal(obj interface{}) { | func (iter *Iterator) ReadVal(obj interface{}) { | ||||||
| 	typ := reflect.TypeOf(obj) | 	typ := reflect.TypeOf(obj) | ||||||
| 	cacheKey := typ.Elem() | 	cacheKey := typ.Elem() | ||||||
| @@ -219,6 +216,7 @@ func (iter *Iterator) ReadVal(obj interface{}) { | |||||||
| 	decoder.Decode(e.word, iter) | 	decoder.Decode(e.word, iter) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // WriteVal copy the go interface into underlying JSON, same as json.Marshal | ||||||
| func (stream *Stream) WriteVal(val interface{}) { | func (stream *Stream) WriteVal(val interface{}) { | ||||||
| 	if nil == val { | 	if nil == val { | ||||||
| 		stream.WriteNil() | 		stream.WriteNil() | ||||||
| @@ -393,9 +391,8 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error | |||||||
| 	case reflect.Interface: | 	case reflect.Interface: | ||||||
| 		if typ.NumMethod() == 0 { | 		if typ.NumMethod() == 0 { | ||||||
| 			return &emptyInterfaceCodec{}, nil | 			return &emptyInterfaceCodec{}, nil | ||||||
| 		} else { |  | ||||||
| 			return &nonEmptyInterfaceCodec{}, nil |  | ||||||
| 		} | 		} | ||||||
|  | 		return &nonEmptyInterfaceCodec{}, nil | ||||||
| 	case reflect.Struct: | 	case reflect.Struct: | ||||||
| 		return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ)) | 		return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ)) | ||||||
| 	case reflect.Array: | 	case reflect.Array: | ||||||
| @@ -517,9 +514,8 @@ func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) { | |||||||
| 	case reflect.Interface: | 	case reflect.Interface: | ||||||
| 		if typ.NumMethod() == 0 { | 		if typ.NumMethod() == 0 { | ||||||
| 			return &emptyInterfaceCodec{}, nil | 			return &emptyInterfaceCodec{}, nil | ||||||
| 		} else { |  | ||||||
| 			return &nonEmptyInterfaceCodec{}, nil |  | ||||||
| 		} | 		} | ||||||
|  | 		return &nonEmptyInterfaceCodec{}, nil | ||||||
| 	case reflect.Struct: | 	case reflect.Struct: | ||||||
| 		return &structEncoder{}, nil | 		return &structEncoder{}, nil | ||||||
| 	case reflect.Array: | 	case reflect.Array: | ||||||
| @@ -617,9 +613,8 @@ func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, | |||||||
| 	case reflect.Interface: | 	case reflect.Interface: | ||||||
| 		if typ.NumMethod() == 0 { | 		if typ.NumMethod() == 0 { | ||||||
| 			return &emptyInterfaceCodec{}, nil | 			return &emptyInterfaceCodec{}, nil | ||||||
| 		} else { |  | ||||||
| 			return &nonEmptyInterfaceCodec{}, nil |  | ||||||
| 		} | 		} | ||||||
|  | 		return &nonEmptyInterfaceCodec{}, nil | ||||||
| 	case reflect.Struct: | 	case reflect.Struct: | ||||||
| 		return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ)) | 		return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ)) | ||||||
| 	case reflect.Array: | 	case reflect.Array: | ||||||
| @@ -679,7 +674,6 @@ func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | |||||||
| 	mapInterface := reflect.New(typ).Elem().Interface() | 	mapInterface := reflect.New(typ).Elem().Interface() | ||||||
| 	if cfg.sortMapKeys { | 	if cfg.sortMapKeys { | ||||||
| 		return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil | 		return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil | ||||||
| 	} else { |  | ||||||
| 		return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil |  | ||||||
| 	} | 	} | ||||||
|  | 	return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -110,6 +110,11 @@ func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool { | |||||||
| 	return encoder.isEmptyFunc(ptr) | 	return encoder.isEmptyFunc(ptr) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // DecoderFunc the function form of TypeDecoder | ||||||
|  | type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) | ||||||
|  | // EncoderFunc the function form of TypeEncoder | ||||||
|  | type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) | ||||||
|  |  | ||||||
| // RegisterTypeDecoderFunc register TypeDecoder for a type with function | // RegisterTypeDecoderFunc register TypeDecoder for a type with function | ||||||
| func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) { | func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) { | ||||||
| 	typeDecoders[typ] = &funcDecoder{fun} | 	typeDecoders[typ] = &funcDecoder{fun} | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| package jsoniter | package jsoniter | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"reflect" |  | ||||||
| 	"io" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"reflect" | ||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -71,7 +71,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &threeFieldsStructDecoder{typ, | 		return &threeFieldsStructDecoder{typ, | ||||||
| 										 fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil | ||||||
| 	case 4: | 	case 4: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -103,8 +103,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &fourFieldsStructDecoder{typ, | 		return &fourFieldsStructDecoder{typ, | ||||||
| 										fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 										fieldName4, fieldDecoder4}, nil | 			fieldName4, fieldDecoder4}, nil | ||||||
| 	case 5: | 	case 5: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -141,8 +141,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &fiveFieldsStructDecoder{typ, | 		return &fiveFieldsStructDecoder{typ, | ||||||
| 										fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 										fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil | ||||||
| 	case 6: | 	case 6: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -184,8 +184,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &sixFieldsStructDecoder{typ, | 		return &sixFieldsStructDecoder{typ, | ||||||
| 									   fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 									   fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil | ||||||
| 	case 7: | 	case 7: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -232,9 +232,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &sevenFieldsStructDecoder{typ, | 		return &sevenFieldsStructDecoder{typ, | ||||||
| 										 fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 										 fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | ||||||
| 										 fieldName7, fieldDecoder7}, nil | 			fieldName7, fieldDecoder7}, nil | ||||||
| 	case 8: | 	case 8: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -286,9 +286,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &eightFieldsStructDecoder{typ, | 		return &eightFieldsStructDecoder{typ, | ||||||
| 										 fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 										 fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | ||||||
| 										 fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil | 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil | ||||||
| 	case 9: | 	case 9: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -345,9 +345,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &nineFieldsStructDecoder{typ, | 		return &nineFieldsStructDecoder{typ, | ||||||
| 										fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 										fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | ||||||
| 										fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil | 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil | ||||||
| 	case 10: | 	case 10: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -409,15 +409,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &tenFieldsStructDecoder{typ, | 		return &tenFieldsStructDecoder{typ, | ||||||
| 									   fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||||
| 									   fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | ||||||
| 									   fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, | 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, | ||||||
| 									   fieldName10, fieldDecoder10}, nil | 			fieldName10, fieldDecoder10}, nil | ||||||
| 	} | 	} | ||||||
| 	return &generalStructDecoder{typ, fields}, nil | 	return &generalStructDecoder{typ, fields}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| type generalStructDecoder struct { | type generalStructDecoder struct { | ||||||
| 	typ    reflect.Type | 	typ    reflect.Type | ||||||
| 	fields map[string]*structFieldDecoder | 	fields map[string]*structFieldDecoder | ||||||
| @@ -911,4 +910,4 @@ func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { | |||||||
| 	if iter.Error != nil && iter.Error != io.EOF { | 	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()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Stream is a writer like object, with JSON specific write functions. | // Stream is a io.Writer like object, with JSON specific write functions. | ||||||
| // Error is not returned as return value, but stored as Error member on this stream instance. | // Error is not returned as return value, but stored as Error member on this stream instance. | ||||||
| type Stream struct { | type Stream struct { | ||||||
| 	cfg       *frozenConfig | 	cfg       *frozenConfig | ||||||
| @@ -19,9 +19,9 @@ type Stream struct { | |||||||
| // cfg can be jsoniter.ConfigDefault. | // cfg can be jsoniter.ConfigDefault. | ||||||
| // out can be nil if write to internal buffer. | // out can be nil if write to internal buffer. | ||||||
| // bufSize is the initial size for the internal buffer in bytes. | // bufSize is the initial size for the internal buffer in bytes. | ||||||
| func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream { | func NewStream(cfg API, out io.Writer, bufSize int) *Stream { | ||||||
| 	return &Stream{ | 	return &Stream{ | ||||||
| 		cfg:       cfg, | 		cfg:       cfg.(*frozenConfig), | ||||||
| 		out:       out, | 		out:       out, | ||||||
| 		buf:       make([]byte, bufSize), | 		buf:       make([]byte, bufSize), | ||||||
| 		n:         0, | 		n:         0, | ||||||
| @@ -30,6 +30,11 @@ func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Pool returns a pool can provide more stream with same configuration | ||||||
|  | func (stream *Stream) Pool() StreamPool { | ||||||
|  | 	return stream.cfg | ||||||
|  | } | ||||||
|  |  | ||||||
| // Reset reuse this stream instance by assign a new writer | // Reset reuse this stream instance by assign a new writer | ||||||
| func (stream *Stream) Reset(out io.Writer) { | func (stream *Stream) Reset(out io.Writer) { | ||||||
| 	stream.out = out | 	stream.out = out | ||||||
| @@ -196,7 +201,6 @@ func (stream *Stream) growAtLeast(minimal int) { | |||||||
| 	stream.buf = newBuf | 	stream.buf = newBuf | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // WriteRaw write string out without quotes, just like []byte | // WriteRaw write string out without quotes, just like []byte | ||||||
| func (stream *Stream) WriteRaw(s string) { | func (stream *Stream) WriteRaw(s string) { | ||||||
| 	stream.ensure(len(s)) | 	stream.ensure(len(s)) | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								jsoniter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								jsoniter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | // Package jsoniter implements encoding and decoding of JSON as defined in | ||||||
|  | // RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json. | ||||||
|  | // Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter | ||||||
|  | // and variable type declarations (if any). | ||||||
|  | // jsoniter interfaces gives 100% compatibility with code using standard lib. | ||||||
|  | // | ||||||
|  | // "JSON and Go" | ||||||
|  | // (https://golang.org/doc/articles/json_and_go.html) | ||||||
|  | // gives a description of how Marshal/Unmarshal operate | ||||||
|  | // between arbitrary or predefined json objects and bytes, | ||||||
|  | // and it applies to jsoniter.Marshal/Unmarshal as well. | ||||||
|  | // | ||||||
|  | // Besides, jsoniter.Iterator provides a different set of interfaces | ||||||
|  | // iterating given bytes/string/reader | ||||||
|  | // and yielding parsed elements one by one. | ||||||
|  | // This set of interfaces reads input as required and gives | ||||||
|  | // better performance. | ||||||
|  | package jsoniter | ||||||
| @@ -26,7 +26,7 @@ func Test_new_encoder(t *testing.T) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Test_string_encode_with_std_without_html_escape(t *testing.T) { | func Test_string_encode_with_std_without_html_escape(t *testing.T) { | ||||||
| 	api := Config{EscapeHtml: false}.Froze() | 	api := Config{EscapeHTML: false}.Froze() | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	for i := 0; i < utf8.RuneSelf; i++ { | 	for i := 0; i < utf8.RuneSelf; i++ { | ||||||
| 		input := string([]byte{byte(i)}) | 		input := string([]byte{byte(i)}) | ||||||
|   | |||||||
| @@ -7,25 +7,25 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| var stringConvertMap = map[string]string{ | var stringConvertMap = map[string]string{ | ||||||
| 	"null":              "", | 	"null":                   "", | ||||||
| 	"321.1":             "321.1", | 	"321.1":                  "321.1", | ||||||
| 	`"1.1"`:             "1.1", | 	`"1.1"`:                  "1.1", | ||||||
| 	`"-123.1"`:          "-123.1", | 	`"-123.1"`:               "-123.1", | ||||||
| 	"0.0":               "0.0", | 	"0.0":                    "0.0", | ||||||
| 	"0":                 "0", | 	"0":                      "0", | ||||||
| 	`"0"`:               "0", | 	`"0"`:                    "0", | ||||||
| 	`"0.0"`:             "0.0", | 	`"0.0"`:                  "0.0", | ||||||
| 	`"00.0"`:            "00.0", | 	`"00.0"`:                 "00.0", | ||||||
| 	"true":              "true", | 	"true":                   "true", | ||||||
| 	"false":             "false", | 	"false":                  "false", | ||||||
| 	`"true"`:            "true", | 	`"true"`:                 "true", | ||||||
| 	`"false"`:           "false", | 	`"false"`:                "false", | ||||||
| 	`"true123"`:         "true123", | 	`"true123"`:              "true123", | ||||||
| 	`"+1"`:              "+1", | 	`"+1"`:                   "+1", | ||||||
| 	"[]":                "[]", | 	"[]":                     "[]", | ||||||
| 	"[1,2]":             "[1,2]", | 	"[1,2]":                  "[1,2]", | ||||||
| 	"{}":                "{}", | 	"{}":                     "{}", | ||||||
| 	"{1,2}":             "{1,2}", | 	"{1,2}":                  "{1,2}", | ||||||
| 	`{"a":1, "stream":true}`: `{"a":1, "stream":true}`, | 	`{"a":1, "stream":true}`: `{"a":1, "stream":true}`, | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ func Test_customize_type_decoder(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 		*((*time.Time)(ptr)) = t | 		*((*time.Time)(ptr)) = t | ||||||
| 	}) | 	}) | ||||||
| 	defer ConfigDefault.cleanDecoders() | 	defer ConfigDefault.(*frozenConfig).cleanDecoders() | ||||||
| 	val := time.Time{} | 	val := time.Time{} | ||||||
| 	err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val) | 	err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -36,7 +36,7 @@ func Test_customize_type_encoder(t *testing.T) { | |||||||
| 		t := *((*time.Time)(ptr)) | 		t := *((*time.Time)(ptr)) | ||||||
| 		stream.WriteString(t.UTC().Format("2006-01-02 15:04:05")) | 		stream.WriteString(t.UTC().Format("2006-01-02 15:04:05")) | ||||||
| 	}, nil) | 	}, nil) | ||||||
| 	defer ConfigDefault.cleanEncoders() | 	defer ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	val := time.Unix(0, 0) | 	val := time.Unix(0, 0) | ||||||
| 	str, err := MarshalToString(val) | 	str, err := MarshalToString(val) | ||||||
| 	should.Nil(err) | 	should.Nil(err) | ||||||
| @@ -44,13 +44,13 @@ func Test_customize_type_encoder(t *testing.T) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Test_customize_byte_array_encoder(t *testing.T) { | func Test_customize_byte_array_encoder(t *testing.T) { | ||||||
| 	ConfigDefault.cleanEncoders() | 	ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	RegisterTypeEncoderFunc("[]uint8", func(ptr unsafe.Pointer, stream *Stream) { | 	RegisterTypeEncoderFunc("[]uint8", func(ptr unsafe.Pointer, stream *Stream) { | ||||||
| 		t := *((*[]byte)(ptr)) | 		t := *((*[]byte)(ptr)) | ||||||
| 		stream.WriteString(string(t)) | 		stream.WriteString(string(t)) | ||||||
| 	}, nil) | 	}, nil) | ||||||
| 	defer ConfigDefault.cleanEncoders() | 	defer ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	val := []byte("abc") | 	val := []byte("abc") | ||||||
| 	str, err := MarshalToString(val) | 	str, err := MarshalToString(val) | ||||||
| 	should.Nil(err) | 	should.Nil(err) | ||||||
| @@ -73,7 +73,7 @@ func Test_customize_field_decoder(t *testing.T) { | |||||||
| 	RegisterFieldDecoderFunc("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) { | 	RegisterFieldDecoderFunc("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) { | ||||||
| 		*((*string)(ptr)) = strconv.Itoa(iter.ReadInt()) | 		*((*string)(ptr)) = strconv.Itoa(iter.ReadInt()) | ||||||
| 	}) | 	}) | ||||||
| 	defer ConfigDefault.cleanDecoders() | 	defer ConfigDefault.(*frozenConfig).cleanDecoders() | ||||||
| 	tom := Tom{} | 	tom := Tom{} | ||||||
| 	err := Unmarshal([]byte(`{"field1": 100}`), &tom) | 	err := Unmarshal([]byte(`{"field1": 100}`), &tom) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -144,7 +144,7 @@ func Test_marshaler_and_encoder(t *testing.T) { | |||||||
| 	type TestObject struct { | 	type TestObject struct { | ||||||
| 		Field *timeImplementedMarshaler | 		Field *timeImplementedMarshaler | ||||||
| 	} | 	} | ||||||
| 	ConfigDefault.cleanEncoders() | 	ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	RegisterTypeEncoderFunc("jsoniter.timeImplementedMarshaler", func(ptr unsafe.Pointer, stream *Stream) { | 	RegisterTypeEncoderFunc("jsoniter.timeImplementedMarshaler", func(ptr unsafe.Pointer, stream *Stream) { | ||||||
| 		stream.WriteString("hello from encoder") | 		stream.WriteString("hello from encoder") | ||||||
| @@ -184,7 +184,7 @@ func Test_unmarshaler_and_decoder(t *testing.T) { | |||||||
| 		Field  *ObjectImplementedUnmarshaler | 		Field  *ObjectImplementedUnmarshaler | ||||||
| 		Field2 string | 		Field2 string | ||||||
| 	} | 	} | ||||||
| 	ConfigDefault.cleanDecoders() | 	ConfigDefault.(*frozenConfig).cleanDecoders() | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	RegisterTypeDecoderFunc("jsoniter.ObjectImplementedUnmarshaler", func(ptr unsafe.Pointer, iter *Iterator) { | 	RegisterTypeDecoderFunc("jsoniter.ObjectImplementedUnmarshaler", func(ptr unsafe.Pointer, iter *Iterator) { | ||||||
| 		*(*ObjectImplementedUnmarshaler)(ptr) = 10 | 		*(*ObjectImplementedUnmarshaler)(ptr) = 10 | ||||||
|   | |||||||
| @@ -141,8 +141,8 @@ func Test_encode_object_contain_non_empty_interface(t *testing.T) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Test_nil_non_empty_interface(t *testing.T) { | func Test_nil_non_empty_interface(t *testing.T) { | ||||||
| 	ConfigDefault.cleanEncoders() | 	ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	ConfigDefault.cleanDecoders() | 	ConfigDefault.(*frozenConfig).cleanDecoders() | ||||||
| 	type TestObject struct { | 	type TestObject struct { | ||||||
| 		Field []MyInterface | 		Field []MyInterface | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -2,9 +2,9 @@ package jsoniter | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
| 	"io" | 	"io" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"github.com/stretchr/testify/require" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func Test_read_by_one(t *testing.T) { | func Test_read_by_one(t *testing.T) { | ||||||
|   | |||||||
| @@ -127,7 +127,7 @@ func Test_unicode(t *testing.T) { | |||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"}) | 	output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"}) | ||||||
| 	should.Equal(`{"a":"数字山谷"}`, output) | 	should.Equal(`{"a":"数字山谷"}`, output) | ||||||
| 	output, _ = Config{EscapeHtml: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"}) | 	output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"}) | ||||||
| 	should.Equal(`{"a":"数字山谷"}`, output) | 	should.Equal(`{"a":"数字山谷"}`, output) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -142,7 +142,7 @@ func Test_unicode_and_escape(t *testing.T) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Test_unsafe_unicode(t *testing.T) { | func Test_unsafe_unicode(t *testing.T) { | ||||||
| 	ConfigDefault.cleanEncoders() | 	ConfigDefault.(*frozenConfig).cleanEncoders() | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	output, err := ConfigDefault.MarshalToString("he\u2029\u2028he") | 	output, err := ConfigDefault.MarshalToString("he\u2029\u2028he") | ||||||
| 	should.Nil(err) | 	should.Nil(err) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user