config.go raw

   1  package jsoniter
   2  
   3  import (
   4  	"encoding/json"
   5  	"io"
   6  	"reflect"
   7  	"sync"
   8  	"unsafe"
   9  
  10  	"github.com/modern-go/concurrent"
  11  	"github.com/modern-go/reflect2"
  12  )
  13  
  14  // Config customize how the API should behave.
  15  // The API is created from Config by Froze.
  16  type Config struct {
  17  	IndentionStep                 int
  18  	MarshalFloatWith6Digits       bool
  19  	EscapeHTML                    bool
  20  	SortMapKeys                   bool
  21  	UseNumber                     bool
  22  	DisallowUnknownFields         bool
  23  	TagKey                        string
  24  	OnlyTaggedField               bool
  25  	ValidateJsonRawMessage        bool
  26  	ObjectFieldMustBeSimpleString bool
  27  	CaseSensitive                 bool
  28  }
  29  
  30  // API the public interface of this package.
  31  // Primary Marshal and Unmarshal.
  32  type API interface {
  33  	IteratorPool
  34  	StreamPool
  35  	MarshalToString(v interface{}) (string, error)
  36  	Marshal(v interface{}) ([]byte, error)
  37  	MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
  38  	UnmarshalFromString(str string, v interface{}) error
  39  	Unmarshal(data []byte, v interface{}) error
  40  	Get(data []byte, path ...interface{}) Any
  41  	NewEncoder(writer io.Writer) *Encoder
  42  	NewDecoder(reader io.Reader) *Decoder
  43  	Valid(data []byte) bool
  44  	RegisterExtension(extension Extension)
  45  	DecoderOf(typ reflect2.Type) ValDecoder
  46  	EncoderOf(typ reflect2.Type) ValEncoder
  47  }
  48  
  49  // ConfigDefault the default API
  50  var ConfigDefault = Config{
  51  	EscapeHTML: true,
  52  }.Froze()
  53  
  54  // ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
  55  var ConfigCompatibleWithStandardLibrary = Config{
  56  	EscapeHTML:             true,
  57  	SortMapKeys:            true,
  58  	ValidateJsonRawMessage: true,
  59  }.Froze()
  60  
  61  // ConfigFastest marshals float with only 6 digits precision
  62  var ConfigFastest = Config{
  63  	EscapeHTML:                    false,
  64  	MarshalFloatWith6Digits:       true, // will lose precession
  65  	ObjectFieldMustBeSimpleString: true, // do not unescape object field
  66  }.Froze()
  67  
  68  type frozenConfig struct {
  69  	configBeforeFrozen            Config
  70  	sortMapKeys                   bool
  71  	indentionStep                 int
  72  	objectFieldMustBeSimpleString bool
  73  	onlyTaggedField               bool
  74  	disallowUnknownFields         bool
  75  	decoderCache                  *concurrent.Map
  76  	encoderCache                  *concurrent.Map
  77  	encoderExtension              Extension
  78  	decoderExtension              Extension
  79  	extraExtensions               []Extension
  80  	streamPool                    *sync.Pool
  81  	iteratorPool                  *sync.Pool
  82  	caseSensitive                 bool
  83  }
  84  
  85  func (cfg *frozenConfig) initCache() {
  86  	cfg.decoderCache = concurrent.NewMap()
  87  	cfg.encoderCache = concurrent.NewMap()
  88  }
  89  
  90  func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
  91  	cfg.decoderCache.Store(cacheKey, decoder)
  92  }
  93  
  94  func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
  95  	cfg.encoderCache.Store(cacheKey, encoder)
  96  }
  97  
  98  func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
  99  	decoder, found := cfg.decoderCache.Load(cacheKey)
 100  	if found {
 101  		return decoder.(ValDecoder)
 102  	}
 103  	return nil
 104  }
 105  
 106  func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
 107  	encoder, found := cfg.encoderCache.Load(cacheKey)
 108  	if found {
 109  		return encoder.(ValEncoder)
 110  	}
 111  	return nil
 112  }
 113  
 114  var cfgCache = concurrent.NewMap()
 115  
 116  func getFrozenConfigFromCache(cfg Config) *frozenConfig {
 117  	obj, found := cfgCache.Load(cfg)
 118  	if found {
 119  		return obj.(*frozenConfig)
 120  	}
 121  	return nil
 122  }
 123  
 124  func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
 125  	cfgCache.Store(cfg, frozenConfig)
 126  }
 127  
 128  // Froze forge API from config
 129  func (cfg Config) Froze() API {
 130  	api := &frozenConfig{
 131  		sortMapKeys:                   cfg.SortMapKeys,
 132  		indentionStep:                 cfg.IndentionStep,
 133  		objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
 134  		onlyTaggedField:               cfg.OnlyTaggedField,
 135  		disallowUnknownFields:         cfg.DisallowUnknownFields,
 136  		caseSensitive:                 cfg.CaseSensitive,
 137  	}
 138  	api.streamPool = &sync.Pool{
 139  		New: func() interface{} {
 140  			return NewStream(api, nil, 512)
 141  		},
 142  	}
 143  	api.iteratorPool = &sync.Pool{
 144  		New: func() interface{} {
 145  			return NewIterator(api)
 146  		},
 147  	}
 148  	api.initCache()
 149  	encoderExtension := EncoderExtension{}
 150  	decoderExtension := DecoderExtension{}
 151  	if cfg.MarshalFloatWith6Digits {
 152  		api.marshalFloatWith6Digits(encoderExtension)
 153  	}
 154  	if cfg.EscapeHTML {
 155  		api.escapeHTML(encoderExtension)
 156  	}
 157  	if cfg.UseNumber {
 158  		api.useNumber(decoderExtension)
 159  	}
 160  	if cfg.ValidateJsonRawMessage {
 161  		api.validateJsonRawMessage(encoderExtension)
 162  	}
 163  	api.encoderExtension = encoderExtension
 164  	api.decoderExtension = decoderExtension
 165  	api.configBeforeFrozen = cfg
 166  	return api
 167  }
 168  
 169  func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig {
 170  	api := getFrozenConfigFromCache(cfg)
 171  	if api != nil {
 172  		return api
 173  	}
 174  	api = cfg.Froze().(*frozenConfig)
 175  	for _, extension := range extraExtensions {
 176  		api.RegisterExtension(extension)
 177  	}
 178  	addFrozenConfigToCache(cfg, api)
 179  	return api
 180  }
 181  
 182  func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
 183  	encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
 184  		rawMessage := *(*json.RawMessage)(ptr)
 185  		iter := cfg.BorrowIterator([]byte(rawMessage))
 186  		defer cfg.ReturnIterator(iter)
 187  		iter.Read()
 188  		if iter.Error != nil && iter.Error != io.EOF {
 189  			stream.WriteRaw("null")
 190  		} else {
 191  			stream.WriteRaw(string(rawMessage))
 192  		}
 193  	}, func(ptr unsafe.Pointer) bool {
 194  		return len(*((*json.RawMessage)(ptr))) == 0
 195  	}}
 196  	extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
 197  	extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
 198  }
 199  
 200  func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
 201  	extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
 202  		exitingValue := *((*interface{})(ptr))
 203  		if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr {
 204  			iter.ReadVal(exitingValue)
 205  			return
 206  		}
 207  		if iter.WhatIsNext() == NumberValue {
 208  			*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
 209  		} else {
 210  			*((*interface{})(ptr)) = iter.Read()
 211  		}
 212  	}}
 213  }
 214  func (cfg *frozenConfig) getTagKey() string {
 215  	tagKey := cfg.configBeforeFrozen.TagKey
 216  	if tagKey == "" {
 217  		return "json"
 218  	}
 219  	return tagKey
 220  }
 221  
 222  func (cfg *frozenConfig) RegisterExtension(extension Extension) {
 223  	cfg.extraExtensions = append(cfg.extraExtensions, extension)
 224  	copied := cfg.configBeforeFrozen
 225  	cfg.configBeforeFrozen = copied
 226  }
 227  
 228  type lossyFloat32Encoder struct {
 229  }
 230  
 231  func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 232  	stream.WriteFloat32Lossy(*((*float32)(ptr)))
 233  }
 234  
 235  func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
 236  	return *((*float32)(ptr)) == 0
 237  }
 238  
 239  type lossyFloat64Encoder struct {
 240  }
 241  
 242  func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 243  	stream.WriteFloat64Lossy(*((*float64)(ptr)))
 244  }
 245  
 246  func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
 247  	return *((*float64)(ptr)) == 0
 248  }
 249  
 250  // EnableLossyFloatMarshalling keeps 10**(-6) precision
 251  // for float variables for better performance.
 252  func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
 253  	// for better performance
 254  	extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
 255  	extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
 256  }
 257  
 258  type htmlEscapedStringEncoder struct {
 259  }
 260  
 261  func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 262  	str := *((*string)(ptr))
 263  	stream.WriteStringWithHTMLEscaped(str)
 264  }
 265  
 266  func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 267  	return *((*string)(ptr)) == ""
 268  }
 269  
 270  func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
 271  	encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
 272  }
 273  
 274  func (cfg *frozenConfig) cleanDecoders() {
 275  	typeDecoders = map[string]ValDecoder{}
 276  	fieldDecoders = map[string]ValDecoder{}
 277  	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
 278  }
 279  
 280  func (cfg *frozenConfig) cleanEncoders() {
 281  	typeEncoders = map[string]ValEncoder{}
 282  	fieldEncoders = map[string]ValEncoder{}
 283  	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
 284  }
 285  
 286  func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
 287  	stream := cfg.BorrowStream(nil)
 288  	defer cfg.ReturnStream(stream)
 289  	stream.WriteVal(v)
 290  	if stream.Error != nil {
 291  		return "", stream.Error
 292  	}
 293  	return string(stream.Buffer()), nil
 294  }
 295  
 296  func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
 297  	stream := cfg.BorrowStream(nil)
 298  	defer cfg.ReturnStream(stream)
 299  	stream.WriteVal(v)
 300  	if stream.Error != nil {
 301  		return nil, stream.Error
 302  	}
 303  	result := stream.Buffer()
 304  	copied := make([]byte, len(result))
 305  	copy(copied, result)
 306  	return copied, nil
 307  }
 308  
 309  func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
 310  	if prefix != "" {
 311  		panic("prefix is not supported")
 312  	}
 313  	for _, r := range indent {
 314  		if r != ' ' {
 315  			panic("indent can only be space")
 316  		}
 317  	}
 318  	newCfg := cfg.configBeforeFrozen
 319  	newCfg.IndentionStep = len(indent)
 320  	return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v)
 321  }
 322  
 323  func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
 324  	data := []byte(str)
 325  	iter := cfg.BorrowIterator(data)
 326  	defer cfg.ReturnIterator(iter)
 327  	iter.ReadVal(v)
 328  	c := iter.nextToken()
 329  	if c == 0 {
 330  		if iter.Error == io.EOF {
 331  			return nil
 332  		}
 333  		return iter.Error
 334  	}
 335  	iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
 336  	return iter.Error
 337  }
 338  
 339  func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
 340  	iter := cfg.BorrowIterator(data)
 341  	defer cfg.ReturnIterator(iter)
 342  	return locatePath(iter, path)
 343  }
 344  
 345  func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
 346  	iter := cfg.BorrowIterator(data)
 347  	defer cfg.ReturnIterator(iter)
 348  	iter.ReadVal(v)
 349  	c := iter.nextToken()
 350  	if c == 0 {
 351  		if iter.Error == io.EOF {
 352  			return nil
 353  		}
 354  		return iter.Error
 355  	}
 356  	iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
 357  	return iter.Error
 358  }
 359  
 360  func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder {
 361  	stream := NewStream(cfg, writer, 512)
 362  	return &Encoder{stream}
 363  }
 364  
 365  func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder {
 366  	iter := Parse(cfg, reader, 512)
 367  	return &Decoder{iter}
 368  }
 369  
 370  func (cfg *frozenConfig) Valid(data []byte) bool {
 371  	iter := cfg.BorrowIterator(data)
 372  	defer cfg.ReturnIterator(iter)
 373  	iter.Skip()
 374  	return iter.Error == nil
 375  }
 376