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 type Token struct {
43 nonComparable
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 raw *decodeBuffer
81
82
83
84
85 str string
86
87
88
89 num uint64
90 }
91
92
93
94 var (
95 Null Token = rawToken("null")
96 False Token = rawToken("false")
97 True Token = rawToken("true")
98
99 BeginObject Token = rawToken("{")
100 EndObject Token = rawToken("}")
101 BeginArray Token = rawToken("[")
102 EndArray Token = rawToken("]")
103
104 zeroString Token = rawToken(`""`)
105 zeroNumber Token = rawToken(`0`)
106
107 nanString Token = String("NaN")
108 pinfString Token = String("Infinity")
109 ninfString Token = String("-Infinity")
110 )
111
112 func rawToken(s string) Token {
113 return Token{raw: &decodeBuffer{buf: []byte(s), prevStart: 0, prevEnd: len(s)}}
114 }
115
116
117 func Bool(b bool) Token {
118 if b {
119 return True
120 }
121 return False
122 }
123
124
125
126
127 func String(s string) Token {
128 if len(s) == 0 {
129 return zeroString
130 }
131 return Token{str: s}
132 }
133
134
135
136
137 func Float(n float64) Token {
138 switch {
139 case math.Float64bits(n) == 0:
140 return zeroNumber
141 case math.IsNaN(n):
142 return nanString
143 case math.IsInf(n, +1):
144 return pinfString
145 case math.IsInf(n, -1):
146 return ninfString
147 }
148 return Token{str: "f", num: math.Float64bits(n)}
149 }
150
151
152 func Int(n int64) Token {
153 if n == 0 {
154 return zeroNumber
155 }
156 return Token{str: "i", num: uint64(n)}
157 }
158
159
160 func Uint(n uint64) Token {
161 if n == 0 {
162 return zeroNumber
163 }
164 return Token{str: "u", num: uint64(n)}
165 }
166
167
168
169 func (t Token) Clone() Token {
170
171 if raw := t.raw; raw != nil {
172
173 if t.raw.prevStart == 0 {
174 switch t.raw {
175 case Null.raw:
176 return Null
177 case False.raw:
178 return False
179 case True.raw:
180 return True
181 case BeginObject.raw:
182 return BeginObject
183 case EndObject.raw:
184 return EndObject
185 case BeginArray.raw:
186 return BeginArray
187 case EndArray.raw:
188 return EndArray
189 }
190 }
191
192 if uint64(raw.previousOffsetStart()) != t.num {
193 panic(invalidTokenPanic)
194 }
195 buf := bytes.Clone(raw.previousBuffer())
196 return Token{raw: &decodeBuffer{buf: buf, prevStart: 0, prevEnd: len(buf)}}
197 }
198 return t
199 }
200
201
202
203 func (t Token) Bool() bool {
204 switch t.raw {
205 case True.raw:
206 return true
207 case False.raw:
208 return false
209 default:
210 panic("invalid JSON token kind: " + t.Kind().String())
211 }
212 }
213
214
215
216 func (t Token) appendString(dst []byte, flags *jsonflags.Flags) ([]byte, error) {
217 if raw := t.raw; raw != nil {
218
219 buf := raw.previousBuffer()
220 if Kind(buf[0]) == '"' {
221 if jsonwire.ConsumeSimpleString(buf) == len(buf) {
222 return append(dst, buf...), nil
223 }
224 dst, _, err := jsonwire.ReformatString(dst, buf, flags)
225 return dst, err
226 }
227 } else if len(t.str) != 0 && t.num == 0 {
228
229 return jsonwire.AppendQuote(dst, t.str, flags)
230 }
231
232 panic("invalid JSON token kind: " + t.Kind().String())
233 }
234
235
236
237 func (t Token) String() string {
238
239
240
241
242 s, b := t.string()
243 if len(b) > 0 {
244 return string(b)
245 }
246 return s
247 }
248 func (t Token) string() (string, []byte) {
249 if raw := t.raw; raw != nil {
250 if uint64(raw.previousOffsetStart()) != t.num {
251 panic(invalidTokenPanic)
252 }
253 buf := raw.previousBuffer()
254 if buf[0] == '"' {
255
256 isVerbatim := jsonwire.ConsumeSimpleString(buf) == len(buf)
257 return "", jsonwire.UnquoteMayCopy(buf, isVerbatim)
258 }
259
260 return "", buf
261 }
262 if len(t.str) != 0 && t.num == 0 {
263 return t.str, nil
264 }
265
266 if t.num > 0 {
267 switch t.str[0] {
268 case 'f':
269 return string(jsonwire.AppendFloat(nil, math.Float64frombits(t.num), 64)), nil
270 case 'i':
271 return strconv.FormatInt(int64(t.num), 10), nil
272 case 'u':
273 return strconv.FormatUint(uint64(t.num), 10), nil
274 }
275 }
276 return "<invalid jsontext.Token>", nil
277 }
278
279
280
281 func (t Token) appendNumber(dst []byte, flags *jsonflags.Flags) ([]byte, error) {
282 if raw := t.raw; raw != nil {
283
284 buf := raw.previousBuffer()
285 if Kind(buf[0]).normalize() == '0' {
286 dst, _, err := jsonwire.ReformatNumber(dst, buf, flags)
287 return dst, err
288 }
289 } else if t.num != 0 {
290
291 switch t.str[0] {
292 case 'f':
293 return jsonwire.AppendFloat(dst, math.Float64frombits(t.num), 64), nil
294 case 'i':
295 return strconv.AppendInt(dst, int64(t.num), 10), nil
296 case 'u':
297 return strconv.AppendUint(dst, uint64(t.num), 10), nil
298 }
299 }
300
301 panic("invalid JSON token kind: " + t.Kind().String())
302 }
303
304
305
306
307
308 func (t Token) Float() float64 {
309 if raw := t.raw; raw != nil {
310
311 if uint64(raw.previousOffsetStart()) != t.num {
312 panic(invalidTokenPanic)
313 }
314 buf := raw.previousBuffer()
315 if Kind(buf[0]).normalize() == '0' {
316 fv, _ := jsonwire.ParseFloat(buf, 64)
317 return fv
318 }
319 } else if t.num != 0 {
320
321 switch t.str[0] {
322 case 'f':
323 return math.Float64frombits(t.num)
324 case 'i':
325 return float64(int64(t.num))
326 case 'u':
327 return float64(uint64(t.num))
328 }
329 }
330
331
332 if t.Kind() == '"' {
333 switch t.String() {
334 case "NaN":
335 return math.NaN()
336 case "Infinity":
337 return math.Inf(+1)
338 case "-Infinity":
339 return math.Inf(-1)
340 }
341 }
342
343 panic("invalid JSON token kind: " + t.Kind().String())
344 }
345
346
347
348
349
350
351 func (t Token) Int() int64 {
352 if raw := t.raw; raw != nil {
353
354 if uint64(raw.previousOffsetStart()) != t.num {
355 panic(invalidTokenPanic)
356 }
357 neg := false
358 buf := raw.previousBuffer()
359 if len(buf) > 0 && buf[0] == '-' {
360 neg, buf = true, buf[1:]
361 }
362 if numAbs, ok := jsonwire.ParseUint(buf); ok {
363 if neg {
364 if numAbs > -minInt64 {
365 return minInt64
366 }
367 return -1 * int64(numAbs)
368 } else {
369 if numAbs > +maxInt64 {
370 return maxInt64
371 }
372 return +1 * int64(numAbs)
373 }
374 }
375 } else if t.num != 0 {
376
377 switch t.str[0] {
378 case 'i':
379 return int64(t.num)
380 case 'u':
381 if t.num > maxInt64 {
382 return maxInt64
383 }
384 return int64(t.num)
385 }
386 }
387
388
389 if t.Kind() == '0' {
390 switch fv := t.Float(); {
391 case fv >= maxInt64:
392 return maxInt64
393 case fv <= minInt64:
394 return minInt64
395 default:
396 return int64(fv)
397 }
398 }
399
400 panic("invalid JSON token kind: " + t.Kind().String())
401 }
402
403
404
405
406
407
408 func (t Token) Uint() uint64 {
409
410
411
412
413 if raw := t.raw; raw != nil {
414
415 if uint64(raw.previousOffsetStart()) != t.num {
416 panic(invalidTokenPanic)
417 }
418 neg := false
419 buf := raw.previousBuffer()
420 if len(buf) > 0 && buf[0] == '-' {
421 neg, buf = true, buf[1:]
422 }
423 if num, ok := jsonwire.ParseUint(buf); ok {
424 if neg {
425 return minUint64
426 }
427 return num
428 }
429 } else if t.num != 0 {
430
431 switch t.str[0] {
432 case 'u':
433 return t.num
434 case 'i':
435 if int64(t.num) < minUint64 {
436 return minUint64
437 }
438 return uint64(int64(t.num))
439 }
440 }
441
442
443 if t.Kind() == '0' {
444 switch fv := t.Float(); {
445 case fv >= maxUint64:
446 return maxUint64
447 case fv <= minUint64:
448 return minUint64
449 default:
450 return uint64(fv)
451 }
452 }
453
454 panic("invalid JSON token kind: " + t.Kind().String())
455 }
456
457
458 func (t Token) Kind() Kind {
459 switch {
460 case t.raw != nil:
461 raw := t.raw
462 if uint64(raw.previousOffsetStart()) != t.num {
463 panic(invalidTokenPanic)
464 }
465 return Kind(t.raw.buf[raw.prevStart]).normalize()
466 case t.num != 0:
467 return '0'
468 case len(t.str) != 0:
469 return '"'
470 default:
471 return invalidKind
472 }
473 }
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 type Kind byte
492
493 const invalidKind Kind = 0
494
495
496 func (k Kind) String() string {
497 switch k {
498 case 'n':
499 return "null"
500 case 'f':
501 return "false"
502 case 't':
503 return "true"
504 case '"':
505 return "string"
506 case '0':
507 return "number"
508 case '{':
509 return "{"
510 case '}':
511 return "}"
512 case '[':
513 return "["
514 case ']':
515 return "]"
516 default:
517 return "<invalid jsontext.Kind: " + jsonwire.QuoteRune(string(k)) + ">"
518 }
519 }
520
521
522 func (k Kind) normalize() Kind {
523 if k == '-' || ('0' <= k && k <= '9') {
524 return '0'
525 }
526 return k
527 }
528
View as plain text