json.go (37225B)
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 type JsonHandle struct { 1305 textEncodingType 1306 BasicHandle 1307 1308 // Indent indicates how a value is encoded. 1309 // - If positive, indent by that number of spaces. 1310 // - If negative, indent by that number of tabs. 1311 Indent int8 1312 1313 // IntegerAsString controls how integers (signed and unsigned) are encoded. 1314 // 1315 // Per the JSON Spec, JSON numbers are 64-bit floating point numbers. 1316 // Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision. 1317 // This can be mitigated by configuring how to encode integers. 1318 // 1319 // IntegerAsString interpretes the following values: 1320 // - if 'L', then encode integers > 2^53 as a json string. 1321 // - if 'A', then encode all integers as a json string 1322 // containing the exact integer representation as a decimal. 1323 // - else encode all integers as a json number (default) 1324 IntegerAsString byte 1325 1326 // HTMLCharsAsIs controls how to encode some special characters to html: < > & 1327 // 1328 // By default, we encode them as \uXXX 1329 // to prevent security holes when served from some browsers. 1330 HTMLCharsAsIs bool 1331 1332 // PreferFloat says that we will default to decoding a number as a float. 1333 // If not set, we will examine the characters of the number and decode as an 1334 // integer type if it doesn't have any of the characters [.eE]. 1335 PreferFloat bool 1336 1337 // TermWhitespace says that we add a whitespace character 1338 // at the end of an encoding. 1339 // 1340 // The whitespace is important, especially if using numbers in a context 1341 // where multiple items are written to a stream. 1342 TermWhitespace bool 1343 1344 // MapKeyAsString says to encode all map keys as strings. 1345 // 1346 // Use this to enforce strict json output. 1347 // The only caveat is that nil value is ALWAYS written as null (never as "null") 1348 MapKeyAsString bool 1349 1350 // _ uint64 // padding (cache line) 1351 1352 // Note: below, we store hardly-used items e.g. RawBytesExt. 1353 // These values below may straddle a cache line, but they are hardly-used, 1354 // so shouldn't contribute to false-sharing except in rare cases. 1355 1356 // RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way. 1357 // If not configured, raw bytes are encoded to/from base64 text. 1358 RawBytesExt InterfaceExt 1359 } 1360 1361 func (h *JsonHandle) isJson() bool { return true } 1362 1363 // Name returns the name of the handle: json 1364 func (h *JsonHandle) Name() string { return "json" } 1365 1366 func (h *JsonHandle) desc(bd byte) string { return string(bd) } 1367 1368 func (h *JsonHandle) typical() bool { 1369 return h.Indent == 0 && !h.MapKeyAsString && h.IntegerAsString != 'A' && h.IntegerAsString != 'L' 1370 } 1371 1372 func (h *JsonHandle) newEncDriver() encDriver { 1373 var e = &jsonEncDriver{h: h} 1374 // var x []byte 1375 // e.buf = &x 1376 e.e.e = e 1377 e.e.js = true 1378 e.e.init(h) 1379 e.reset() 1380 return e 1381 } 1382 1383 func (h *JsonHandle) newDecDriver() decDriver { 1384 var d = &jsonDecDriver{h: h} 1385 var x []byte 1386 d.buf = &x 1387 d.d.d = d 1388 d.d.js = true 1389 d.d.jsms = h.MapKeyAsString 1390 d.d.init(h) 1391 d.reset() 1392 return d 1393 } 1394 1395 func (e *jsonEncDriver) resetState() { 1396 e.dl = 0 1397 } 1398 1399 func (e *jsonEncDriver) reset() { 1400 e.resetState() 1401 // (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) 1402 // cache values from the handle 1403 e.typical = e.h.typical() 1404 if e.h.HTMLCharsAsIs { 1405 e.s = &jsonCharSafeSet 1406 } else { 1407 e.s = &jsonCharHtmlSafeSet 1408 } 1409 e.rawext = e.h.RawBytesExt != nil 1410 e.di = int8(e.h.Indent) 1411 e.d = e.h.Indent != 0 1412 e.ks = e.h.MapKeyAsString 1413 e.is = e.h.IntegerAsString 1414 } 1415 1416 func (d *jsonDecDriver) resetState() { 1417 *d.buf = d.d.blist.check(*d.buf, 256) 1418 d.tok = 0 1419 } 1420 1421 func (d *jsonDecDriver) reset() { 1422 d.resetState() 1423 d.rawext = d.h.RawBytesExt != nil 1424 } 1425 1426 func jsonFloatStrconvFmtPrec64(f float64) (fmt byte, prec int8) { 1427 fmt = 'f' 1428 prec = -1 1429 fbits := math.Float64bits(f) 1430 abs := math.Float64frombits(fbits &^ (1 << 63)) 1431 if abs == 0 || abs == 1 { 1432 prec = 1 1433 } else if abs < 1e-6 || abs >= 1e21 { 1434 fmt = 'e' 1435 } else if noFrac64(fbits) { 1436 prec = 1 1437 } 1438 return 1439 } 1440 1441 func jsonFloatStrconvFmtPrec32(f float32) (fmt byte, prec int8) { 1442 fmt = 'f' 1443 prec = -1 1444 // directly handle Modf (to get fractions) and Abs (to get absolute) 1445 fbits := math.Float32bits(f) 1446 abs := math.Float32frombits(fbits &^ (1 << 31)) 1447 if abs == 0 || abs == 1 { 1448 prec = 1 1449 } else if abs < 1e-6 || abs >= 1e21 { 1450 fmt = 'e' 1451 } else if noFrac32(fbits) { 1452 prec = 1 1453 } 1454 return 1455 } 1456 1457 var _ decDriverContainerTracker = (*jsonDecDriver)(nil) 1458 var _ encDriverContainerTracker = (*jsonEncDriver)(nil) 1459 var _ decDriver = (*jsonDecDriver)(nil) 1460 var _ encDriver = (*jsonEncDriver)(nil)