podman

Форк
0
1463 строки · 36.5 Кб
1
// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
2
// Use of this source code is governed by a MIT license found in the LICENSE file.
3

4
package codec
5

6
// By default, this json support uses base64 encoding for bytes, because you cannot
7
// store and read any arbitrary string in json (only unicode).
8
// However, the user can configre how to encode/decode bytes.
9
//
10
// This library specifically supports UTF-8 for encoding and decoding only.
11
//
12
// Note that the library will happily encode/decode things which are not valid
13
// json e.g. a map[int64]string. We do it for consistency. With valid json,
14
// we will encode and decode appropriately.
15
// Users can specify their map type if necessary to force it.
16
//
17
// We cannot use strconv.(Q|Unq)uote because json quotes/unquotes differently.
18

19
import (
20
	"encoding/base64"
21
	"math"
22
	"reflect"
23
	"strconv"
24
	"time"
25
	"unicode"
26
	"unicode/utf16"
27
	"unicode/utf8"
28
)
29

30
//--------------------------------
31

32
// jsonLits and jsonLitb are defined at the package level,
33
// so they are guaranteed to be stored efficiently, making
34
// for better append/string comparison/etc.
35
//
36
// (anecdotal evidence from some benchmarking on go 1.20 devel in 20220104)
37
const jsonLits = `"true"false"null"`
38

39
var jsonLitb = []byte(jsonLits)
40

41
const (
42
	jsonLitT = 1
43
	jsonLitF = 6
44
	jsonLitN = 12
45
)
46

47
const jsonEncodeUintSmallsString = "" +
48
	"00010203040506070809" +
49
	"10111213141516171819" +
50
	"20212223242526272829" +
51
	"30313233343536373839" +
52
	"40414243444546474849" +
53
	"50515253545556575859" +
54
	"60616263646566676869" +
55
	"70717273747576777879" +
56
	"80818283848586878889" +
57
	"90919293949596979899"
58

59
var jsonEncodeUintSmallsStringBytes = []byte(jsonEncodeUintSmallsString)
60

61
const (
62
	jsonU4Chk2 = '0'
63
	jsonU4Chk1 = 'a' - 10
64
	jsonU4Chk0 = 'A' - 10
65
)
66

67
const (
68
	// If !jsonValidateSymbols, decoding will be faster, by skipping some checks:
69
	//   - If we see first character of null, false or true,
70
	//     do not validate subsequent characters.
71
	//   - e.g. if we see a n, assume null and skip next 3 characters,
72
	//     and do not validate they are ull.
73
	// P.S. Do not expect a significant decoding boost from this.
74
	jsonValidateSymbols = true
75

76
	// jsonEscapeMultiByteUnicodeSep controls whether some unicode characters
77
	// that are valid json but may bomb in some contexts are escaped during encoeing.
78
	//
79
	// U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR.
80
	// Both technically valid JSON, but bomb on JSONP, so fix here unconditionally.
81
	jsonEscapeMultiByteUnicodeSep = true
82

83
	// jsonRecognizeBoolNullInQuotedStr is used during decoding into a blank interface{}
84
	// to control whether we detect quoted values of bools and null where a map key is expected,
85
	// and treat as nil, true or false.
86
	jsonNakedBoolNullInQuotedStr = true
87

88
	// jsonManualInlineDecRdInHotZones controls whether we manually inline some decReader calls.
89
	//
90
	// encode performance is at par with libraries that just iterate over bytes directly,
91
	// because encWr (with inlined bytesEncAppender calls) is inlined.
92
	// Conversely, decode performance suffers because decRd (with inlined bytesDecReader calls)
93
	// isn't inlinable.
94
	//
95
	// To improve decode performamnce from json:
96
	// - readn1 is only called for \u
97
	// - consequently, to optimize json decoding, we specifically need inlining
98
	//   for bytes use-case of some other decReader methods:
99
	//   - jsonReadAsisChars, skipWhitespace (advance) and jsonReadNum
100
	//   - AND THEN readn3, readn4 (for ull, rue and alse).
101
	//   - (readn1 is only called when a char is escaped).
102
	// - without inlining, we still pay the cost of a method invocationK, and this dominates time
103
	// - To mitigate, we manually inline in hot zones
104
	//   *excluding places where used sparingly (e.g. nextValueBytes, and other atypical cases)*.
105
	//   - jsonReadAsisChars *only* called in: appendStringAsBytes
106
	//   - advance called: everywhere
107
	//   - jsonReadNum: decNumBytes, DecodeNaked
108
	// - From running go test (our anecdotal findings):
109
	//   - calling jsonReadAsisChars in appendStringAsBytes: 23431
110
	//   - calling jsonReadNum in decNumBytes: 15251
111
	//   - calling jsonReadNum in DecodeNaked: 612
112
	// Consequently, we manually inline jsonReadAsisChars (in appendStringAsBytes)
113
	// and jsonReadNum (in decNumbytes)
114
	jsonManualInlineDecRdInHotZones = true
115

116
	jsonSpacesOrTabsLen = 128
117

118
	// jsonAlwaysReturnInternString = false
119
)
120

121
var (
122
	// jsonTabs and jsonSpaces are used as caches for indents
123
	jsonTabs, jsonSpaces [jsonSpacesOrTabsLen]byte
124

125
	jsonCharHtmlSafeSet bitset256
126
	jsonCharSafeSet     bitset256
127
)
128

129
func init() {
130
	var i byte
131
	for i = 0; i < jsonSpacesOrTabsLen; i++ {
132
		jsonSpaces[i] = ' '
133
		jsonTabs[i] = '\t'
134
	}
135

136
	// populate the safe values as true: note: ASCII control characters are (0-31)
137
	// jsonCharSafeSet:     all true except (0-31) " \
138
	// jsonCharHtmlSafeSet: all true except (0-31) " \ < > &
139
	for i = 32; i < utf8.RuneSelf; i++ {
140
		switch i {
141
		case '"', '\\':
142
		case '<', '>', '&':
143
			jsonCharSafeSet.set(i) // = true
144
		default:
145
			jsonCharSafeSet.set(i)
146
			jsonCharHtmlSafeSet.set(i)
147
		}
148
	}
149
}
150

151
// ----------------
152

153
type jsonEncState struct {
154
	di int8   // indent per: if negative, use tabs
155
	d  bool   // indenting?
156
	dl uint16 // indent level
157
}
158

159
func (x jsonEncState) captureState() interface{}   { return x }
160
func (x *jsonEncState) restoreState(v interface{}) { *x = v.(jsonEncState) }
161

162
type jsonEncDriver struct {
163
	noBuiltInTypes
164
	h *JsonHandle
165

166
	// se interfaceExtWrapper
167

168
	// ---- cpu cache line boundary?
169
	jsonEncState
170

171
	ks bool // map key as string
172
	is byte // integer as string
173

174
	typical bool
175
	rawext  bool // rawext configured on the handle
176

177
	s *bitset256 // safe set for characters (taking h.HTMLAsIs into consideration)
178

179
	// buf *[]byte // used mostly for encoding []byte
180

181
	// scratch buffer for: encode time, numbers, etc
182
	//
183
	// RFC3339Nano uses 35 chars: 2006-01-02T15:04:05.999999999Z07:00
184
	// MaxUint64 uses 20 chars: 18446744073709551615
185
	// floats are encoded using: f/e fmt, and -1 precision, or 1 if no fractions.
186
	// This means we are limited by the number of characters for the
187
	// mantissa (up to 17), exponent (up to 3), signs (up to 3), dot (up to 1), E (up to 1)
188
	// for a total of 24 characters.
189
	//    -xxx.yyyyyyyyyyyye-zzz
190
	// Consequently, 35 characters should be sufficient for encoding time, integers or floats.
191
	// We use up all the remaining bytes to make this use full cache lines.
192
	b [48]byte
193

194
	e Encoder
195
}
196

197
func (e *jsonEncDriver) encoder() *Encoder { return &e.e }
198

199
func (e *jsonEncDriver) writeIndent() {
200
	e.e.encWr.writen1('\n')
201
	x := int(e.di) * int(e.dl)
202
	if e.di < 0 {
203
		x = -x
204
		for x > jsonSpacesOrTabsLen {
205
			e.e.encWr.writeb(jsonTabs[:])
206
			x -= jsonSpacesOrTabsLen
207
		}
208
		e.e.encWr.writeb(jsonTabs[:x])
209
	} else {
210
		for x > jsonSpacesOrTabsLen {
211
			e.e.encWr.writeb(jsonSpaces[:])
212
			x -= jsonSpacesOrTabsLen
213
		}
214
		e.e.encWr.writeb(jsonSpaces[:x])
215
	}
216
}
217

218
func (e *jsonEncDriver) WriteArrayElem() {
219
	if e.e.c != containerArrayStart {
220
		e.e.encWr.writen1(',')
221
	}
222
	if e.d {
223
		e.writeIndent()
224
	}
225
}
226

227
func (e *jsonEncDriver) WriteMapElemKey() {
228
	if e.e.c != containerMapStart {
229
		e.e.encWr.writen1(',')
230
	}
231
	if e.d {
232
		e.writeIndent()
233
	}
234
}
235

236
func (e *jsonEncDriver) WriteMapElemValue() {
237
	if e.d {
238
		e.e.encWr.writen2(':', ' ')
239
	} else {
240
		e.e.encWr.writen1(':')
241
	}
242
}
243

244
func (e *jsonEncDriver) EncodeNil() {
245
	// We always encode nil as just null (never in quotes)
246
	// so we can easily decode if a nil in the json stream ie if initial token is n.
247

248
	e.e.encWr.writestr(jsonLits[jsonLitN : jsonLitN+4])
249
}
250

251
func (e *jsonEncDriver) EncodeTime(t time.Time) {
252
	// Do NOT use MarshalJSON, as it allocates internally.
253
	// instead, we call AppendFormat directly, using our scratch buffer (e.b)
254

255
	if t.IsZero() {
256
		e.EncodeNil()
257
	} else {
258
		e.b[0] = '"'
259
		b := fmtTime(t, time.RFC3339Nano, e.b[1:1])
260
		e.b[len(b)+1] = '"'
261
		e.e.encWr.writeb(e.b[:len(b)+2])
262
	}
263
}
264

265
func (e *jsonEncDriver) EncodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
266
	if ext == SelfExt {
267
		e.e.encodeValue(baseRV(rv), e.h.fnNoExt(basetype))
268
	} else if v := ext.ConvertExt(rv); v == nil {
269
		e.EncodeNil()
270
	} else {
271
		e.e.encode(v)
272
	}
273
}
274

275
func (e *jsonEncDriver) EncodeRawExt(re *RawExt) {
276
	// only encodes re.Value (never re.Data)
277
	if re.Value == nil {
278
		e.EncodeNil()
279
	} else {
280
		e.e.encode(re.Value)
281
	}
282
}
283

284
var jsonEncBoolStrs = [2][2]string{
285
	{jsonLits[jsonLitF : jsonLitF+5], jsonLits[jsonLitT : jsonLitT+4]},
286
	{jsonLits[jsonLitF-1 : jsonLitF+6], jsonLits[jsonLitT-1 : jsonLitT+5]},
287
}
288

289
func (e *jsonEncDriver) EncodeBool(b bool) {
290
	e.e.encWr.writestr(
291
		jsonEncBoolStrs[bool2int(e.ks && e.e.c == containerMapKey)%2][bool2int(b)%2])
292
}
293

294
// func (e *jsonEncDriver) EncodeBool(b bool) {
295
// 	if e.ks && e.e.c == containerMapKey {
296
// 		if b {
297
// 			e.e.encWr.writestr(jsonLits[jsonLitT-1 : jsonLitT+5])
298
// 		} else {
299
// 			e.e.encWr.writestr(jsonLits[jsonLitF-1 : jsonLitF+6])
300
// 		}
301
// 	} else {
302
// 		if b {
303
// 			e.e.encWr.writestr(jsonLits[jsonLitT : jsonLitT+4])
304
// 		} else {
305
// 			e.e.encWr.writestr(jsonLits[jsonLitF : jsonLitF+5])
306
// 		}
307
// 	}
308
// }
309

310
func (e *jsonEncDriver) encodeFloat(f float64, bitsize, fmt byte, prec int8) {
311
	var blen uint
312
	if e.ks && e.e.c == containerMapKey {
313
		blen = 2 + uint(len(strconv.AppendFloat(e.b[1:1], f, fmt, int(prec), int(bitsize))))
314
		// _ = e.b[:blen]
315
		e.b[0] = '"'
316
		e.b[blen-1] = '"'
317
		e.e.encWr.writeb(e.b[:blen])
318
	} else {
319
		e.e.encWr.writeb(strconv.AppendFloat(e.b[:0], f, fmt, int(prec), int(bitsize)))
320
	}
321
}
322

323
func (e *jsonEncDriver) EncodeFloat64(f float64) {
324
	if math.IsNaN(f) || math.IsInf(f, 0) {
325
		e.EncodeNil()
326
		return
327
	}
328
	fmt, prec := jsonFloatStrconvFmtPrec64(f)
329
	e.encodeFloat(f, 64, fmt, prec)
330
}
331

332
func (e *jsonEncDriver) EncodeFloat32(f float32) {
333
	if math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) {
334
		e.EncodeNil()
335
		return
336
	}
337
	fmt, prec := jsonFloatStrconvFmtPrec32(f)
338
	e.encodeFloat(float64(f), 32, fmt, prec)
339
}
340

341
func (e *jsonEncDriver) encodeUint(neg bool, quotes bool, u uint64) {
342
	// copied mostly from std library: strconv
343
	// this should only be called on 64bit OS.
344

345
	// const smallsString = jsonEncodeUintSmallsString
346
	var ss = jsonEncodeUintSmallsStringBytes
347

348
	// typically, 19 or 20 bytes sufficient for decimal encoding a uint64
349
	// var a [24]byte
350
	var a = e.b[0:24]
351
	var i = uint(len(a))
352

353
	if quotes {
354
		i--
355
		setByteAt(a, i, '"')
356
		// a[i] = '"'
357
	}
358
	// u guaranteed to fit into a uint (as we are not 32bit OS)
359
	var is uint
360
	var us = uint(u)
361
	for us >= 100 {
362
		is = us % 100 * 2
363
		us /= 100
364
		i -= 2
365
		setByteAt(a, i+1, byteAt(ss, is+1))
366
		setByteAt(a, i, byteAt(ss, is))
367
		// a[i+1] = smallsString[is+1]
368
		// a[i+0] = smallsString[is+0]
369
	}
370

371
	// us < 100
372
	is = us * 2
373
	i--
374
	setByteAt(a, i, byteAt(ss, is+1))
375
	// a[i] = smallsString[is+1]
376
	if us >= 10 {
377
		i--
378
		setByteAt(a, i, byteAt(ss, is))
379
		// a[i] = smallsString[is]
380
	}
381
	if neg {
382
		i--
383
		setByteAt(a, i, '-')
384
		// a[i] = '-'
385
	}
386
	if quotes {
387
		i--
388
		setByteAt(a, i, '"')
389
		// a[i] = '"'
390
	}
391
	e.e.encWr.writeb(a[i:])
392
}
393

394
func (e *jsonEncDriver) EncodeInt(v int64) {
395
	quotes := e.is == 'A' || e.is == 'L' && (v > 1<<53 || v < -(1<<53)) ||
396
		(e.ks && e.e.c == containerMapKey)
397

398
	if cpu32Bit {
399
		if quotes {
400
			blen := 2 + len(strconv.AppendInt(e.b[1:1], v, 10))
401
			e.b[0] = '"'
402
			e.b[blen-1] = '"'
403
			e.e.encWr.writeb(e.b[:blen])
404
		} else {
405
			e.e.encWr.writeb(strconv.AppendInt(e.b[:0], v, 10))
406
		}
407
		return
408
	}
409

410
	if v < 0 {
411
		e.encodeUint(true, quotes, uint64(-v))
412
	} else {
413
		e.encodeUint(false, quotes, uint64(v))
414
	}
415
}
416

417
func (e *jsonEncDriver) EncodeUint(v uint64) {
418
	quotes := e.is == 'A' || e.is == 'L' && v > 1<<53 ||
419
		(e.ks && e.e.c == containerMapKey)
420

421
	if cpu32Bit {
422
		// use strconv directly, as optimized encodeUint only works on 64-bit alone
423
		if quotes {
424
			blen := 2 + len(strconv.AppendUint(e.b[1:1], v, 10))
425
			e.b[0] = '"'
426
			e.b[blen-1] = '"'
427
			e.e.encWr.writeb(e.b[:blen])
428
		} else {
429
			e.e.encWr.writeb(strconv.AppendUint(e.b[:0], v, 10))
430
		}
431
		return
432
	}
433

434
	e.encodeUint(false, quotes, v)
435
}
436

437
func (e *jsonEncDriver) EncodeString(v string) {
438
	if e.h.StringToRaw {
439
		e.EncodeStringBytesRaw(bytesView(v))
440
		return
441
	}
442
	e.quoteStr(v)
443
}
444

445
func (e *jsonEncDriver) EncodeStringBytesRaw(v []byte) {
446
	// if encoding raw bytes and RawBytesExt is configured, use it to encode
447
	if v == nil {
448
		e.EncodeNil()
449
		return
450
	}
451

452
	if e.rawext {
453
		iv := e.h.RawBytesExt.ConvertExt(v)
454
		if iv == nil {
455
			e.EncodeNil()
456
		} else {
457
			e.e.encode(iv)
458
		}
459
		return
460
	}
461

462
	slen := base64.StdEncoding.EncodedLen(len(v)) + 2
463

464
	// bs := e.e.blist.check(*e.buf, n)[:slen]
465
	// *e.buf = bs
466

467
	bs := e.e.blist.peek(slen, false)
468
	bs = bs[:slen]
469

470
	base64.StdEncoding.Encode(bs[1:], v)
471
	bs[len(bs)-1] = '"'
472
	bs[0] = '"'
473
	e.e.encWr.writeb(bs)
474
}
475

476
// indent is done as below:
477
//   - newline and indent are added before each mapKey or arrayElem
478
//   - newline and indent are added before each ending,
479
//     except there was no entry (so we can have {} or [])
480

481
func (e *jsonEncDriver) WriteArrayStart(length int) {
482
	if e.d {
483
		e.dl++
484
	}
485
	e.e.encWr.writen1('[')
486
}
487

488
func (e *jsonEncDriver) WriteArrayEnd() {
489
	if e.d {
490
		e.dl--
491
		e.writeIndent()
492
	}
493
	e.e.encWr.writen1(']')
494
}
495

496
func (e *jsonEncDriver) WriteMapStart(length int) {
497
	if e.d {
498
		e.dl++
499
	}
500
	e.e.encWr.writen1('{')
501
}
502

503
func (e *jsonEncDriver) WriteMapEnd() {
504
	if e.d {
505
		e.dl--
506
		if e.e.c != containerMapStart {
507
			e.writeIndent()
508
		}
509
	}
510
	e.e.encWr.writen1('}')
511
}
512

513
func (e *jsonEncDriver) quoteStr(s string) {
514
	// adapted from std pkg encoding/json
515
	const hex = "0123456789abcdef"
516
	w := e.e.w()
517
	w.writen1('"')
518
	var i, start uint
519
	for i < uint(len(s)) {
520
		// encode all bytes < 0x20 (except \r, \n).
521
		// also encode < > & to prevent security holes when served to some browsers.
522

523
		// We optimize for ascii, by assumining that most characters are in the BMP
524
		// and natively consumed by json without much computation.
525

526
		// if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
527
		// if (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) {
528
		if e.s.isset(s[i]) {
529
			i++
530
			continue
531
		}
532
		// b := s[i]
533
		if s[i] < utf8.RuneSelf {
534
			if start < i {
535
				w.writestr(s[start:i])
536
			}
537
			switch s[i] {
538
			case '\\', '"':
539
				w.writen2('\\', s[i])
540
			case '\n':
541
				w.writen2('\\', 'n')
542
			case '\r':
543
				w.writen2('\\', 'r')
544
			case '\b':
545
				w.writen2('\\', 'b')
546
			case '\f':
547
				w.writen2('\\', 'f')
548
			case '\t':
549
				w.writen2('\\', 't')
550
			default:
551
				w.writestr(`\u00`)
552
				w.writen2(hex[s[i]>>4], hex[s[i]&0xF])
553
			}
554
			i++
555
			start = i
556
			continue
557
		}
558
		c, size := utf8.DecodeRuneInString(s[i:])
559
		if c == utf8.RuneError && size == 1 { // meaning invalid encoding (so output as-is)
560
			if start < i {
561
				w.writestr(s[start:i])
562
			}
563
			w.writestr(`\uFFFD`)
564
			i++
565
			start = i
566
			continue
567
		}
568
		// U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR.
569
		// Both technically valid JSON, but bomb on JSONP, so fix here *unconditionally*.
570
		if jsonEscapeMultiByteUnicodeSep && (c == '\u2028' || c == '\u2029') {
571
			if start < i {
572
				w.writestr(s[start:i])
573
			}
574
			w.writestr(`\u202`)
575
			w.writen1(hex[c&0xF])
576
			i += uint(size)
577
			start = i
578
			continue
579
		}
580
		i += uint(size)
581
	}
582
	if start < uint(len(s)) {
583
		w.writestr(s[start:])
584
	}
585
	w.writen1('"')
586
}
587

588
func (e *jsonEncDriver) atEndOfEncode() {
589
	if e.h.TermWhitespace {
590
		var c byte = ' ' // default is that scalar is written, so output space
591
		if e.e.c != 0 {
592
			c = '\n' // for containers (map/list), output a newline
593
		}
594
		e.e.encWr.writen1(c)
595
	}
596
}
597

598
// ----------
599

600
type jsonDecState struct {
601
	rawext bool // rawext configured on the handle
602

603
	tok  uint8   // used to store the token read right after skipWhiteSpace
604
	_    bool    // found null
605
	_    byte    // padding
606
	bstr [4]byte // scratch used for string \UXXX parsing
607

608
	// scratch buffer used for base64 decoding (DecodeBytes in reuseBuf mode),
609
	// or reading doubleQuoted string (DecodeStringAsBytes, DecodeNaked)
610
	buf *[]byte
611
}
612

613
func (x jsonDecState) captureState() interface{}   { return x }
614
func (x *jsonDecState) restoreState(v interface{}) { *x = v.(jsonDecState) }
615

616
type jsonDecDriver struct {
617
	noBuiltInTypes
618
	decDriverNoopNumberHelper
619
	h *JsonHandle
620

621
	jsonDecState
622

623
	// se  interfaceExtWrapper
624

625
	// ---- cpu cache line boundary?
626

627
	d Decoder
628
}
629

630
func (d *jsonDecDriver) descBd() (s string) { panic("descBd unsupported") }
631

632
func (d *jsonDecDriver) decoder() *Decoder {
633
	return &d.d
634
}
635

636
func (d *jsonDecDriver) ReadMapStart() int {
637
	d.advance()
638
	if d.tok == 'n' {
639
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
640
		return containerLenNil
641
	}
642
	if d.tok != '{' {
643
		d.d.errorf("read map - expect char '%c' but got char '%c'", '{', d.tok)
644
	}
645
	d.tok = 0
646
	return containerLenUnknown
647
}
648

649
func (d *jsonDecDriver) ReadArrayStart() int {
650
	d.advance()
651
	if d.tok == 'n' {
652
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
653
		return containerLenNil
654
	}
655
	if d.tok != '[' {
656
		d.d.errorf("read array - expect char '%c' but got char '%c'", '[', d.tok)
657
	}
658
	d.tok = 0
659
	return containerLenUnknown
660
}
661

662
// MARKER:
663
// We attempted making sure CheckBreak can be inlined, by moving the skipWhitespace
664
// call to an explicit (noinline) function call.
665
// However, this forces CheckBreak to always incur a function call if there was whitespace,
666
// with no clear benefit.
667

668
func (d *jsonDecDriver) CheckBreak() bool {
669
	d.advance()
670
	return d.tok == '}' || d.tok == ']'
671
}
672

673
func (d *jsonDecDriver) ReadArrayElem() {
674
	const xc uint8 = ','
675
	if d.d.c != containerArrayStart {
676
		d.advance()
677
		if d.tok != xc {
678
			d.readDelimError(xc)
679
		}
680
		d.tok = 0
681
	}
682
}
683

684
func (d *jsonDecDriver) ReadArrayEnd() {
685
	const xc uint8 = ']'
686
	d.advance()
687
	if d.tok != xc {
688
		d.readDelimError(xc)
689
	}
690
	d.tok = 0
691
}
692

693
func (d *jsonDecDriver) ReadMapElemKey() {
694
	const xc uint8 = ','
695
	if d.d.c != containerMapStart {
696
		d.advance()
697
		if d.tok != xc {
698
			d.readDelimError(xc)
699
		}
700
		d.tok = 0
701
	}
702
}
703

704
func (d *jsonDecDriver) ReadMapElemValue() {
705
	const xc uint8 = ':'
706
	d.advance()
707
	if d.tok != xc {
708
		d.readDelimError(xc)
709
	}
710
	d.tok = 0
711
}
712

713
func (d *jsonDecDriver) ReadMapEnd() {
714
	const xc uint8 = '}'
715
	d.advance()
716
	if d.tok != xc {
717
		d.readDelimError(xc)
718
	}
719
	d.tok = 0
720
}
721

722
func (d *jsonDecDriver) readDelimError(xc uint8) {
723
	d.d.errorf("read json delimiter - expect char '%c' but got char '%c'", xc, d.tok)
724
}
725

726
// MARKER: checkLit takes the readn(3|4) result as a parameter so they can be inlined.
727
// We pass the array directly to errorf, as passing slice pushes past inlining threshold,
728
// and passing slice also might cause allocation of the bs array on the heap.
729

730
func (d *jsonDecDriver) checkLit3(got, expect [3]byte) {
731
	d.tok = 0
732
	if jsonValidateSymbols && got != expect {
733
		d.d.errorf("expecting %s: got %s", expect, got)
734
	}
735
}
736

737
func (d *jsonDecDriver) checkLit4(got, expect [4]byte) {
738
	d.tok = 0
739
	if jsonValidateSymbols && got != expect {
740
		d.d.errorf("expecting %s: got %s", expect, got)
741
	}
742
}
743

744
func (d *jsonDecDriver) skipWhitespace() {
745
	d.tok = d.d.decRd.skipWhitespace()
746
}
747

748
func (d *jsonDecDriver) advance() {
749
	if d.tok == 0 {
750
		d.skipWhitespace()
751
	}
752
}
753

754
func (d *jsonDecDriver) nextValueBytes(v []byte) []byte {
755
	v, cursor := d.nextValueBytesR(v)
756
	decNextValueBytesHelper{d: &d.d}.bytesRdV(&v, cursor)
757
	return v
758
}
759

760
func (d *jsonDecDriver) nextValueBytesR(v0 []byte) (v []byte, cursor uint) {
761
	v = v0
762
	var h = decNextValueBytesHelper{d: &d.d}
763
	dr := &d.d.decRd
764

765
	consumeString := func() {
766
	TOP:
767
		bs := dr.jsonReadAsisChars()
768
		h.appendN(&v, bs...)
769
		if bs[len(bs)-1] != '"' {
770
			// last char is '\', so consume next one and try again
771
			h.append1(&v, dr.readn1())
772
			goto TOP
773
		}
774
	}
775

776
	d.advance()           // ignore leading whitespace
777
	cursor = d.d.rb.c - 1 // cursor starts just before non-whitespace token
778

779
	switch d.tok {
780
	default:
781
		h.appendN(&v, dr.jsonReadNum()...)
782
	case 'n':
783
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
784
		h.appendS(&v, jsonLits[jsonLitN:jsonLitN+4])
785
	case 'f':
786
		d.checkLit4([4]byte{'a', 'l', 's', 'e'}, d.d.decRd.readn4())
787
		h.appendS(&v, jsonLits[jsonLitF:jsonLitF+5])
788
	case 't':
789
		d.checkLit3([3]byte{'r', 'u', 'e'}, d.d.decRd.readn3())
790
		h.appendS(&v, jsonLits[jsonLitT:jsonLitT+4])
791
	case '"':
792
		h.append1(&v, '"')
793
		consumeString()
794
	case '{', '[':
795
		var elem struct{}
796
		var stack []struct{}
797

798
		stack = append(stack, elem)
799

800
		h.append1(&v, d.tok)
801

802
		for len(stack) != 0 {
803
			c := dr.readn1()
804
			h.append1(&v, c)
805
			switch c {
806
			case '"':
807
				consumeString()
808
			case '{', '[':
809
				stack = append(stack, elem)
810
			case '}', ']':
811
				stack = stack[:len(stack)-1]
812
			}
813
		}
814
	}
815
	d.tok = 0
816
	return
817
}
818

819
func (d *jsonDecDriver) TryNil() bool {
820
	d.advance()
821
	// we shouldn't try to see if quoted "null" was here, right?
822
	// only the plain string: `null` denotes a nil (ie not quotes)
823
	if d.tok == 'n' {
824
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
825
		return true
826
	}
827
	return false
828
}
829

830
func (d *jsonDecDriver) DecodeBool() (v bool) {
831
	d.advance()
832
	// bool can be in quotes if and only if it's a map key
833
	fquot := d.d.c == containerMapKey && d.tok == '"'
834
	if fquot {
835
		d.tok = d.d.decRd.readn1()
836
	}
837
	switch d.tok {
838
	case 'f':
839
		d.checkLit4([4]byte{'a', 'l', 's', 'e'}, d.d.decRd.readn4())
840
		// v = false
841
	case 't':
842
		d.checkLit3([3]byte{'r', 'u', 'e'}, d.d.decRd.readn3())
843
		v = true
844
	case 'n':
845
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
846
		// v = false
847
	default:
848
		d.d.errorf("decode bool: got first char %c", d.tok)
849
		// v = false // "unreachable"
850
	}
851
	if fquot {
852
		d.d.decRd.readn1()
853
	}
854
	return
855
}
856

857
func (d *jsonDecDriver) DecodeTime() (t time.Time) {
858
	// read string, and pass the string into json.unmarshal
859
	d.advance()
860
	if d.tok == 'n' {
861
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
862
		return
863
	}
864
	d.ensureReadingString()
865
	bs := d.readUnescapedString()
866
	t, err := time.Parse(time.RFC3339, stringView(bs))
867
	d.d.onerror(err)
868
	return
869
}
870

871
func (d *jsonDecDriver) ContainerType() (vt valueType) {
872
	// check container type by checking the first char
873
	d.advance()
874

875
	// optimize this, so we don't do 4 checks but do one computation.
876
	// return jsonContainerSet[d.tok]
877

878
	// ContainerType is mostly called for Map and Array,
879
	// so this conditional is good enough (max 2 checks typically)
880
	if d.tok == '{' {
881
		return valueTypeMap
882
	} else if d.tok == '[' {
883
		return valueTypeArray
884
	} else if d.tok == 'n' {
885
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
886
		return valueTypeNil
887
	} else if d.tok == '"' {
888
		return valueTypeString
889
	}
890
	return valueTypeUnset
891
}
892

893
func (d *jsonDecDriver) decNumBytes() (bs []byte) {
894
	d.advance()
895
	dr := &d.d.decRd
896
	if d.tok == '"' {
897
		bs = dr.readUntil('"')
898
	} else if d.tok == 'n' {
899
		d.checkLit3([3]byte{'u', 'l', 'l'}, dr.readn3())
900
	} else {
901
		if jsonManualInlineDecRdInHotZones {
902
			if dr.bytes {
903
				bs = dr.rb.jsonReadNum()
904
			} else {
905
				bs = dr.ri.jsonReadNum()
906
			}
907
		} else {
908
			bs = dr.jsonReadNum()
909
		}
910
	}
911
	d.tok = 0
912
	return
913
}
914

915
func (d *jsonDecDriver) DecodeUint64() (u uint64) {
916
	b := d.decNumBytes()
917
	u, neg, ok := parseInteger_bytes(b)
918
	if neg {
919
		d.d.errorf("negative number cannot be decoded as uint64")
920
	}
921
	if !ok {
922
		d.d.onerror(strconvParseErr(b, "ParseUint"))
923
	}
924
	return
925
}
926

927
func (d *jsonDecDriver) DecodeInt64() (v int64) {
928
	b := d.decNumBytes()
929
	u, neg, ok := parseInteger_bytes(b)
930
	if !ok {
931
		d.d.onerror(strconvParseErr(b, "ParseInt"))
932
	}
933
	if chkOvf.Uint2Int(u, neg) {
934
		d.d.errorf("overflow decoding number from %s", b)
935
	}
936
	if neg {
937
		v = -int64(u)
938
	} else {
939
		v = int64(u)
940
	}
941
	return
942
}
943

944
func (d *jsonDecDriver) DecodeFloat64() (f float64) {
945
	var err error
946
	bs := d.decNumBytes()
947
	if len(bs) == 0 {
948
		return
949
	}
950
	f, err = parseFloat64(bs)
951
	d.d.onerror(err)
952
	return
953
}
954

955
func (d *jsonDecDriver) DecodeFloat32() (f float32) {
956
	var err error
957
	bs := d.decNumBytes()
958
	if len(bs) == 0 {
959
		return
960
	}
961
	f, err = parseFloat32(bs)
962
	d.d.onerror(err)
963
	return
964
}
965

966
func (d *jsonDecDriver) DecodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
967
	d.advance()
968
	if d.tok == 'n' {
969
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
970
		return
971
	}
972
	if ext == nil {
973
		re := rv.(*RawExt)
974
		re.Tag = xtag
975
		d.d.decode(&re.Value)
976
	} else if ext == SelfExt {
977
		d.d.decodeValue(baseRV(rv), d.h.fnNoExt(basetype))
978
	} else {
979
		d.d.interfaceExtConvertAndDecode(rv, ext)
980
	}
981
}
982

983
func (d *jsonDecDriver) decBytesFromArray(bs []byte) []byte {
984
	if bs != nil {
985
		bs = bs[:0]
986
	}
987
	d.tok = 0
988
	bs = append(bs, uint8(d.DecodeUint64()))
989
	d.tok = d.d.decRd.skipWhitespace() // skip(&whitespaceCharBitset)
990
	for d.tok != ']' {
991
		if d.tok != ',' {
992
			d.d.errorf("read array element - expect char '%c' but got char '%c'", ',', d.tok)
993
		}
994
		d.tok = 0
995
		bs = append(bs, uint8(chkOvf.UintV(d.DecodeUint64(), 8)))
996
		d.tok = d.d.decRd.skipWhitespace() // skip(&whitespaceCharBitset)
997
	}
998
	d.tok = 0
999
	return bs
1000
}
1001

1002
func (d *jsonDecDriver) DecodeBytes(bs []byte) (bsOut []byte) {
1003
	d.d.decByteState = decByteStateNone
1004
	d.advance()
1005
	if d.tok == 'n' {
1006
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
1007
		return nil
1008
	}
1009
	// if decoding into raw bytes, and the RawBytesExt is configured, use it to decode.
1010
	if d.rawext {
1011
		bsOut = bs
1012
		d.d.interfaceExtConvertAndDecode(&bsOut, d.h.RawBytesExt)
1013
		return
1014
	}
1015
	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
1016
	if d.tok == '[' {
1017
		// bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
1018
		if bs == nil {
1019
			d.d.decByteState = decByteStateReuseBuf
1020
			bs = d.d.b[:]
1021
		}
1022
		return d.decBytesFromArray(bs)
1023
	}
1024

1025
	// base64 encodes []byte{} as "", and we encode nil []byte as null.
1026
	// Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}.
1027

1028
	d.ensureReadingString()
1029
	bs1 := d.readUnescapedString()
1030
	slen := base64.StdEncoding.DecodedLen(len(bs1))
1031
	if slen == 0 {
1032
		bsOut = []byte{}
1033
	} else if slen <= cap(bs) {
1034
		bsOut = bs[:slen]
1035
	} else if bs == nil {
1036
		d.d.decByteState = decByteStateReuseBuf
1037
		bsOut = d.d.blist.check(*d.buf, slen)
1038
		bsOut = bsOut[:slen]
1039
		*d.buf = bsOut
1040
	} else {
1041
		bsOut = make([]byte, slen)
1042
	}
1043
	slen2, err := base64.StdEncoding.Decode(bsOut, bs1)
1044
	if err != nil {
1045
		d.d.errorf("error decoding base64 binary '%s': %v", bs1, err)
1046
	}
1047
	if slen != slen2 {
1048
		bsOut = bsOut[:slen2]
1049
	}
1050
	return
1051
}
1052

1053
func (d *jsonDecDriver) DecodeStringAsBytes() (s []byte) {
1054
	d.d.decByteState = decByteStateNone
1055
	d.advance()
1056

1057
	// common case - hoist outside the switch statement
1058
	if d.tok == '"' {
1059
		return d.dblQuoteStringAsBytes()
1060
	}
1061

1062
	// handle non-string scalar: null, true, false or a number
1063
	switch d.tok {
1064
	case 'n':
1065
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
1066
		return nil // []byte{}
1067
	case 'f':
1068
		d.checkLit4([4]byte{'a', 'l', 's', 'e'}, d.d.decRd.readn4())
1069
		return jsonLitb[jsonLitF : jsonLitF+5]
1070
	case 't':
1071
		d.checkLit3([3]byte{'r', 'u', 'e'}, d.d.decRd.readn3())
1072
		return jsonLitb[jsonLitT : jsonLitT+4]
1073
	default:
1074
		// try to parse a valid number
1075
		d.tok = 0
1076
		return d.d.decRd.jsonReadNum()
1077
	}
1078
}
1079

1080
func (d *jsonDecDriver) ensureReadingString() {
1081
	if d.tok != '"' {
1082
		d.d.errorf("expecting string starting with '\"'; got '%c'", d.tok)
1083
	}
1084
}
1085

1086
func (d *jsonDecDriver) readUnescapedString() (bs []byte) {
1087
	// d.ensureReadingString()
1088
	bs = d.d.decRd.readUntil('"')
1089
	d.tok = 0
1090
	return
1091
}
1092

1093
func (d *jsonDecDriver) dblQuoteStringAsBytes() (buf []byte) {
1094
	checkUtf8 := d.h.ValidateUnicode
1095
	d.d.decByteState = decByteStateNone
1096
	// use a local buf variable, so we don't do pointer chasing within loop
1097
	buf = (*d.buf)[:0]
1098
	dr := &d.d.decRd
1099
	d.tok = 0
1100

1101
	var bs []byte
1102
	var c byte
1103
	var firstTime bool = true
1104

1105
	for {
1106
		if firstTime {
1107
			firstTime = false
1108
			if dr.bytes {
1109
				bs = dr.rb.jsonReadAsisChars()
1110
				if bs[len(bs)-1] == '"' {
1111
					d.d.decByteState = decByteStateZerocopy
1112
					return bs[:len(bs)-1]
1113
				}
1114
				goto APPEND
1115
			}
1116
		}
1117

1118
		if jsonManualInlineDecRdInHotZones {
1119
			if dr.bytes {
1120
				bs = dr.rb.jsonReadAsisChars()
1121
			} else {
1122
				bs = dr.ri.jsonReadAsisChars()
1123
			}
1124
		} else {
1125
			bs = dr.jsonReadAsisChars()
1126
		}
1127

1128
	APPEND:
1129
		_ = bs[0] // bounds check hint - slice must be > 0 elements
1130
		buf = append(buf, bs[:len(bs)-1]...)
1131
		c = bs[len(bs)-1]
1132

1133
		if c == '"' {
1134
			break
1135
		}
1136

1137
		// c is now '\'
1138
		c = dr.readn1()
1139

1140
		switch c {
1141
		case '"', '\\', '/', '\'':
1142
			buf = append(buf, c)
1143
		case 'b':
1144
			buf = append(buf, '\b')
1145
		case 'f':
1146
			buf = append(buf, '\f')
1147
		case 'n':
1148
			buf = append(buf, '\n')
1149
		case 'r':
1150
			buf = append(buf, '\r')
1151
		case 't':
1152
			buf = append(buf, '\t')
1153
		case 'u':
1154
			rr := d.appendStringAsBytesSlashU()
1155
			if checkUtf8 && rr == unicode.ReplacementChar {
1156
				d.d.errorf("invalid UTF-8 character found after: %s", buf)
1157
			}
1158
			buf = append(buf, d.bstr[:utf8.EncodeRune(d.bstr[:], rr)]...)
1159
		default:
1160
			*d.buf = buf
1161
			d.d.errorf("unsupported escaped value: %c", c)
1162
		}
1163
	}
1164
	*d.buf = buf
1165
	d.d.decByteState = decByteStateReuseBuf
1166
	return
1167
}
1168

1169
func (d *jsonDecDriver) appendStringAsBytesSlashU() (r rune) {
1170
	var rr uint32
1171
	var csu [2]byte
1172
	var cs [4]byte = d.d.decRd.readn4()
1173
	if rr = jsonSlashURune(cs); rr == unicode.ReplacementChar {
1174
		return unicode.ReplacementChar
1175
	}
1176
	r = rune(rr)
1177
	if utf16.IsSurrogate(r) {
1178
		csu = d.d.decRd.readn2()
1179
		cs = d.d.decRd.readn4()
1180
		if csu[0] == '\\' && csu[1] == 'u' {
1181
			if rr = jsonSlashURune(cs); rr == unicode.ReplacementChar {
1182
				return unicode.ReplacementChar
1183
			}
1184
			return utf16.DecodeRune(r, rune(rr))
1185
		}
1186
		return unicode.ReplacementChar
1187
	}
1188
	return
1189
}
1190

1191
func jsonSlashURune(cs [4]byte) (rr uint32) {
1192
	for _, c := range cs {
1193
		// best to use explicit if-else
1194
		// - not a table, etc which involve memory loads, array lookup with bounds checks, etc
1195
		if c >= '0' && c <= '9' {
1196
			rr = rr*16 + uint32(c-jsonU4Chk2)
1197
		} else if c >= 'a' && c <= 'f' {
1198
			rr = rr*16 + uint32(c-jsonU4Chk1)
1199
		} else if c >= 'A' && c <= 'F' {
1200
			rr = rr*16 + uint32(c-jsonU4Chk0)
1201
		} else {
1202
			return unicode.ReplacementChar
1203
		}
1204
	}
1205
	return
1206
}
1207

1208
func (d *jsonDecDriver) nakedNum(z *fauxUnion, bs []byte) (err error) {
1209
	// Note: nakedNum is NEVER called with a zero-length []byte
1210
	if d.h.PreferFloat {
1211
		z.v = valueTypeFloat
1212
		z.f, err = parseFloat64(bs)
1213
	} else {
1214
		err = parseNumber(bs, z, d.h.SignedInteger)
1215
	}
1216
	return
1217
}
1218

1219
func (d *jsonDecDriver) DecodeNaked() {
1220
	z := d.d.naked()
1221

1222
	d.advance()
1223
	var bs []byte
1224
	switch d.tok {
1225
	case 'n':
1226
		d.checkLit3([3]byte{'u', 'l', 'l'}, d.d.decRd.readn3())
1227
		z.v = valueTypeNil
1228
	case 'f':
1229
		d.checkLit4([4]byte{'a', 'l', 's', 'e'}, d.d.decRd.readn4())
1230
		z.v = valueTypeBool
1231
		z.b = false
1232
	case 't':
1233
		d.checkLit3([3]byte{'r', 'u', 'e'}, d.d.decRd.readn3())
1234
		z.v = valueTypeBool
1235
		z.b = true
1236
	case '{':
1237
		z.v = valueTypeMap // don't consume. kInterfaceNaked will call ReadMapStart
1238
	case '[':
1239
		z.v = valueTypeArray // don't consume. kInterfaceNaked will call ReadArrayStart
1240
	case '"':
1241
		// if a string, and MapKeyAsString, then try to decode it as a bool or number first
1242
		bs = d.dblQuoteStringAsBytes()
1243
		if jsonNakedBoolNullInQuotedStr &&
1244
			d.h.MapKeyAsString && len(bs) > 0 && d.d.c == containerMapKey {
1245
			switch string(bs) {
1246
			// case "null": // nil is never quoted
1247
			// 	z.v = valueTypeNil
1248
			case "true":
1249
				z.v = valueTypeBool
1250
				z.b = true
1251
			case "false":
1252
				z.v = valueTypeBool
1253
				z.b = false
1254
			default:
1255
				// check if a number: float, int or uint
1256
				if err := d.nakedNum(z, bs); err != nil {
1257
					z.v = valueTypeString
1258
					z.s = d.d.stringZC(bs)
1259
				}
1260
			}
1261
		} else {
1262
			z.v = valueTypeString
1263
			z.s = d.d.stringZC(bs)
1264
		}
1265
	default: // number
1266
		bs = d.d.decRd.jsonReadNum()
1267
		d.tok = 0
1268
		if len(bs) == 0 {
1269
			d.d.errorf("decode number from empty string")
1270
		}
1271
		if err := d.nakedNum(z, bs); err != nil {
1272
			d.d.errorf("decode number from %s: %v", bs, err)
1273
		}
1274
	}
1275
}
1276

1277
//----------------------
1278

1279
// JsonHandle is a handle for JSON encoding format.
1280
//
1281
// Json is comprehensively supported:
1282
//   - decodes numbers into interface{} as int, uint or float64
1283
//     based on how the number looks and some config parameters e.g. PreferFloat, SignedInt, etc.
1284
//   - decode integers from float formatted numbers e.g. 1.27e+8
1285
//   - decode any json value (numbers, bool, etc) from quoted strings
1286
//   - configurable way to encode/decode []byte .
1287
//     by default, encodes and decodes []byte using base64 Std Encoding
1288
//   - UTF-8 support for encoding and decoding
1289
//
1290
// It has better performance than the json library in the standard library,
1291
// by leveraging the performance improvements of the codec library.
1292
//
1293
// In addition, it doesn't read more bytes than necessary during a decode, which allows
1294
// reading multiple values from a stream containing json and non-json content.
1295
// For example, a user can read a json value, then a cbor value, then a msgpack value,
1296
// all from the same stream in sequence.
1297
//
1298
// Note that, when decoding quoted strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are
1299
// not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD.
1300
//
1301
// Note also that the float values for NaN, +Inf or -Inf are encoded as null,
1302
// as suggested by NOTE 4 of the ECMA-262 ECMAScript Language Specification 5.1 edition.
1303
// see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf .
1304
//
1305
// Note the following behaviour differences vs std-library encoding/json package:
1306
//   - struct field names matched in case-sensitive manner
1307
type JsonHandle struct {
1308
	textEncodingType
1309
	BasicHandle
1310

1311
	// Indent indicates how a value is encoded.
1312
	//   - If positive, indent by that number of spaces.
1313
	//   - If negative, indent by that number of tabs.
1314
	Indent int8
1315

1316
	// IntegerAsString controls how integers (signed and unsigned) are encoded.
1317
	//
1318
	// Per the JSON Spec, JSON numbers are 64-bit floating point numbers.
1319
	// Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision.
1320
	// This can be mitigated by configuring how to encode integers.
1321
	//
1322
	// IntegerAsString interpretes the following values:
1323
	//   - if 'L', then encode integers > 2^53 as a json string.
1324
	//   - if 'A', then encode all integers as a json string
1325
	//             containing the exact integer representation as a decimal.
1326
	//   - else    encode all integers as a json number (default)
1327
	IntegerAsString byte
1328

1329
	// HTMLCharsAsIs controls how to encode some special characters to html: < > &
1330
	//
1331
	// By default, we encode them as \uXXX
1332
	// to prevent security holes when served from some browsers.
1333
	HTMLCharsAsIs bool
1334

1335
	// PreferFloat says that we will default to decoding a number as a float.
1336
	// If not set, we will examine the characters of the number and decode as an
1337
	// integer type if it doesn't have any of the characters [.eE].
1338
	PreferFloat bool
1339

1340
	// TermWhitespace says that we add a whitespace character
1341
	// at the end of an encoding.
1342
	//
1343
	// The whitespace is important, especially if using numbers in a context
1344
	// where multiple items are written to a stream.
1345
	TermWhitespace bool
1346

1347
	// MapKeyAsString says to encode all map keys as strings.
1348
	//
1349
	// Use this to enforce strict json output.
1350
	// The only caveat is that nil value is ALWAYS written as null (never as "null")
1351
	MapKeyAsString bool
1352

1353
	// _ uint64 // padding (cache line)
1354

1355
	// Note: below, we store hardly-used items e.g. RawBytesExt.
1356
	// These values below may straddle a cache line, but they are hardly-used,
1357
	// so shouldn't contribute to false-sharing except in rare cases.
1358

1359
	// RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way.
1360
	// If not configured, raw bytes are encoded to/from base64 text.
1361
	RawBytesExt InterfaceExt
1362
}
1363

1364
func (h *JsonHandle) isJson() bool { return true }
1365

1366
// Name returns the name of the handle: json
1367
func (h *JsonHandle) Name() string { return "json" }
1368

1369
func (h *JsonHandle) desc(bd byte) string { return string(bd) }
1370

1371
func (h *JsonHandle) typical() bool {
1372
	return h.Indent == 0 && !h.MapKeyAsString && h.IntegerAsString != 'A' && h.IntegerAsString != 'L'
1373
}
1374

1375
func (h *JsonHandle) newEncDriver() encDriver {
1376
	var e = &jsonEncDriver{h: h}
1377
	// var x []byte
1378
	// e.buf = &x
1379
	e.e.e = e
1380
	e.e.js = true
1381
	e.e.init(h)
1382
	e.reset()
1383
	return e
1384
}
1385

1386
func (h *JsonHandle) newDecDriver() decDriver {
1387
	var d = &jsonDecDriver{h: h}
1388
	var x []byte
1389
	d.buf = &x
1390
	d.d.d = d
1391
	d.d.js = true
1392
	d.d.jsms = h.MapKeyAsString
1393
	d.d.init(h)
1394
	d.reset()
1395
	return d
1396
}
1397

1398
func (e *jsonEncDriver) resetState() {
1399
	e.dl = 0
1400
}
1401

1402
func (e *jsonEncDriver) reset() {
1403
	e.resetState()
1404
	// (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b)
1405
	// cache values from the handle
1406
	e.typical = e.h.typical()
1407
	if e.h.HTMLCharsAsIs {
1408
		e.s = &jsonCharSafeSet
1409
	} else {
1410
		e.s = &jsonCharHtmlSafeSet
1411
	}
1412
	e.rawext = e.h.RawBytesExt != nil
1413
	e.di = int8(e.h.Indent)
1414
	e.d = e.h.Indent != 0
1415
	e.ks = e.h.MapKeyAsString
1416
	e.is = e.h.IntegerAsString
1417
}
1418

1419
func (d *jsonDecDriver) resetState() {
1420
	*d.buf = d.d.blist.check(*d.buf, 256)
1421
	d.tok = 0
1422
}
1423

1424
func (d *jsonDecDriver) reset() {
1425
	d.resetState()
1426
	d.rawext = d.h.RawBytesExt != nil
1427
}
1428

1429
func jsonFloatStrconvFmtPrec64(f float64) (fmt byte, prec int8) {
1430
	fmt = 'f'
1431
	prec = -1
1432
	fbits := math.Float64bits(f)
1433
	abs := math.Float64frombits(fbits &^ (1 << 63))
1434
	if abs == 0 || abs == 1 {
1435
		prec = 1
1436
	} else if abs < 1e-6 || abs >= 1e21 {
1437
		fmt = 'e'
1438
	} else if noFrac64(fbits) {
1439
		prec = 1
1440
	}
1441
	return
1442
}
1443

1444
func jsonFloatStrconvFmtPrec32(f float32) (fmt byte, prec int8) {
1445
	fmt = 'f'
1446
	prec = -1
1447
	// directly handle Modf (to get fractions) and Abs (to get absolute)
1448
	fbits := math.Float32bits(f)
1449
	abs := math.Float32frombits(fbits &^ (1 << 31))
1450
	if abs == 0 || abs == 1 {
1451
		prec = 1
1452
	} else if abs < 1e-6 || abs >= 1e21 {
1453
		fmt = 'e'
1454
	} else if noFrac32(fbits) {
1455
		prec = 1
1456
	}
1457
	return
1458
}
1459

1460
var _ decDriverContainerTracker = (*jsonDecDriver)(nil)
1461
var _ encDriverContainerTracker = (*jsonEncDriver)(nil)
1462
var _ decDriver = (*jsonDecDriver)(nil)
1463
var _ encDriver = (*jsonEncDriver)(nil)
1464

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

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

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

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