1
2
3
4
5
6
7 package jsontext
8
9 import (
10 "bytes"
11 "errors"
12 "math"
13 "strconv"
14
15 "encoding/json/internal/jsonflags"
16 "encoding/json/internal/jsonwire"
17 )
18
19
20
21 const (
22 maxInt64 = math.MaxInt64
23 minInt64 = math.MinInt64
24 maxUint64 = math.MaxUint64
25 minUint64 = 0
26
27 invalidTokenPanic = "invalid jsontext.Token; it has been voided by a subsequent json.Decoder call"
28 )
29
30 var errInvalidToken = errors.New("invalid jsontext.Token")
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 type Token struct {
57 nonComparable
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 raw *decodeBuffer
96
97
98
99
100 str string
101
102
103
104
105 num uint64
106 }
107
108
109
110 var (
111 Null Token = rawToken("null")
112 False Token = rawToken("false")
113 True Token = rawToken("true")
114
115 BeginObject Token = rawToken("{")
116 EndObject Token = rawToken("}")
117 BeginArray Token = rawToken("[")
118 EndArray Token = rawToken("]")
119
120 zeroString Token = rawToken(`""`)
121 zeroNumber Token = rawToken(`0`)
122
123 nanString Token = String("NaN")
124 pinfString Token = String("Infinity")
125 ninfString Token = String("-Infinity")
126 )
127
128 func rawToken(s string) Token {
129 return Token{raw: &decodeBuffer{buf: []byte(s), prevStart: 0, prevEnd: len(s)}}
130 }
131
132
133 func Bool(b bool) Token {
134 if b {
135 return True
136 }
137 return False
138 }
139
140
141
142
143 func String(s string) Token {
144 if len(s) == 0 {
145 return zeroString
146 }
147 return Token{str: s}
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162 func Float32(n float32) Token {
163 if n != 0 && !math.IsNaN(float64(n)) && !math.IsInf(float64(n), 0) {
164 return Token{str: "F", num: uint64(math.Float32bits(n))}
165 }
166 return Float(float64(n))
167 }
168
169
170
171
172
173
174
175 func Float(n float64) Token {
176 switch {
177 case math.Float64bits(n) == 0:
178 return zeroNumber
179 case math.IsNaN(n):
180 return nanString
181 case math.IsInf(n, +1):
182 return pinfString
183 case math.IsInf(n, -1):
184 return ninfString
185 }
186 return Token{str: "f", num: math.Float64bits(n)}
187 }
188
189
190 func Int(n int64) Token {
191 if n == 0 {
192 return zeroNumber
193 }
194 return Token{str: "i", num: uint64(n)}
195 }
196
197
198 func Uint(n uint64) Token {
199 if n == 0 {
200 return zeroNumber
201 }
202 return Token{str: "u", num: uint64(n)}
203 }
204
205
206
207
208
209 func (t Token) Clone() Token {
210
211 if raw := t.raw; raw != nil {
212
213 if t.raw.prevStart == 0 {
214 switch t.raw {
215 case Null.raw:
216 return Null
217 case False.raw:
218 return False
219 case True.raw:
220 return True
221 case BeginObject.raw:
222 return BeginObject
223 case EndObject.raw:
224 return EndObject
225 case BeginArray.raw:
226 return BeginArray
227 case EndArray.raw:
228 return EndArray
229 }
230 }
231
232
233 if uint64(raw.previousOffsetStart()) != t.num {
234 panic(invalidTokenPanic)
235 }
236 buf := bytes.Clone(raw.previousBuffer())
237 return Token{raw: &decodeBuffer{buf: buf, prevStart: 0, prevEnd: len(buf)}}
238 }
239 return t
240 }
241
242
243
244 func (t Token) Bool() bool {
245 switch t.raw {
246 case True.raw:
247 return true
248 case False.raw:
249 return false
250 default:
251 panic("invalid JSON token kind: " + t.Kind().String())
252 }
253 }
254
255
256
257 func (t Token) appendString(dst []byte, flags *jsonflags.Flags) ([]byte, error) {
258 if raw := t.raw; raw != nil {
259
260 buf := raw.previousBuffer()
261 if Kind(buf[0]) == '"' {
262 if jsonwire.ConsumeSimpleString(buf) == len(buf) {
263 return append(dst, buf...), nil
264 }
265 dst, _, err := jsonwire.ReformatString(dst, buf, flags)
266 return dst, err
267 }
268 } else if len(t.str) != 0 && t.num == 0 {
269
270 return jsonwire.AppendQuote(dst, []byte(t.str), flags)
271 }
272
273 panic("invalid JSON token kind: " + t.Kind().String())
274 }
275
276
277
278 func (t Token) String() string {
279
280
281
282
283 s, b := t.string()
284 if len(b) > 0 {
285 return string(b)
286 }
287 return s
288 }
289 func (t Token) string() (string, []byte) {
290 if raw := t.raw; raw != nil {
291 if uint64(raw.previousOffsetStart()) != t.num {
292 panic(invalidTokenPanic)
293 }
294 buf := raw.previousBuffer()
295 if buf[0] == '"' {
296
297 isVerbatim := jsonwire.ConsumeSimpleString(buf) == len(buf)
298 return "", jsonwire.UnquoteMayCopy(buf, isVerbatim)
299 }
300
301 return "", buf
302 }
303 if len(t.str) != 0 && t.num == 0 {
304 return t.str, nil
305 }
306
307 if t.num > 0 {
308 switch t.str[0] {
309 case 'F':
310 return string(jsonwire.AppendFloat(nil, float64(math.Float32frombits(uint32(t.num))), 32)), nil
311 case 'f':
312 return string(jsonwire.AppendFloat(nil, float64(math.Float64frombits(uint64(t.num))), 64)), nil
313 case 'i':
314 return strconv.FormatInt(int64(t.num), 10), nil
315 case 'u':
316 return strconv.FormatUint(uint64(t.num), 10), nil
317 }
318 }
319 return "<invalid jsontext.Token>", nil
320 }
321
322
323
324 func (t Token) appendNumber(dst []byte, flags *jsonflags.Flags) ([]byte, error) {
325 if raw := t.raw; raw != nil {
326
327 buf := raw.previousBuffer()
328 if Kind(buf[0]).normalize() == '0' {
329 dst, _, err := jsonwire.ReformatNumber(dst, buf, flags)
330 return dst, err
331 }
332 } else if t.num != 0 {
333
334 switch t.str[0] {
335 case 'F':
336 return jsonwire.AppendFloat(dst, float64(math.Float32frombits(uint32(t.num))), 32), nil
337 case 'f':
338 return jsonwire.AppendFloat(dst, float64(math.Float64frombits(uint64(t.num))), 64), nil
339 case 'i':
340 return strconv.AppendInt(dst, int64(t.num), 10), nil
341 case 'u':
342 return strconv.AppendUint(dst, uint64(t.num), 10), nil
343 }
344 }
345
346 panic("invalid JSON token kind: " + t.Kind().String())
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 func (t Token) Float32() (float32, error) {
370 f, err := t.float(32)
371 return float32(f), err
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385
386 func (t Token) Float() (float64, error) {
387 f, err := t.float(64)
388 return float64(f), err
389 }
390
391 func (t Token) float(bits int) (float64, error) {
392 if raw := t.raw; raw != nil {
393
394 if uint64(raw.previousOffsetStart()) != t.num {
395 panic(invalidTokenPanic)
396 }
397 buf := raw.previousBuffer()
398 if Kind(buf[0]).normalize() == '0' {
399 fv, err := strconv.ParseFloat(string(buf), bits)
400 if err != nil {
401 err = &numError{accessor: "Float", value: t.String(), err: errors.Unwrap(err)}
402 }
403 return fv, err
404 }
405 } else if t.num != 0 {
406
407 switch t.str[0] {
408 case 'F':
409 return float64(math.Float32frombits(uint32(t.num))), nil
410 case 'f':
411 f64 := float64(math.Float64frombits(uint64(t.num)))
412 if bits == 32 && !math.IsInf(f64, 0) && math.IsInf(float64(float32(f64)), 0) {
413 return f64, &numError{accessor: "Float", value: t.String(), err: strconv.ErrRange}
414 }
415 return f64, nil
416 case 'i':
417 return float64(int64(t.num)), nil
418 case 'u':
419 return float64(uint64(t.num)), nil
420 }
421 }
422
423
424 if t.Kind() == '"' {
425 switch t.String() {
426 case "NaN":
427 return math.NaN(), nil
428 case "Infinity":
429 return math.Inf(+1), nil
430 case "-Infinity":
431 return math.Inf(-1), nil
432 }
433
434
435 }
436
437 panic("invalid JSON token kind: " + t.Kind().String())
438 }
439
440
441
442
443
444
445
446
447
448
449
450
451
452 func (t Token) Int() (int64, error) {
453 if raw := t.raw; raw != nil {
454
455 if uint64(raw.previousOffsetStart()) != t.num {
456 panic(invalidTokenPanic)
457 }
458 buf := raw.previousBuffer()
459 if len(buf) > 0 && buf[0] == '-' {
460
461 switch abs, ok := jsonwire.ParseUint(buf[len("-"):]); {
462 case abs > -minInt64:
463 return minInt64, &numError{accessor: "Int", value: t.String(), err: strconv.ErrRange}
464 case ok:
465 return -1 * int64(abs), nil
466 }
467 } else {
468
469 switch abs, ok := jsonwire.ParseUint(buf); {
470 case abs > +maxInt64:
471 return maxInt64, &numError{accessor: "Int", value: t.String(), err: strconv.ErrRange}
472 case ok:
473 return +1 * int64(abs), nil
474 }
475 }
476
477 if Kind(buf[0]).normalize() == '0' {
478 f64, _ := strconv.ParseFloat(string(buf), 64)
479 return f64toi64(f64), &numError{accessor: "Int", value: t.String(), err: strconv.ErrSyntax}
480 }
481 } else if t.num != 0 {
482
483 switch t.str[0] {
484 case 'i':
485 return int64(t.num), nil
486 case 'u':
487 if t.num > maxInt64 {
488 return maxInt64, &numError{accessor: "Int", value: t.String(), err: strconv.ErrRange}
489 }
490 return int64(t.num), nil
491 case 'f', 'F':
492 f64 := float64(math.Float64frombits(uint64(t.num)))
493 if t.str[0] == 'F' {
494 f64 = float64(math.Float32frombits(uint32(t.num)))
495 }
496 switch i64 := f64toi64(f64); {
497 case math.IsNaN(f64), math.Trunc(f64) != f64:
498 return i64, &numError{accessor: "Int", value: t.String(), err: strconv.ErrSyntax}
499 case (i64 == minInt64 && f64 < minInt64) || (i64 == maxInt64 && f64 > maxInt64):
500 return i64, &numError{accessor: "Int", value: t.String(), err: strconv.ErrRange}
501 default:
502 return i64, nil
503 }
504 }
505 }
506
507 panic("invalid JSON token kind: " + t.Kind().String())
508 }
509
510 func f64toi64(f64 float64) int64 {
511 switch {
512 case math.IsNaN(f64):
513 return 0
514 case f64 >= maxInt64+1:
515 return maxInt64
516 case f64 < minInt64:
517 return minInt64
518 default:
519 return int64(f64)
520 }
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535 func (t Token) Uint() (uint64, error) {
536
537
538
539
540
541
542 if raw := t.raw; raw != nil {
543
544 if uint64(raw.previousOffsetStart()) != t.num {
545 panic(invalidTokenPanic)
546 }
547 buf := raw.previousBuffer()
548
549 switch abs, ok := jsonwire.ParseUint(buf); {
550 case ok:
551 return abs, nil
552 case abs == maxUint64:
553 return maxUint64, &numError{accessor: "Uint", value: t.String(), err: strconv.ErrRange}
554 }
555
556 if Kind(buf[0]).normalize() == '0' {
557 f64, _ := strconv.ParseFloat(string(buf), 64)
558 return f64tou64(f64), &numError{accessor: "Uint", value: t.String(), err: strconv.ErrSyntax}
559 }
560 } else if t.num != 0 {
561
562 switch t.str[0] {
563 case 'u':
564 return t.num, nil
565 case 'i':
566 if int64(t.num) < minUint64 {
567 return minUint64, &numError{accessor: "Uint", value: t.String(), err: strconv.ErrSyntax}
568 }
569 return uint64(int64(t.num)), nil
570 case 'f', 'F':
571 f64 := float64(math.Float64frombits(uint64(t.num)))
572 if t.str[0] == 'F' {
573 f64 = float64(math.Float32frombits(uint32(t.num)))
574 }
575 switch u64 := f64tou64(f64); {
576 case math.IsNaN(f64), math.Trunc(f64) != f64, math.Signbit(f64):
577 return u64, &numError{accessor: "Uint", value: t.String(), err: strconv.ErrSyntax}
578 case (u64 == minUint64 && f64 < minUint64) || (u64 == maxUint64 && f64 > maxUint64):
579 return u64, &numError{accessor: "Uint", value: t.String(), err: strconv.ErrRange}
580 default:
581 return u64, nil
582 }
583 }
584 }
585
586 panic("invalid JSON token kind: " + t.Kind().String())
587 }
588
589 func f64tou64(f64 float64) uint64 {
590 switch {
591 case math.IsNaN(f64):
592 return 0
593 case f64 >= maxUint64+1:
594 return maxUint64
595 case f64 < minUint64:
596 return minUint64
597 default:
598 return uint64(f64)
599 }
600 }
601
602
603 func (t Token) Kind() Kind {
604 switch {
605 case t.raw != nil:
606 raw := t.raw
607 if uint64(raw.previousOffsetStart()) != t.num {
608 panic(invalidTokenPanic)
609 }
610 return Kind(t.raw.buf[raw.prevStart]).normalize()
611 case t.num != 0:
612 return '0'
613 case len(t.str) != 0:
614 return '"'
615 default:
616 return invalidKind
617 }
618 }
619
620
621
622
623
624
625 type Kind byte
626
627 const (
628 KindInvalid Kind = 0
629 KindNull Kind = 'n'
630 KindFalse Kind = 'f'
631 KindTrue Kind = 't'
632 KindString Kind = '"'
633 KindNumber Kind = '0'
634 KindBeginObject Kind = '{'
635 KindEndObject Kind = '}'
636 KindBeginArray Kind = '['
637 KindEndArray Kind = ']'
638 )
639
640 const invalidKind Kind = 0
641
642
643 func (k Kind) String() string {
644 switch k {
645 case 0:
646 return "invalid"
647 case 'n':
648 return "null"
649 case 'f':
650 return "false"
651 case 't':
652 return "true"
653 case '"':
654 return "string"
655 case '0':
656 return "number"
657 case '{':
658 return "{"
659 case '}':
660 return "}"
661 case '[':
662 return "["
663 case ']':
664 return "]"
665 default:
666 return "<invalid jsontext.Kind: " + jsonwire.QuoteRune([]byte{byte(k)}) + ">"
667 }
668 }
669
670 var normKind = [256]Kind{
671 'n': 'n',
672 'f': 'f',
673 't': 't',
674 '"': '"',
675 '{': '{',
676 '}': '}',
677 '[': '[',
678 ']': ']',
679 '-': '0',
680 '0': '0',
681 '1': '0',
682 '2': '0',
683 '3': '0',
684 '4': '0',
685 '5': '0',
686 '6': '0',
687 '7': '0',
688 '8': '0',
689 '9': '0',
690 }
691
692
693
694 func (k Kind) normalize() Kind {
695
696 return normKind[k]
697 }
698
View as plain text