Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / json-iterator / go / config.go
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                 iter.Read()
187                 if iter.Error != nil {
188                         stream.WriteRaw("null")
189                 } else {
190                         cfg.ReturnIterator(iter)
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 }