podman

Форк
0
375 строк · 10.3 Кб
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.