1// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved. 2// Use of this source code is governed by a MIT license found in the LICENSE file. 3 4package 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// Note: 18// - we cannot use strconv.Quote and strconv.Unquote because json quotes/unquotes differently. 19// We implement it here. 20 21// Top-level methods of json(End|Dec)Driver (which are implementations of (en|de)cDriver 22// MUST not call one-another. 23 24import ( 25 "bytes" 26 "encoding/base64" 27 "math" 28 "reflect" 29 "strconv" 30 "time" 31 "unicode" 32 "unicode/utf16" 33 "unicode/utf8" 34) 35 36//-------------------------------- 37 38var jsonLiterals = [...]byte{ 39 '"', 't', 'r', 'u', 'e', '"', 40 '"', 'f', 'a', 'l', 's', 'e', '"', 41 '"', 'n', 'u', 'l', 'l', '"', 42} 43 44const ( 45 jsonLitTrueQ = 0 46 jsonLitTrue = 1 47 jsonLitFalseQ = 6 48 jsonLitFalse = 7 49 // jsonLitNullQ = 13 50 jsonLitNull = 14 51) 52 53var ( 54 jsonLiteral4True = jsonLiterals[jsonLitTrue+1 : jsonLitTrue+4] 55 jsonLiteral4False = jsonLiterals[jsonLitFalse+1 : jsonLitFalse+5] 56 jsonLiteral4Null = jsonLiterals[jsonLitNull+1 : jsonLitNull+4] 57) 58 59const ( 60 jsonU4Chk2 = '0' 61 jsonU4Chk1 = 'a' - 10 62 jsonU4Chk0 = 'A' - 10 63 64 jsonScratchArrayLen = 64 65) 66 67const ( 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 jsonSpacesOrTabsLen = 128 77 78 jsonAlwaysReturnInternString = false 79) 80 81var ( 82 // jsonTabs and jsonSpaces are used as caches for indents 83 jsonTabs, jsonSpaces [jsonSpacesOrTabsLen]byte 84 85 jsonCharHtmlSafeSet bitset256 86 jsonCharSafeSet bitset256 87 jsonCharWhitespaceSet bitset256 88 jsonNumSet bitset256 89) 90 91func init() { 92 var i byte 93 for i = 0; i < jsonSpacesOrTabsLen; i++ { 94 jsonSpaces[i] = ' ' 95 jsonTabs[i] = '\t' 96 } 97 98 // populate the safe values as true: note: ASCII control characters are (0-31) 99 // jsonCharSafeSet: all true except (0-31) " \ 100 // jsonCharHtmlSafeSet: all true except (0-31) " \ < > & 101 for i = 32; i < utf8.RuneSelf; i++ { 102 switch i { 103 case '"', '\\': 104 case '<', '>', '&': 105 jsonCharSafeSet.set(i) // = true 106 default: 107 jsonCharSafeSet.set(i) 108 jsonCharHtmlSafeSet.set(i) 109 } 110 } 111 for i = 0; i <= utf8.RuneSelf; i++ { 112 switch i { 113 case ' ', '\t', '\r', '\n': 114 jsonCharWhitespaceSet.set(i) 115 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-': 116 jsonNumSet.set(i) 117 } 118 } 119} 120 121// ---------------- 122 123type jsonEncDriverTypical struct { 124 jsonEncDriver 125} 126 127func (e *jsonEncDriverTypical) typical() {} 128 129func (e *jsonEncDriverTypical) WriteArrayStart(length int) { 130 e.w.writen1('[') 131 e.c = containerArrayStart 132} 133 134func (e *jsonEncDriverTypical) WriteArrayElem() { 135 if e.c != containerArrayStart { 136 e.w.writen1(',') 137 } 138 e.c = containerArrayElem 139} 140 141func (e *jsonEncDriverTypical) WriteArrayEnd() { 142 e.w.writen1(']') 143 e.c = containerArrayEnd 144} 145 146func (e *jsonEncDriverTypical) WriteMapStart(length int) { 147 e.w.writen1('{') 148 e.c = containerMapStart 149} 150 151func (e *jsonEncDriverTypical) WriteMapElemKey() { 152 if e.c != containerMapStart { 153 e.w.writen1(',') 154 } 155 e.c = containerMapKey 156} 157 158func (e *jsonEncDriverTypical) WriteMapElemValue() { 159 e.w.writen1(':') 160 e.c = containerMapValue 161} 162 163func (e *jsonEncDriverTypical) WriteMapEnd() { 164 e.w.writen1('}') 165 e.c = containerMapEnd 166} 167 168func (e *jsonEncDriverTypical) EncodeBool(b bool) { 169 if b { 170 e.w.writeb(jsonLiterals[jsonLitTrue : jsonLitTrue+4]) 171 } else { 172 e.w.writeb(jsonLiterals[jsonLitFalse : jsonLitFalse+5]) 173 } 174} 175 176func (e *jsonEncDriverTypical) EncodeFloat64(f float64) { 177 fmt, prec := jsonFloatStrconvFmtPrec(f) 178 e.w.writeb(strconv.AppendFloat(e.b[:0], f, fmt, prec, 64)) 179} 180 181func (e *jsonEncDriverTypical) EncodeInt(v int64) { 182 e.w.writeb(strconv.AppendInt(e.b[:0], v, 10)) 183} 184 185func (e *jsonEncDriverTypical) EncodeUint(v uint64) { 186 e.w.writeb(strconv.AppendUint(e.b[:0], v, 10)) 187} 188 189func (e *jsonEncDriverTypical) EncodeFloat32(f float32) { 190 e.EncodeFloat64(float64(f)) 191} 192 193// func (e *jsonEncDriverTypical) atEndOfEncode() { 194// if e.tw { 195// e.w.writen1(' ') 196// } 197// } 198 199// ---------------- 200 201type jsonEncDriverGeneric struct { 202 jsonEncDriver 203 // ds string // indent string 204 di int8 // indent per 205 d bool // indenting? 206 dt bool // indent using tabs 207 dl uint16 // indent level 208 ks bool // map key as string 209 is byte // integer as string 210 _ byte // padding 211 _ [2]uint64 // padding 212} 213 214// indent is done as below: 215// - newline and indent are added before each mapKey or arrayElem 216// - newline and indent are added before each ending, 217// except there was no entry (so we can have {} or []) 218 219func (e *jsonEncDriverGeneric) reset() { 220 e.jsonEncDriver.reset() 221 e.d, e.dt, e.dl, e.di = false, false, 0, 0 222 if e.h.Indent > 0 { 223 e.d = true 224 e.di = int8(e.h.Indent) 225 } else if e.h.Indent < 0 { 226 e.d = true 227 e.dt = true 228 e.di = int8(-e.h.Indent) 229 } 230 e.ks = e.h.MapKeyAsString 231 e.is = e.h.IntegerAsString 232} 233 234func (e *jsonEncDriverGeneric) WriteArrayStart(length int) { 235 if e.d { 236 e.dl++ 237 } 238 e.w.writen1('[') 239 e.c = containerArrayStart 240} 241 242func (e *jsonEncDriverGeneric) WriteArrayElem() { 243 if e.c != containerArrayStart { 244 e.w.writen1(',') 245 } 246 if e.d { 247 e.writeIndent() 248 } 249 e.c = containerArrayElem 250} 251 252func (e *jsonEncDriverGeneric) WriteArrayEnd() { 253 if e.d { 254 e.dl-- 255 if e.c != containerArrayStart { 256 e.writeIndent() 257 } 258 } 259 e.w.writen1(']') 260 e.c = containerArrayEnd 261} 262 263func (e *jsonEncDriverGeneric) WriteMapStart(length int) { 264 if e.d { 265 e.dl++ 266 } 267 e.w.writen1('{') 268 e.c = containerMapStart 269} 270 271func (e *jsonEncDriverGeneric) WriteMapElemKey() { 272 if e.c != containerMapStart { 273 e.w.writen1(',') 274 } 275 if e.d { 276 e.writeIndent() 277 } 278 e.c = containerMapKey 279} 280 281func (e *jsonEncDriverGeneric) WriteMapElemValue() { 282 if e.d { 283 e.w.writen2(':', ' ') 284 } else { 285 e.w.writen1(':') 286 } 287 e.c = containerMapValue 288} 289 290func (e *jsonEncDriverGeneric) WriteMapEnd() { 291 if e.d { 292 e.dl-- 293 if e.c != containerMapStart { 294 e.writeIndent() 295 } 296 } 297 e.w.writen1('}') 298 e.c = containerMapEnd 299} 300 301func (e *jsonEncDriverGeneric) writeIndent() { 302 e.w.writen1('\n') 303 x := int(e.di) * int(e.dl) 304 if e.dt { 305 for x > jsonSpacesOrTabsLen { 306 e.w.writeb(jsonTabs[:]) 307 x -= jsonSpacesOrTabsLen 308 } 309 e.w.writeb(jsonTabs[:x]) 310 } else { 311 for x > jsonSpacesOrTabsLen { 312 e.w.writeb(jsonSpaces[:]) 313 x -= jsonSpacesOrTabsLen 314 } 315 e.w.writeb(jsonSpaces[:x]) 316 } 317} 318 319func (e *jsonEncDriverGeneric) EncodeBool(b bool) { 320 if e.ks && e.c == containerMapKey { 321 if b { 322 e.w.writeb(jsonLiterals[jsonLitTrueQ : jsonLitTrueQ+6]) 323 } else { 324 e.w.writeb(jsonLiterals[jsonLitFalseQ : jsonLitFalseQ+7]) 325 } 326 } else { 327 if b { 328 e.w.writeb(jsonLiterals[jsonLitTrue : jsonLitTrue+4]) 329 } else { 330 e.w.writeb(jsonLiterals[jsonLitFalse : jsonLitFalse+5]) 331 } 332 } 333} 334 335func (e *jsonEncDriverGeneric) EncodeFloat64(f float64) { 336 // instead of using 'g', specify whether to use 'e' or 'f' 337 fmt, prec := jsonFloatStrconvFmtPrec(f) 338 339 var blen int 340 if e.ks && e.c == containerMapKey { 341 blen = 2 + len(strconv.AppendFloat(e.b[1:1], f, fmt, prec, 64)) 342 e.b[0] = '"' 343 e.b[blen-1] = '"' 344 } else { 345 blen = len(strconv.AppendFloat(e.b[:0], f, fmt, prec, 64)) 346 } 347 e.w.writeb(e.b[:blen]) 348} 349 350func (e *jsonEncDriverGeneric) EncodeInt(v int64) { 351 x := e.is 352 if x == 'A' || x == 'L' && (v > 1<<53 || v < -(1<<53)) || (e.ks && e.c == containerMapKey) { 353 blen := 2 + len(strconv.AppendInt(e.b[1:1], v, 10)) 354 e.b[0] = '"' 355 e.b[blen-1] = '"' 356 e.w.writeb(e.b[:blen]) 357 return 358 } 359 e.w.writeb(strconv.AppendInt(e.b[:0], v, 10)) 360} 361 362func (e *jsonEncDriverGeneric) EncodeUint(v uint64) { 363 x := e.is 364 if x == 'A' || x == 'L' && v > 1<<53 || (e.ks && e.c == containerMapKey) { 365 blen := 2 + len(strconv.AppendUint(e.b[1:1], v, 10)) 366 e.b[0] = '"' 367 e.b[blen-1] = '"' 368 e.w.writeb(e.b[:blen]) 369 return 370 } 371 e.w.writeb(strconv.AppendUint(e.b[:0], v, 10)) 372} 373 374func (e *jsonEncDriverGeneric) EncodeFloat32(f float32) { 375 // e.encodeFloat(float64(f), 32) 376 // always encode all floats as IEEE 64-bit floating point. 377 // It also ensures that we can decode in full precision even if into a float32, 378 // as what is written is always to float64 precision. 379 e.EncodeFloat64(float64(f)) 380} 381 382// func (e *jsonEncDriverGeneric) atEndOfEncode() { 383// if e.tw { 384// if e.d { 385// e.w.writen1('\n') 386// } else { 387// e.w.writen1(' ') 388// } 389// } 390// } 391 392// -------------------- 393 394type jsonEncDriver struct { 395 noBuiltInTypes 396 e *Encoder 397 h *JsonHandle 398 w *encWriterSwitch 399 se extWrapper 400 // ---- cpu cache line boundary? 401 bs []byte // scratch 402 // ---- cpu cache line boundary? 403 // scratch: encode time, etc. 404 // include scratch buffer and padding, but leave space for containerstate 405 b [jsonScratchArrayLen + 8 + 8 - 1]byte 406 c containerState 407 // _ [2]uint64 // padding 408} 409 410func (e *jsonEncDriver) EncodeNil() { 411 // We always encode nil as just null (never in quotes) 412 // This allows us to easily decode if a nil in the json stream 413 // ie if initial token is n. 414 e.w.writeb(jsonLiterals[jsonLitNull : jsonLitNull+4]) 415 416 // if e.h.MapKeyAsString && e.c == containerMapKey { 417 // e.w.writeb(jsonLiterals[jsonLitNullQ : jsonLitNullQ+6]) 418 // } else { 419 // e.w.writeb(jsonLiterals[jsonLitNull : jsonLitNull+4]) 420 // } 421} 422 423func (e *jsonEncDriver) EncodeTime(t time.Time) { 424 // Do NOT use MarshalJSON, as it allocates internally. 425 // instead, we call AppendFormat directly, using our scratch buffer (e.b) 426 if t.IsZero() { 427 e.EncodeNil() 428 } else { 429 e.b[0] = '"' 430 b := t.AppendFormat(e.b[1:1], time.RFC3339Nano) 431 e.b[len(b)+1] = '"' 432 e.w.writeb(e.b[:len(b)+2]) 433 } 434 // v, err := t.MarshalJSON(); if err != nil { e.e.error(err) } e.w.writeb(v) 435} 436 437func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) { 438 if v := ext.ConvertExt(rv); v == nil { 439 e.EncodeNil() 440 } else { 441 en.encode(v) 442 } 443} 444 445func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) { 446 // only encodes re.Value (never re.Data) 447 if re.Value == nil { 448 e.EncodeNil() 449 } else { 450 en.encode(re.Value) 451 } 452} 453 454func (e *jsonEncDriver) EncodeString(c charEncoding, v string) { 455 e.quoteStr(v) 456} 457 458func (e *jsonEncDriver) EncodeStringEnc(c charEncoding, v string) { 459 e.quoteStr(v) 460} 461 462func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) { 463 // if encoding raw bytes and RawBytesExt is configured, use it to encode 464 if v == nil { 465 e.EncodeNil() 466 return 467 } 468 if c == cRAW { 469 if e.se.InterfaceExt != nil { 470 e.EncodeExt(v, 0, &e.se, e.e) 471 return 472 } 473 474 slen := base64.StdEncoding.EncodedLen(len(v)) + 2 475 if cap(e.bs) >= slen { 476 e.bs = e.bs[:slen] 477 } else { 478 e.bs = make([]byte, slen) 479 } 480 e.bs[0] = '"' 481 base64.StdEncoding.Encode(e.bs[1:], v) 482 e.bs[slen-1] = '"' 483 e.w.writeb(e.bs) 484 } else { 485 e.quoteStr(stringView(v)) 486 } 487} 488 489func (e *jsonEncDriver) EncodeStringBytesRaw(v []byte) { 490 // if encoding raw bytes and RawBytesExt is configured, use it to encode 491 if v == nil { 492 e.EncodeNil() 493 return 494 } 495 if e.se.InterfaceExt != nil { 496 e.EncodeExt(v, 0, &e.se, e.e) 497 return 498 } 499 500 slen := base64.StdEncoding.EncodedLen(len(v)) + 2 501 if cap(e.bs) >= slen { 502 e.bs = e.bs[:slen] 503 } else { 504 e.bs = make([]byte, slen) 505 } 506 e.bs[0] = '"' 507 base64.StdEncoding.Encode(e.bs[1:], v) 508 e.bs[slen-1] = '"' 509 e.w.writeb(e.bs) 510} 511 512func (e *jsonEncDriver) EncodeAsis(v []byte) { 513 e.w.writeb(v) 514} 515 516func (e *jsonEncDriver) quoteStr(s string) { 517 // adapted from std pkg encoding/json 518 const hex = "0123456789abcdef" 519 w := e.w 520 htmlasis := e.h.HTMLCharsAsIs 521 w.writen1('"') 522 var start int 523 for i, slen := 0, len(s); i < slen; { 524 // encode all bytes < 0x20 (except \r, \n). 525 // also encode < > & to prevent security holes when served to some browsers. 526 if b := s[i]; b < utf8.RuneSelf { 527 // if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { 528 // if (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) { 529 if jsonCharHtmlSafeSet.isset(b) || (htmlasis && jsonCharSafeSet.isset(b)) { 530 i++ 531 continue 532 } 533 if start < i { 534 w.writestr(s[start:i]) 535 } 536 switch b { 537 case '\\', '"': 538 w.writen2('\\', b) 539 case '\n': 540 w.writen2('\\', 'n') 541 case '\r': 542 w.writen2('\\', 'r') 543 case '\b': 544 w.writen2('\\', 'b') 545 case '\f': 546 w.writen2('\\', 'f') 547 case '\t': 548 w.writen2('\\', 't') 549 default: 550 w.writestr(`\u00`) 551 w.writen2(hex[b>>4], hex[b&0xF]) 552 } 553 i++ 554 start = i 555 continue 556 } 557 c, size := utf8.DecodeRuneInString(s[i:]) 558 if c == utf8.RuneError && size == 1 { 559 if start < i { 560 w.writestr(s[start:i]) 561 } 562 w.writestr(`\ufffd`) 563 i += size 564 start = i 565 continue 566 } 567 // U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR. 568 // Both technically valid JSON, but bomb on JSONP, so fix here unconditionally. 569 if c == '\u2028' || c == '\u2029' { 570 if start < i { 571 w.writestr(s[start:i]) 572 } 573 w.writestr(`\u202`) 574 w.writen1(hex[c&0xF]) 575 i += size 576 start = i 577 continue 578 } 579 i += size 580 } 581 if start < len(s) { 582 w.writestr(s[start:]) 583 } 584 w.writen1('"') 585} 586 587func (e *jsonEncDriver) atEndOfEncode() { 588 // if e.c == 0 { // scalar written, output space 589 // e.w.writen1(' ') 590 // } else if e.h.TermWhitespace { // container written, output new-line 591 // e.w.writen1('\n') 592 // } 593 if e.h.TermWhitespace { 594 if e.c == 0 { // scalar written, output space 595 e.w.writen1(' ') 596 } else { // container written, output new-line 597 e.w.writen1('\n') 598 } 599 } 600 601 // e.c = 0 602} 603 604type jsonDecDriver struct { 605 noBuiltInTypes 606 d *Decoder 607 h *JsonHandle 608 r *decReaderSwitch 609 se extWrapper 610 611 // ---- writable fields during execution --- *try* to keep in sep cache line 612 613 c containerState 614 // tok is used to store the token read right after skipWhiteSpace. 615 tok uint8 616 fnull bool // found null from appendStringAsBytes 617 bs []byte // scratch. Initialized from b. Used for parsing strings or numbers. 618 bstr [8]byte // scratch used for string \UXXX parsing 619 // ---- cpu cache line boundary? 620 b [jsonScratchArrayLen]byte // scratch 1, used for parsing strings or numbers or time.Time 621 b2 [jsonScratchArrayLen]byte // scratch 2, used only for readUntil, decNumBytes 622 623 // _ [3]uint64 // padding 624 // n jsonNum 625} 626 627// func jsonIsWS(b byte) bool { 628// // return b == ' ' || b == '\t' || b == '\r' || b == '\n' 629// return jsonCharWhitespaceSet.isset(b) 630// } 631 632func (d *jsonDecDriver) uncacheRead() { 633 if d.tok != 0 { 634 d.r.unreadn1() 635 d.tok = 0 636 } 637} 638 639func (d *jsonDecDriver) ReadMapStart() int { 640 if d.tok == 0 { 641 d.tok = d.r.skip(&jsonCharWhitespaceSet) 642 } 643 const xc uint8 = '{' 644 if d.tok != xc { 645 d.d.errorf("read map - expect char '%c' but got char '%c'", xc, d.tok) 646 } 647 d.tok = 0 648 d.c = containerMapStart 649 return -1 650} 651 652func (d *jsonDecDriver) ReadArrayStart() int { 653 if d.tok == 0 { 654 d.tok = d.r.skip(&jsonCharWhitespaceSet) 655 } 656 const xc uint8 = '[' 657 if d.tok != xc { 658 d.d.errorf("read array - expect char '%c' but got char '%c'", xc, d.tok) 659 } 660 d.tok = 0 661 d.c = containerArrayStart 662 return -1 663} 664 665func (d *jsonDecDriver) CheckBreak() bool { 666 if d.tok == 0 { 667 d.tok = d.r.skip(&jsonCharWhitespaceSet) 668 } 669 return d.tok == '}' || d.tok == ']' 670} 671 672// For the ReadXXX methods below, we could just delegate to helper functions 673// readContainerState(c containerState, xc uint8, check bool) 674// - ReadArrayElem would become: 675// readContainerState(containerArrayElem, ',', d.c != containerArrayStart) 676// 677// However, until mid-stack inlining comes in go1.11 which supports inlining of 678// one-liners, we explicitly write them all 5 out to elide the extra func call. 679// 680// TODO: For Go 1.11, if inlined, consider consolidating these. 681 682func (d *jsonDecDriver) ReadArrayElem() { 683 const xc uint8 = ',' 684 if d.tok == 0 { 685 d.tok = d.r.skip(&jsonCharWhitespaceSet) 686 } 687 if d.c != containerArrayStart { 688 if d.tok != xc { 689 d.d.errorf("read array element - expect char '%c' but got char '%c'", xc, d.tok) 690 } 691 d.tok = 0 692 } 693 d.c = containerArrayElem 694} 695 696func (d *jsonDecDriver) ReadArrayEnd() { 697 const xc uint8 = ']' 698 if d.tok == 0 { 699 d.tok = d.r.skip(&jsonCharWhitespaceSet) 700 } 701 if d.tok != xc { 702 d.d.errorf("read array end - expect char '%c' but got char '%c'", xc, d.tok) 703 } 704 d.tok = 0 705 d.c = containerArrayEnd 706} 707 708func (d *jsonDecDriver) ReadMapElemKey() { 709 const xc uint8 = ',' 710 if d.tok == 0 { 711 d.tok = d.r.skip(&jsonCharWhitespaceSet) 712 } 713 if d.c != containerMapStart { 714 if d.tok != xc { 715 d.d.errorf("read map key - expect char '%c' but got char '%c'", xc, d.tok) 716 } 717 d.tok = 0 718 } 719 d.c = containerMapKey 720} 721 722func (d *jsonDecDriver) ReadMapElemValue() { 723 const xc uint8 = ':' 724 if d.tok == 0 { 725 d.tok = d.r.skip(&jsonCharWhitespaceSet) 726 } 727 if d.tok != xc { 728 d.d.errorf("read map value - expect char '%c' but got char '%c'", xc, d.tok) 729 } 730 d.tok = 0 731 d.c = containerMapValue 732} 733 734func (d *jsonDecDriver) ReadMapEnd() { 735 const xc uint8 = '}' 736 if d.tok == 0 { 737 d.tok = d.r.skip(&jsonCharWhitespaceSet) 738 } 739 if d.tok != xc { 740 d.d.errorf("read map end - expect char '%c' but got char '%c'", xc, d.tok) 741 } 742 d.tok = 0 743 d.c = containerMapEnd 744} 745 746// func (d *jsonDecDriver) readLit(length, fromIdx uint8) { 747// // length here is always less than 8 (literals are: null, true, false) 748// bs := d.r.readx(int(length)) 749// d.tok = 0 750// if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:fromIdx+length]) { 751// d.d.errorf("expecting %s: got %s", jsonLiterals[fromIdx:fromIdx+length], bs) 752// } 753// } 754 755func (d *jsonDecDriver) readLit4True() { 756 bs := d.r.readx(3) 757 d.tok = 0 758 if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4True) { 759 d.d.errorf("expecting %s: got %s", jsonLiteral4True, bs) 760 } 761} 762 763func (d *jsonDecDriver) readLit4False() { 764 bs := d.r.readx(4) 765 d.tok = 0 766 if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4False) { 767 d.d.errorf("expecting %s: got %s", jsonLiteral4False, bs) 768 } 769} 770 771func (d *jsonDecDriver) readLit4Null() { 772 bs := d.r.readx(3) 773 d.tok = 0 774 if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4Null) { 775 d.d.errorf("expecting %s: got %s", jsonLiteral4Null, bs) 776 } 777} 778 779func (d *jsonDecDriver) TryDecodeAsNil() bool { 780 if d.tok == 0 { 781 d.tok = d.r.skip(&jsonCharWhitespaceSet) 782 } 783 // we shouldn't try to see if "null" was here, right? 784 // only the plain string: `null` denotes a nil (ie not quotes) 785 if d.tok == 'n' { 786 d.readLit4Null() 787 return true 788 } 789 return false 790} 791 792func (d *jsonDecDriver) DecodeBool() (v bool) { 793 if d.tok == 0 { 794 d.tok = d.r.skip(&jsonCharWhitespaceSet) 795 } 796 fquot := d.c == containerMapKey && d.tok == '"' 797 if fquot { 798 d.tok = d.r.readn1() 799 } 800 switch d.tok { 801 case 'f': 802 d.readLit4False() 803 // v = false 804 case 't': 805 d.readLit4True() 806 v = true 807 default: 808 d.d.errorf("decode bool: got first char %c", d.tok) 809 // v = false // "unreachable" 810 } 811 if fquot { 812 d.r.readn1() 813 } 814 return 815} 816 817func (d *jsonDecDriver) DecodeTime() (t time.Time) { 818 // read string, and pass the string into json.unmarshal 819 d.appendStringAsBytes() 820 if d.fnull { 821 return 822 } 823 t, err := time.Parse(time.RFC3339, stringView(d.bs)) 824 if err != nil { 825 d.d.errorv(err) 826 } 827 return 828} 829 830func (d *jsonDecDriver) ContainerType() (vt valueType) { 831 // check container type by checking the first char 832 if d.tok == 0 { 833 d.tok = d.r.skip(&jsonCharWhitespaceSet) 834 } 835 836 // optimize this, so we don't do 4 checks but do one computation. 837 // return jsonContainerSet[d.tok] 838 839 // ContainerType is mostly called for Map and Array, 840 // so this conditional is good enough (max 2 checks typically) 841 if b := d.tok; b == '{' { 842 return valueTypeMap 843 } else if b == '[' { 844 return valueTypeArray 845 } else if b == 'n' { 846 return valueTypeNil 847 } else if b == '"' { 848 return valueTypeString 849 } 850 return valueTypeUnset 851} 852 853func (d *jsonDecDriver) decNumBytes() (bs []byte) { 854 // stores num bytes in d.bs 855 if d.tok == 0 { 856 d.tok = d.r.skip(&jsonCharWhitespaceSet) 857 } 858 if d.tok == '"' { 859 bs = d.r.readUntil(d.b2[:0], '"') 860 bs = bs[:len(bs)-1] 861 } else { 862 d.r.unreadn1() 863 bs = d.r.readTo(d.bs[:0], &jsonNumSet) 864 } 865 d.tok = 0 866 return bs 867} 868 869func (d *jsonDecDriver) DecodeUint64() (u uint64) { 870 bs := d.decNumBytes() 871 if len(bs) == 0 { 872 return 873 } 874 n, neg, badsyntax, overflow := jsonParseInteger(bs) 875 if overflow { 876 d.d.errorf("overflow parsing unsigned integer: %s", bs) 877 } else if neg { 878 d.d.errorf("minus found parsing unsigned integer: %s", bs) 879 } else if badsyntax { 880 // fallback: try to decode as float, and cast 881 n = d.decUint64ViaFloat(stringView(bs)) 882 } 883 return n 884} 885 886func (d *jsonDecDriver) DecodeInt64() (i int64) { 887 const cutoff = uint64(1 << uint(64-1)) 888 bs := d.decNumBytes() 889 if len(bs) == 0 { 890 return 891 } 892 n, neg, badsyntax, overflow := jsonParseInteger(bs) 893 if overflow { 894 d.d.errorf("overflow parsing integer: %s", bs) 895 } else if badsyntax { 896 // d.d.errorf("invalid syntax for integer: %s", bs) 897 // fallback: try to decode as float, and cast 898 if neg { 899 n = d.decUint64ViaFloat(stringView(bs[1:])) 900 } else { 901 n = d.decUint64ViaFloat(stringView(bs)) 902 } 903 } 904 if neg { 905 if n > cutoff { 906 d.d.errorf("overflow parsing integer: %s", bs) 907 } 908 i = -(int64(n)) 909 } else { 910 if n >= cutoff { 911 d.d.errorf("overflow parsing integer: %s", bs) 912 } 913 i = int64(n) 914 } 915 return 916} 917 918func (d *jsonDecDriver) decUint64ViaFloat(s string) (u uint64) { 919 if len(s) == 0 { 920 return 921 } 922 f, err := strconv.ParseFloat(s, 64) 923 if err != nil { 924 d.d.errorf("invalid syntax for integer: %s", s) 925 // d.d.errorv(err) 926 } 927 fi, ff := math.Modf(f) 928 if ff > 0 { 929 d.d.errorf("fractional part found parsing integer: %s", s) 930 } else if fi > float64(math.MaxUint64) { 931 d.d.errorf("overflow parsing integer: %s", s) 932 } 933 return uint64(fi) 934} 935 936func (d *jsonDecDriver) DecodeFloat64() (f float64) { 937 bs := d.decNumBytes() 938 if len(bs) == 0 { 939 return 940 } 941 f, err := strconv.ParseFloat(stringView(bs), 64) 942 if err != nil { 943 d.d.errorv(err) 944 } 945 return 946} 947 948func (d *jsonDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { 949 if ext == nil { 950 re := rv.(*RawExt) 951 re.Tag = xtag 952 d.d.decode(&re.Value) 953 } else { 954 var v interface{} 955 d.d.decode(&v) 956 ext.UpdateExt(rv, v) 957 } 958 return 959} 960 961func (d *jsonDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) { 962 // if decoding into raw bytes, and the RawBytesExt is configured, use it to decode. 963 if d.se.InterfaceExt != nil { 964 bsOut = bs 965 d.DecodeExt(&bsOut, 0, &d.se) 966 return 967 } 968 if d.tok == 0 { 969 d.tok = d.r.skip(&jsonCharWhitespaceSet) 970 } 971 // check if an "array" of uint8's (see ContainerType for how to infer if an array) 972 if d.tok == '[' { 973 bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d) 974 return 975 } 976 d.appendStringAsBytes() 977 // base64 encodes []byte{} as "", and we encode nil []byte as null. 978 // Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}. 979 // appendStringAsBytes returns a zero-len slice for both, so as not to reset d.bs. 980 // However, it sets a fnull field to true, so we can check if a null was found. 981 if len(d.bs) == 0 { 982 if d.fnull { 983 return nil 984 } 985 return []byte{} 986 } 987 bs0 := d.bs 988 slen := base64.StdEncoding.DecodedLen(len(bs0)) 989 if slen <= cap(bs) { 990 bsOut = bs[:slen] 991 } else if zerocopy && slen <= cap(d.b2) { 992 bsOut = d.b2[:slen] 993 } else { 994 bsOut = make([]byte, slen) 995 } 996 slen2, err := base64.StdEncoding.Decode(bsOut, bs0) 997 if err != nil { 998 d.d.errorf("error decoding base64 binary '%s': %v", bs0, err) 999 return nil 1000 } 1001 if slen != slen2 { 1002 bsOut = bsOut[:slen2] 1003 } 1004 return 1005} 1006 1007func (d *jsonDecDriver) DecodeString() (s string) { 1008 d.appendStringAsBytes() 1009 return d.bsToString() 1010} 1011 1012func (d *jsonDecDriver) DecodeStringAsBytes() (s []byte) { 1013 d.appendStringAsBytes() 1014 return d.bs 1015} 1016 1017func (d *jsonDecDriver) appendStringAsBytes() { 1018 if d.tok == 0 { 1019 d.tok = d.r.skip(&jsonCharWhitespaceSet) 1020 } 1021 1022 d.fnull = false 1023 if d.tok != '"' { 1024 // d.d.errorf("expect char '%c' but got char '%c'", '"', d.tok) 1025 // handle non-string scalar: null, true, false or a number 1026 switch d.tok { 1027 case 'n': 1028 d.readLit4Null() 1029 d.bs = d.bs[:0] 1030 d.fnull = true 1031 case 'f': 1032 d.readLit4False() 1033 d.bs = d.bs[:5] 1034 copy(d.bs, "false") 1035 case 't': 1036 d.readLit4True() 1037 d.bs = d.bs[:4] 1038 copy(d.bs, "true") 1039 default: 1040 // try to parse a valid number 1041 bs := d.decNumBytes() 1042 if len(bs) <= cap(d.bs) { 1043 d.bs = d.bs[:len(bs)] 1044 } else { 1045 d.bs = make([]byte, len(bs)) 1046 } 1047 copy(d.bs, bs) 1048 } 1049 return 1050 } 1051 1052 d.tok = 0 1053 r := d.r 1054 var cs = r.readUntil(d.b2[:0], '"') 1055 var cslen = uint(len(cs)) 1056 var c uint8 1057 v := d.bs[:0] 1058 // append on each byte seen can be expensive, so we just 1059 // keep track of where we last read a contiguous set of 1060 // non-special bytes (using cursor variable), 1061 // and when we see a special byte 1062 // e.g. end-of-slice, " or \, 1063 // we will append the full range into the v slice before proceeding 1064 var i, cursor uint 1065 for { 1066 if i == cslen { 1067 v = append(v, cs[cursor:]...) 1068 cs = r.readUntil(d.b2[:0], '"') 1069 cslen = uint(len(cs)) 1070 i, cursor = 0, 0 1071 } 1072 c = cs[i] 1073 if c == '"' { 1074 v = append(v, cs[cursor:i]...) 1075 break 1076 } 1077 if c != '\\' { 1078 i++ 1079 continue 1080 } 1081 v = append(v, cs[cursor:i]...) 1082 i++ 1083 c = cs[i] 1084 switch c { 1085 case '"', '\\', '/', '\'': 1086 v = append(v, c) 1087 case 'b': 1088 v = append(v, '\b') 1089 case 'f': 1090 v = append(v, '\f') 1091 case 'n': 1092 v = append(v, '\n') 1093 case 'r': 1094 v = append(v, '\r') 1095 case 't': 1096 v = append(v, '\t') 1097 case 'u': 1098 var r rune 1099 var rr uint32 1100 if cslen < i+4 { 1101 d.d.errorf("need at least 4 more bytes for unicode sequence") 1102 } 1103 var j uint 1104 for _, c = range cs[i+1 : i+5] { // bounds-check-elimination 1105 // best to use explicit if-else 1106 // - not a table, etc which involve memory loads, array lookup with bounds checks, etc 1107 if c >= '0' && c <= '9' { 1108 rr = rr*16 + uint32(c-jsonU4Chk2) 1109 } else if c >= 'a' && c <= 'f' { 1110 rr = rr*16 + uint32(c-jsonU4Chk1) 1111 } else if c >= 'A' && c <= 'F' { 1112 rr = rr*16 + uint32(c-jsonU4Chk0) 1113 } else { 1114 r = unicode.ReplacementChar 1115 i += 4 1116 goto encode_rune 1117 } 1118 } 1119 r = rune(rr) 1120 i += 4 1121 if utf16.IsSurrogate(r) { 1122 if len(cs) >= int(i+6) { 1123 var cx = cs[i+1:][:6:6] // [:6] affords bounds-check-elimination 1124 if cx[0] == '\\' && cx[1] == 'u' { 1125 i += 2 1126 var rr1 uint32 1127 for j = 2; j < 6; j++ { 1128 c = cx[j] 1129 if c >= '0' && c <= '9' { 1130 rr = rr*16 + uint32(c-jsonU4Chk2) 1131 } else if c >= 'a' && c <= 'f' { 1132 rr = rr*16 + uint32(c-jsonU4Chk1) 1133 } else if c >= 'A' && c <= 'F' { 1134 rr = rr*16 + uint32(c-jsonU4Chk0) 1135 } else { 1136 r = unicode.ReplacementChar 1137 i += 4 1138 goto encode_rune 1139 } 1140 } 1141 r = utf16.DecodeRune(r, rune(rr1)) 1142 i += 4 1143 goto encode_rune 1144 } 1145 } 1146 r = unicode.ReplacementChar 1147 } 1148 encode_rune: 1149 w2 := utf8.EncodeRune(d.bstr[:], r) 1150 v = append(v, d.bstr[:w2]...) 1151 default: 1152 d.d.errorf("unsupported escaped value: %c", c) 1153 } 1154 i++ 1155 cursor = i 1156 } 1157 d.bs = v 1158} 1159 1160func (d *jsonDecDriver) nakedNum(z *decNaked, bs []byte) (err error) { 1161 const cutoff = uint64(1 << uint(64-1)) 1162 1163 var n uint64 1164 var neg, badsyntax, overflow bool 1165 1166 if len(bs) == 0 { 1167 if d.h.PreferFloat { 1168 z.v = valueTypeFloat 1169 z.f = 0 1170 } else if d.h.SignedInteger { 1171 z.v = valueTypeInt 1172 z.i = 0 1173 } else { 1174 z.v = valueTypeUint 1175 z.u = 0 1176 } 1177 return 1178 } 1179 if d.h.PreferFloat { 1180 goto F 1181 } 1182 n, neg, badsyntax, overflow = jsonParseInteger(bs) 1183 if badsyntax || overflow { 1184 goto F 1185 } 1186 if neg { 1187 if n > cutoff { 1188 goto F 1189 } 1190 z.v = valueTypeInt 1191 z.i = -(int64(n)) 1192 } else if d.h.SignedInteger { 1193 if n >= cutoff { 1194 goto F 1195 } 1196 z.v = valueTypeInt 1197 z.i = int64(n) 1198 } else { 1199 z.v = valueTypeUint 1200 z.u = n 1201 } 1202 return 1203F: 1204 z.v = valueTypeFloat 1205 z.f, err = strconv.ParseFloat(stringView(bs), 64) 1206 return 1207} 1208 1209func (d *jsonDecDriver) bsToString() string { 1210 // if x := d.s.sc; x != nil && x.so && x.st == '}' { // map key 1211 if jsonAlwaysReturnInternString || d.c == containerMapKey { 1212 return d.d.string(d.bs) 1213 } 1214 return string(d.bs) 1215} 1216 1217func (d *jsonDecDriver) DecodeNaked() { 1218 z := d.d.naked() 1219 // var decodeFurther bool 1220 1221 if d.tok == 0 { 1222 d.tok = d.r.skip(&jsonCharWhitespaceSet) 1223 } 1224 switch d.tok { 1225 case 'n': 1226 d.readLit4Null() 1227 z.v = valueTypeNil 1228 case 'f': 1229 d.readLit4False() 1230 z.v = valueTypeBool 1231 z.b = false 1232 case 't': 1233 d.readLit4True() 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 nil, bool or number first 1242 d.appendStringAsBytes() 1243 if len(d.bs) > 0 && d.c == containerMapKey && d.h.MapKeyAsString { 1244 switch stringView(d.bs) { 1245 case "null": 1246 z.v = valueTypeNil 1247 case "true": 1248 z.v = valueTypeBool 1249 z.b = true 1250 case "false": 1251 z.v = valueTypeBool 1252 z.b = false 1253 default: 1254 // check if a number: float, int or uint 1255 if err := d.nakedNum(z, d.bs); err != nil { 1256 z.v = valueTypeString 1257 z.s = d.bsToString() 1258 } 1259 } 1260 } else { 1261 z.v = valueTypeString 1262 z.s = d.bsToString() 1263 } 1264 default: // number 1265 bs := d.decNumBytes() 1266 if len(bs) == 0 { 1267 d.d.errorf("decode number from empty string") 1268 return 1269 } 1270 if err := d.nakedNum(z, bs); err != nil { 1271 d.d.errorf("decode number from %s: %v", bs, err) 1272 return 1273 } 1274 } 1275 // if decodeFurther { 1276 // d.s.sc.retryRead() 1277 // } 1278} 1279 1280//---------------------- 1281 1282// JsonHandle is a handle for JSON encoding format. 1283// 1284// Json is comprehensively supported: 1285// - decodes numbers into interface{} as int, uint or float64 1286// based on how the number looks and some config parameters e.g. PreferFloat, SignedInt, etc. 1287// - decode integers from float formatted numbers e.g. 1.27e+8 1288// - decode any json value (numbers, bool, etc) from quoted strings 1289// - configurable way to encode/decode []byte . 1290// by default, encodes and decodes []byte using base64 Std Encoding 1291// - UTF-8 support for encoding and decoding 1292// 1293// It has better performance than the json library in the standard library, 1294// by leveraging the performance improvements of the codec library. 1295// 1296// In addition, it doesn't read more bytes than necessary during a decode, which allows 1297// reading multiple values from a stream containing json and non-json content. 1298// For example, a user can read a json value, then a cbor value, then a msgpack value, 1299// all from the same stream in sequence. 1300// 1301// Note that, when decoding quoted strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are 1302// not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD. 1303type JsonHandle struct { 1304 textEncodingType 1305 BasicHandle 1306 1307 // Indent indicates how a value is encoded. 1308 // - If positive, indent by that number of spaces. 1309 // - If negative, indent by that number of tabs. 1310 Indent int8 1311 1312 // IntegerAsString controls how integers (signed and unsigned) are encoded. 1313 // 1314 // Per the JSON Spec, JSON numbers are 64-bit floating point numbers. 1315 // Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision. 1316 // This can be mitigated by configuring how to encode integers. 1317 // 1318 // IntegerAsString interpretes the following values: 1319 // - if 'L', then encode integers > 2^53 as a json string. 1320 // - if 'A', then encode all integers as a json string 1321 // containing the exact integer representation as a decimal. 1322 // - else encode all integers as a json number (default) 1323 IntegerAsString byte 1324 1325 // HTMLCharsAsIs controls how to encode some special characters to html: < > & 1326 // 1327 // By default, we encode them as \uXXX 1328 // to prevent security holes when served from some browsers. 1329 HTMLCharsAsIs bool 1330 1331 // PreferFloat says that we will default to decoding a number as a float. 1332 // If not set, we will examine the characters of the number and decode as an 1333 // integer type if it doesn't have any of the characters [.eE]. 1334 PreferFloat bool 1335 1336 // TermWhitespace says that we add a whitespace character 1337 // at the end of an encoding. 1338 // 1339 // The whitespace is important, especially if using numbers in a context 1340 // where multiple items are written to a stream. 1341 TermWhitespace bool 1342 1343 // MapKeyAsString says to encode all map keys as strings. 1344 // 1345 // Use this to enforce strict json output. 1346 // The only caveat is that nil value is ALWAYS written as null (never as "null") 1347 MapKeyAsString bool 1348 1349 // _ [2]byte // padding 1350 1351 // Note: below, we store hardly-used items e.g. RawBytesExt is cached in the (en|de)cDriver. 1352 1353 // RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way. 1354 // If not configured, raw bytes are encoded to/from base64 text. 1355 RawBytesExt InterfaceExt 1356 1357 _ [2]uint64 // padding 1358} 1359 1360// Name returns the name of the handle: json 1361func (h *JsonHandle) Name() string { return "json" } 1362func (h *JsonHandle) hasElemSeparators() bool { return true } 1363func (h *JsonHandle) typical() bool { 1364 return h.Indent == 0 && !h.MapKeyAsString && h.IntegerAsString != 'A' && h.IntegerAsString != 'L' 1365} 1366 1367type jsonTypical interface { 1368 typical() 1369} 1370 1371func (h *JsonHandle) recreateEncDriver(ed encDriver) (v bool) { 1372 _, v = ed.(jsonTypical) 1373 return v != h.typical() 1374} 1375 1376// SetInterfaceExt sets an extension 1377func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) { 1378 return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext}) 1379} 1380 1381func (h *JsonHandle) newEncDriver(e *Encoder) (ee encDriver) { 1382 var hd *jsonEncDriver 1383 if h.typical() { 1384 var v jsonEncDriverTypical 1385 ee = &v 1386 hd = &v.jsonEncDriver 1387 } else { 1388 var v jsonEncDriverGeneric 1389 ee = &v 1390 hd = &v.jsonEncDriver 1391 } 1392 hd.e, hd.h, hd.bs = e, h, hd.b[:0] 1393 hd.se.BytesExt = bytesExtFailer{} 1394 ee.reset() 1395 return 1396} 1397 1398func (h *JsonHandle) newDecDriver(d *Decoder) decDriver { 1399 // d := jsonDecDriver{r: r.(*bytesDecReader), h: h} 1400 hd := jsonDecDriver{d: d, h: h} 1401 hd.se.BytesExt = bytesExtFailer{} 1402 hd.bs = hd.b[:0] 1403 hd.reset() 1404 return &hd 1405} 1406 1407func (e *jsonEncDriver) reset() { 1408 e.w = e.e.w 1409 e.se.InterfaceExt = e.h.RawBytesExt 1410 if e.bs != nil { 1411 e.bs = e.bs[:0] 1412 } 1413 e.c = 0 1414} 1415 1416func (d *jsonDecDriver) reset() { 1417 d.r = d.d.r 1418 d.se.InterfaceExt = d.h.RawBytesExt 1419 if d.bs != nil { 1420 d.bs = d.bs[:0] 1421 } 1422 d.c, d.tok = 0, 0 1423 // d.n.reset() 1424} 1425 1426func jsonFloatStrconvFmtPrec(f float64) (fmt byte, prec int) { 1427 prec = -1 1428 var abs = math.Abs(f) 1429 if abs != 0 && (abs < 1e-6 || abs >= 1e21) { 1430 fmt = 'e' 1431 } else { 1432 fmt = 'f' 1433 // set prec to 1 iff mod is 0. 1434 // better than using jsonIsFloatBytesB2 to check if a . or E in the float bytes. 1435 // this ensures that every float has an e or .0 in it. 1436 if abs <= 1 { 1437 if abs == 0 || abs == 1 { 1438 prec = 1 1439 } 1440 } else if _, mod := math.Modf(abs); mod == 0 { 1441 prec = 1 1442 } 1443 } 1444 return 1445} 1446 1447// custom-fitted version of strconv.Parse(Ui|I)nt. 1448// Also ensures we don't have to search for .eE to determine if a float or not. 1449// Note: s CANNOT be a zero-length slice. 1450func jsonParseInteger(s []byte) (n uint64, neg, badSyntax, overflow bool) { 1451 const maxUint64 = (1<<64 - 1) 1452 const cutoff = maxUint64/10 + 1 1453 1454 if len(s) == 0 { // bounds-check-elimination 1455 // treat empty string as zero value 1456 // badSyntax = true 1457 return 1458 } 1459 switch s[0] { 1460 case '+': 1461 s = s[1:] 1462 case '-': 1463 s = s[1:] 1464 neg = true 1465 } 1466 for _, c := range s { 1467 if c < '0' || c > '9' { 1468 badSyntax = true 1469 return 1470 } 1471 // unsigned integers don't overflow well on multiplication, so check cutoff here 1472 // e.g. (maxUint64-5)*10 doesn't overflow well ... 1473 if n >= cutoff { 1474 overflow = true 1475 return 1476 } 1477 n *= 10 1478 n1 := n + uint64(c-'0') 1479 if n1 < n || n1 > maxUint64 { 1480 overflow = true 1481 return 1482 } 1483 n = n1 1484 } 1485 return 1486} 1487 1488var _ decDriver = (*jsonDecDriver)(nil) 1489var _ encDriver = (*jsonEncDriverGeneric)(nil) 1490var _ encDriver = (*jsonEncDriverTypical)(nil) 1491var _ jsonTypical = (*jsonEncDriverTypical)(nil) 1492