1
0
mirror of https://github.com/json-iterator/go.git synced 2025-05-13 21:36:29 +02:00

document public symbols

This commit is contained in:
Tao Wen 2017-07-09 16:09:23 +08:00
parent 46574e7d09
commit f0487718f6
22 changed files with 227 additions and 176 deletions

View File

@ -160,8 +160,8 @@ type tolerateEmptyArrayDecoder struct {
func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
if iter.WhatIsNext() == jsoniter.Array {
iter.Skip()
newIter := iter.Config().BorrowIterator([]byte("{}"))
defer iter.Config().ReturnIterator(newIter)
newIter := iter.Pool().BorrowIterator([]byte("{}"))
defer iter.Pool().ReturnIterator(newIter)
decoder.valDecoder.Decode(ptr, newIter)
} else {
decoder.valDecoder.Decode(ptr, iter)
@ -202,8 +202,8 @@ func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
default:
iter.ReportError("fuzzyIntegerDecoder", "not number or string")
}
newIter := iter.Config().BorrowIterator([]byte(str))
defer iter.Config().ReturnIterator(newIter)
newIter := iter.Pool().BorrowIterator([]byte(str))
defer iter.Pool().ReturnIterator(newIter)
isFloat := strings.IndexByte(str, '.') != -1
decoder.fun(isFloat, ptr, newIter)
if newIter.Error != nil {
@ -222,8 +222,8 @@ func (decoder *fuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
*((*float32)(ptr)) = iter.ReadFloat32()
case jsoniter.String:
str = iter.ReadString()
newIter := iter.Config().BorrowIterator([]byte(str))
defer iter.Config().ReturnIterator(newIter)
newIter := iter.Pool().BorrowIterator([]byte(str))
defer iter.Pool().ReturnIterator(newIter)
*((*float32)(ptr)) = newIter.ReadFloat32()
if newIter.Error != nil {
iter.Error = newIter.Error
@ -244,8 +244,8 @@ func (decoder *fuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
*((*float64)(ptr)) = iter.ReadFloat64()
case jsoniter.String:
str = iter.ReadString()
newIter := iter.Config().BorrowIterator([]byte(str))
defer iter.Config().ReturnIterator(newIter)
newIter := iter.Pool().BorrowIterator([]byte(str))
defer iter.Pool().ReturnIterator(newIter)
*((*float64)(ptr)) = newIter.ReadFloat64()
if newIter.Error != nil {
iter.Error = newIter.Error

View File

@ -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
import (
@ -96,7 +85,7 @@ func (adapter *Decoder) Buffered() io.Reader {
func (decoder *Decoder) UseNumber() {
origCfg := decoder.iter.cfg.configBeforeFrozen
origCfg.UseNumber = true
decoder.iter.cfg = origCfg.Froze()
decoder.iter.cfg = origCfg.Froze().(*frozenConfig)
}
func NewEncoder(writer io.Writer) *Encoder {
@ -119,6 +108,6 @@ func (adapter *Encoder) SetIndent(prefix, indent string) {
func (adapter *Encoder) SetEscapeHTML(escapeHtml bool) {
config := adapter.stream.cfg.configBeforeFrozen
config.EscapeHtml = escapeHtml
adapter.stream.cfg = config.Froze()
config.EscapeHTML = escapeHtml
adapter.stream.cfg = config.Froze().(*frozenConfig)
}

View File

@ -9,10 +9,12 @@ import (
"unsafe"
)
// Config customize how the API should behave.
// The API is created from Config by Froze.
type Config struct {
IndentionStep int
MarshalFloatWith6Digits bool
EscapeHtml bool
EscapeHTML bool
SortMapKeys bool
UseNumber bool
}
@ -28,7 +30,11 @@ type frozenConfig struct {
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)
Marshal(v interface{}) ([]byte, error)
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
@ -39,22 +45,25 @@ type Api interface {
NewDecoder(reader io.Reader) *Decoder
}
// ConfigDefault the default API
var ConfigDefault = Config{
EscapeHtml: true,
EscapeHTML: true,
}.Froze()
// Trying to be 100% compatible with standard library behavior
// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
var ConfigCompatibleWithStandardLibrary = Config{
EscapeHtml: true,
EscapeHTML: true,
SortMapKeys: true,
}.Froze()
// ConfigFastest marshals float with only 6 digits precision
var ConfigFastest = Config{
EscapeHtml: false,
EscapeHTML: false,
MarshalFloatWith6Digits: true,
}.Froze()
func (cfg Config) Froze() *frozenConfig {
// Froze forge API from config
func (cfg Config) Froze() API {
// TODO: cache frozen config
frozenConfig := &frozenConfig{
sortMapKeys: cfg.SortMapKeys,
@ -67,8 +76,8 @@ func (cfg Config) Froze() *frozenConfig {
if cfg.MarshalFloatWith6Digits {
frozenConfig.marshalFloatWith6Digits()
}
if cfg.EscapeHtml {
frozenConfig.escapeHtml()
if cfg.EscapeHTML {
frozenConfig.escapeHTML()
}
if cfg.UseNumber {
frozenConfig.useNumber()
@ -145,7 +154,7 @@ func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
func (cfg *frozenConfig) escapeHtml() {
func (cfg *frozenConfig) escapeHTML() {
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
}
@ -189,18 +198,16 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
return cache[cacheKey]
}
// cleanDecoders cleans decoders registered or cached
func (cfg *frozenConfig) cleanDecoders() {
typeDecoders = 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() {
typeEncoders = map[string]ValEncoder{}
fieldEncoders = map[string]ValEncoder{}
*cfg = *cfg.configBeforeFrozen.Froze()
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
}
func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {

View File

@ -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
import (
@ -11,15 +5,23 @@ import (
"io"
)
// ValueType the type for JSON element
type ValueType int
const (
// Invalid invalid JSON element
Invalid ValueType = iota
// String JSON element "string"
String
// Number JSON element 100 or 0.10
Number
// Nil JSON element null
Nil
// Bool JSON element true or false
Bool
// Array JSON element []
Array
// Object JSON element {}
Object
)
@ -63,7 +65,8 @@ func init() {
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 {
cfg *frozenConfig
reader io.Reader
@ -75,10 +78,10 @@ type Iterator struct {
Error error
}
// Create creates an empty Iterator instance
func NewIterator(cfg *frozenConfig) *Iterator {
// NewIterator creates an empty Iterator instance
func NewIterator(cfg API) *Iterator {
return &Iterator{
cfg: cfg,
cfg: cfg.(*frozenConfig),
reader: nil,
buf: nil,
head: 0,
@ -86,10 +89,10 @@ func NewIterator(cfg *frozenConfig) *Iterator {
}
}
// Parse parses a json buffer in io.Reader into an Iterator instance
func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator {
// Parse creates an Iterator instance from io.Reader
func Parse(cfg API, reader io.Reader, bufSize int) *Iterator {
return &Iterator{
cfg: cfg,
cfg: cfg.(*frozenConfig),
reader: reader,
buf: make([]byte, bufSize),
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
func ParseBytes(cfg *frozenConfig, input []byte) *Iterator {
// ParseBytes creates an Iterator instance from byte array
func ParseBytes(cfg API, input []byte) *Iterator {
return &Iterator{
cfg: cfg,
cfg: cfg.(*frozenConfig),
reader: nil,
buf: input,
head: 0,
@ -108,16 +111,17 @@ func ParseBytes(cfg *frozenConfig, input []byte) *Iterator {
}
}
// ParseString parses a json string into an Iterator instance
func ParseString(cfg *frozenConfig, input string) *Iterator {
// ParseString creates an Iterator instance from string
func ParseString(cfg API, input string) *Iterator {
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
}
// 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 {
iter.reader = reader
iter.head = 0
@ -125,7 +129,7 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator {
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 {
iter.reader = nil
iter.buf = input
@ -134,7 +138,7 @@ func (iter *Iterator) ResetBytes(input []byte) *Iterator {
return iter
}
// WhatIsNext gets ValueType of relatively next json object
// WhatIsNext gets ValueType of relatively next json element
func (iter *Iterator) WhatIsNext() ValueType {
valueType := valueTypes[iter.nextToken()]
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) {
if iter.Error != nil {
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]))
}
// CurrentBuffer gets current buffer as string
// CurrentBuffer gets current buffer as string for debugging purpose
func (iter *Iterator) CurrentBuffer() string {
peekStart := iter.head - 10
if peekStart < 0 {
@ -261,6 +266,7 @@ func (iter *Iterator) unreadByte() {
return
}
// Read read the next JSON element as generic interface{}.
func (iter *Iterator) Read() interface{} {
valueType := iter.WhatIsNext()
switch valueType {

View File

@ -1,5 +1,6 @@
package jsoniter
// ReadArray read array element, tells if the array has more element to read.
func (iter *Iterator) ReadArray() (ret bool) {
c := iter.nextToken()
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) {
c := iter.nextToken()
if c == '[' {

View File

@ -30,6 +30,7 @@ func init() {
floatDigits['.'] = dotInNumber
}
// ReadBigFloat read big.Float
func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
str := iter.readNumberAsString()
if iter.Error != nil && iter.Error != io.EOF {
@ -47,6 +48,7 @@ func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
return val
}
// ReadBigInt read big.Int
func (iter *Iterator) ReadBigInt() (ret *big.Int) {
str := iter.readNumberAsString()
if iter.Error != nil && iter.Error != io.EOF {
@ -62,14 +64,14 @@ func (iter *Iterator) ReadBigInt() (ret *big.Int) {
return ret
}
//ReadFloat32 read float32
func (iter *Iterator) ReadFloat32() (ret float32) {
c := iter.nextToken()
if c == '-' {
return -iter.readPositiveFloat32()
} else {
iter.unreadByte()
return iter.readPositiveFloat32()
}
iter.unreadByte()
return iter.readPositiveFloat32()
}
func (iter *Iterator) readPositiveFloat32() (ret float32) {
@ -165,14 +167,14 @@ func (iter *Iterator) readFloat32SlowPath() (ret float32) {
return float32(val)
}
// ReadFloat64 read float64
func (iter *Iterator) ReadFloat64() (ret float64) {
c := iter.nextToken()
if c == '-' {
return -iter.readPositiveFloat64()
} else {
iter.unreadByte()
return iter.readPositiveFloat64()
}
iter.unreadByte()
return iter.readPositiveFloat64()
}
func (iter *Iterator) readPositiveFloat64() (ret float64) {

View File

@ -20,14 +20,17 @@ func init() {
}
}
// ReadUint read uint
func (iter *Iterator) ReadUint() uint {
return uint(iter.ReadUint64())
}
// ReadInt read int
func (iter *Iterator) ReadInt() int {
return int(iter.ReadInt64())
}
// ReadInt8 read int8
func (iter *Iterator) ReadInt8() (ret int8) {
c := iter.nextToken()
if c == '-' {
@ -37,16 +40,16 @@ func (iter *Iterator) ReadInt8() (ret int8) {
return
}
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) {
val := iter.readUint32(iter.nextToken())
if val > math.MaxUint8 {
@ -56,6 +59,7 @@ func (iter *Iterator) ReadUint8() (ret uint8) {
return uint8(val)
}
// ReadInt16 read int16
func (iter *Iterator) ReadInt16() (ret int16) {
c := iter.nextToken()
if c == '-' {
@ -65,16 +69,16 @@ func (iter *Iterator) ReadInt16() (ret int16) {
return
}
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) {
val := iter.readUint32(iter.nextToken())
if val > math.MaxUint16 {
@ -84,6 +88,7 @@ func (iter *Iterator) ReadUint16() (ret uint16) {
return uint16(val)
}
// ReadInt32 read int32
func (iter *Iterator) ReadInt32() (ret int32) {
c := iter.nextToken()
if c == '-' {
@ -93,16 +98,16 @@ func (iter *Iterator) ReadInt32() (ret int32) {
return
}
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) {
return iter.readUint32(iter.nextToken())
}
@ -182,10 +187,9 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
if value2 < value {
iter.ReportError("readUint32", "overflow")
return
} else {
value = value2
continue
}
value = value2
continue
}
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) {
c := iter.nextToken()
if c == '-' {
@ -204,16 +209,16 @@ func (iter *Iterator) ReadInt64() (ret int64) {
return
}
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 {
return iter.readUint64(iter.nextToken())
}
@ -240,10 +245,9 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
if value2 < value {
iter.ReportError("readUint64", "overflow")
return
} else {
value = value2
continue
}
value = value2
continue
}
value = (value << 3) + (value << 1) + uint64(ind)
}

View File

@ -6,6 +6,9 @@ import (
"unsafe"
)
// ReadObject read one field from object.
// If object ended, returns empty string.
// Otherwise, returns the field name.
func (iter *Iterator) ReadObject() (ret string) {
c := iter.nextToken()
switch c {
@ -74,6 +77,7 @@ func calcHash(str string) int32 {
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 {
c := iter.nextToken()
if c == '{' {
@ -106,6 +110,7 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
return false
}
// ReadMapCB read map with callback, the key can be any string
func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
c := iter.nextToken()
if c == '{' {

View File

@ -29,6 +29,8 @@ func (iter *Iterator) ReadBool() (ret bool) {
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 {
iter.startCapture(iter.head)
iter.Skip()
@ -58,10 +60,9 @@ func (iter *Iterator) stopCapture() []byte {
iter.captured = nil
if len(captured) == 0 {
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

View File

@ -4,6 +4,7 @@ import (
"unicode/utf16"
)
// ReadString read string from iterator
func (iter *Iterator) ReadString() (ret string) {
c := iter.nextToken()
if c == '"' {
@ -96,6 +97,8 @@ func (iter *Iterator) readStringSlowPath() (ret string) {
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) {
c := iter.nextToken()
if c == '"' {

View File

@ -4,6 +4,18 @@ import (
"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 {
select {
case stream := <-cfg.streamPool:

View File

@ -36,6 +36,7 @@ type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
// WriteToStream the default implementation for TypeEncoder method EncodeInterface
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
@ -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 jsonRawMessageType 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 {
if *((*unsafe.Pointer)(ptr)) == nil {
return true
} else {
return false
}
return false
}
type placeholderEncoder struct {
@ -206,7 +203,7 @@ type nonEmptyInterface struct {
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{}) {
typ := reflect.TypeOf(obj)
cacheKey := typ.Elem()
@ -219,6 +216,7 @@ func (iter *Iterator) ReadVal(obj interface{}) {
decoder.Decode(e.word, iter)
}
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
func (stream *Stream) WriteVal(val interface{}) {
if nil == val {
stream.WriteNil()
@ -393,9 +391,8 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
} else {
return &nonEmptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
case reflect.Array:
@ -517,9 +514,8 @@ func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) {
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
} else {
return &nonEmptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return &structEncoder{}, nil
case reflect.Array:
@ -617,9 +613,8 @@ func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder,
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
} else {
return &nonEmptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
case reflect.Array:
@ -679,7 +674,6 @@ func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
mapInterface := reflect.New(typ).Elem().Interface()
if cfg.sortMapKeys {
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
}

View File

@ -110,6 +110,11 @@ func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
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
func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) {
typeDecoders[typ] = &funcDecoder{fun}

View File

@ -1,9 +1,9 @@
package jsoniter
import (
"reflect"
"io"
"fmt"
"io"
"reflect"
"unsafe"
)
@ -71,7 +71,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
case 4:
var fieldName1 int32
var fieldName2 int32
@ -103,8 +103,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil
case 5:
var fieldName1 int32
var fieldName2 int32
@ -141,8 +141,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &fiveFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
case 6:
var fieldName1 int32
var fieldName2 int32
@ -184,8 +184,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &sixFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
case 7:
var fieldName1 int32
var fieldName2 int32
@ -232,9 +232,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &sevenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}, nil
case 8:
var fieldName1 int32
var fieldName2 int32
@ -286,9 +286,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &eightFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
case 9:
var fieldName1 int32
var fieldName2 int32
@ -345,9 +345,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &nineFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
case 10:
var fieldName1 int32
var fieldName2 int32
@ -409,15 +409,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &tenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}, nil
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}, nil
}
return &generalStructDecoder{typ, fields}, nil
}
type generalStructDecoder struct {
typ reflect.Type
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 {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error())
}
}
}

View File

@ -4,7 +4,7 @@ import (
"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.
type Stream struct {
cfg *frozenConfig
@ -19,9 +19,9 @@ type Stream struct {
// cfg can be jsoniter.ConfigDefault.
// out can be nil if write to internal buffer.
// 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{
cfg: cfg,
cfg: cfg.(*frozenConfig),
out: out,
buf: make([]byte, bufSize),
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
func (stream *Stream) Reset(out io.Writer) {
stream.out = out
@ -196,7 +201,6 @@ func (stream *Stream) growAtLeast(minimal int) {
stream.buf = newBuf
}
// WriteRaw write string out without quotes, just like []byte
func (stream *Stream) WriteRaw(s string) {
stream.ensure(len(s))

18
jsoniter.go Normal file
View 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

View File

@ -26,7 +26,7 @@ func Test_new_encoder(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)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})

View File

@ -7,25 +7,25 @@ import (
)
var stringConvertMap = map[string]string{
"null": "",
"321.1": "321.1",
`"1.1"`: "1.1",
`"-123.1"`: "-123.1",
"0.0": "0.0",
"0": "0",
`"0"`: "0",
`"0.0"`: "0.0",
`"00.0"`: "00.0",
"true": "true",
"false": "false",
`"true"`: "true",
`"false"`: "false",
`"true123"`: "true123",
`"+1"`: "+1",
"[]": "[]",
"[1,2]": "[1,2]",
"{}": "{}",
"{1,2}": "{1,2}",
"null": "",
"321.1": "321.1",
`"1.1"`: "1.1",
`"-123.1"`: "-123.1",
"0.0": "0.0",
"0": "0",
`"0"`: "0",
`"0.0"`: "0.0",
`"00.0"`: "00.0",
"true": "true",
"false": "false",
`"true"`: "true",
`"false"`: "false",
`"true123"`: "true123",
`"+1"`: "+1",
"[]": "[]",
"[1,2]": "[1,2]",
"{}": "{}",
"{1,2}": "{1,2}",
`{"a":1, "stream":true}`: `{"a":1, "stream":true}`,
}

View File

@ -18,7 +18,7 @@ func Test_customize_type_decoder(t *testing.T) {
}
*((*time.Time)(ptr)) = t
})
defer ConfigDefault.cleanDecoders()
defer ConfigDefault.(*frozenConfig).cleanDecoders()
val := time.Time{}
err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val)
if err != nil {
@ -36,7 +36,7 @@ func Test_customize_type_encoder(t *testing.T) {
t := *((*time.Time)(ptr))
stream.WriteString(t.UTC().Format("2006-01-02 15:04:05"))
}, nil)
defer ConfigDefault.cleanEncoders()
defer ConfigDefault.(*frozenConfig).cleanEncoders()
val := time.Unix(0, 0)
str, err := MarshalToString(val)
should.Nil(err)
@ -44,13 +44,13 @@ func Test_customize_type_encoder(t *testing.T) {
}
func Test_customize_byte_array_encoder(t *testing.T) {
ConfigDefault.cleanEncoders()
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
RegisterTypeEncoderFunc("[]uint8", func(ptr unsafe.Pointer, stream *Stream) {
t := *((*[]byte)(ptr))
stream.WriteString(string(t))
}, nil)
defer ConfigDefault.cleanEncoders()
defer ConfigDefault.(*frozenConfig).cleanEncoders()
val := []byte("abc")
str, err := MarshalToString(val)
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) {
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
})
defer ConfigDefault.cleanDecoders()
defer ConfigDefault.(*frozenConfig).cleanDecoders()
tom := Tom{}
err := Unmarshal([]byte(`{"field1": 100}`), &tom)
if err != nil {
@ -144,7 +144,7 @@ func Test_marshaler_and_encoder(t *testing.T) {
type TestObject struct {
Field *timeImplementedMarshaler
}
ConfigDefault.cleanEncoders()
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
RegisterTypeEncoderFunc("jsoniter.timeImplementedMarshaler", func(ptr unsafe.Pointer, stream *Stream) {
stream.WriteString("hello from encoder")
@ -184,7 +184,7 @@ func Test_unmarshaler_and_decoder(t *testing.T) {
Field *ObjectImplementedUnmarshaler
Field2 string
}
ConfigDefault.cleanDecoders()
ConfigDefault.(*frozenConfig).cleanDecoders()
should := require.New(t)
RegisterTypeDecoderFunc("jsoniter.ObjectImplementedUnmarshaler", func(ptr unsafe.Pointer, iter *Iterator) {
*(*ObjectImplementedUnmarshaler)(ptr) = 10

View File

@ -141,8 +141,8 @@ func Test_encode_object_contain_non_empty_interface(t *testing.T) {
}
func Test_nil_non_empty_interface(t *testing.T) {
ConfigDefault.cleanEncoders()
ConfigDefault.cleanDecoders()
ConfigDefault.(*frozenConfig).cleanEncoders()
ConfigDefault.(*frozenConfig).cleanDecoders()
type TestObject struct {
Field []MyInterface
}

View File

@ -2,9 +2,9 @@ package jsoniter
import (
"bytes"
"github.com/stretchr/testify/require"
"io"
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_by_one(t *testing.T) {

View File

@ -127,7 +127,7 @@ func Test_unicode(t *testing.T) {
should := require.New(t)
output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
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)
}
@ -142,7 +142,7 @@ func Test_unicode_and_escape(t *testing.T) {
}
func Test_unsafe_unicode(t *testing.T) {
ConfigDefault.cleanEncoders()
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
should.Nil(err)