github.com/patricebensoussan/go/codec@v1.2.99/json.go (about) 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 "bytes" 21 "encoding/base64" 22 "math" 23 "reflect" 24 "strconv" 25 "time" 26 "unicode" 27 "unicode/utf16" 28 "unicode/utf8" 29 ) 30 31 //-------------------------------- 32 33 var jsonLiterals = [...]byte{ 34 '"', 't', 'r', 'u', 'e', '"', 35 '"', 'f', 'a', 'l', 's', 'e', '"', 36 '"', 'n', 'u', 'l', 'l', '"', 37 } 38 39 const ( 40 jsonLitTrueQ = 0 41 jsonLitTrue = 1 42 jsonLitFalseQ = 6 43 jsonLitFalse = 7 44 jsonLitNullQ = 13 45 jsonLitNull = 14 46 ) 47 48 var ( 49 // jsonLiteralTrueQ = jsonLiterals[jsonLitTrueQ : jsonLitTrueQ+6] 50 // jsonLiteralFalseQ = jsonLiterals[jsonLitFalseQ : jsonLitFalseQ+7] 51 // jsonLiteralNullQ = jsonLiterals[jsonLitNullQ : jsonLitNullQ+6] 52 53 jsonLiteralTrue = jsonLiterals[jsonLitTrue : jsonLitTrue+4] 54 jsonLiteralFalse = jsonLiterals[jsonLitFalse : jsonLitFalse+5] 55 jsonLiteralNull = jsonLiterals[jsonLitNull : jsonLitNull+4] 56 57 // these are used, after consuming the first char 58 jsonLiteral4True = jsonLiterals[jsonLitTrue+1 : jsonLitTrue+4] 59 jsonLiteral4False = jsonLiterals[jsonLitFalse+1 : jsonLitFalse+5] 60 jsonLiteral4Null = jsonLiterals[jsonLitNull+1 : jsonLitNull+4] 61 ) 62 63 const ( 64 jsonU4Chk2 = '0' 65 jsonU4Chk1 = 'a' - 10 66 jsonU4Chk0 = 'A' - 10 67 ) 68 69 const ( 70 // If !jsonValidateSymbols, decoding will be faster, by skipping some checks: 71 // - If we see first character of null, false or true, 72 // do not validate subsequent characters. 73 // - e.g. if we see a n, assume null and skip next 3 characters, 74 // and do not validate they are ull. 75 // P.S. Do not expect a significant decoding boost from this. 76 jsonValidateSymbols = true 77 78 // jsonEscapeMultiByteUnicodeSep controls whether some unicode characters 79 // that are valid json but may bomb in some contexts are escaped during encoeing. 80 // 81 // U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR. 82 // Both technically valid JSON, but bomb on JSONP, so fix here unconditionally. 83 jsonEscapeMultiByteUnicodeSep = true 84 85 // jsonManualInlineDecRdInHotZones controls whether we manually inline some decReader calls. 86 // 87 // encode performance is at par with libraries that just iterate over bytes directly, 88 // because encWr (with inlined bytesEncAppender calls) is inlined. 89 // Conversely, decode performance suffers because decRd (with inlined bytesDecReader calls) 90 // isn't inlinable. 91 // 92 // To improve decode performamnce from json: 93 // - readn1 is only called for \u 94 // - consequently, to optimize json decoding, we specifically need inlining 95 // for bytes use-case of some other decReader methods: 96 // - jsonReadAsisChars, skipWhitespace (advance) and jsonReadNum 97 // - AND THEN readn3, readn4 (for ull, rue and alse). 98 // - (readn1 is only called when a char is escaped). 99 // - without inlining, we still pay the cost of a method invocationK, and this dominates time 100 // - To mitigate, we manually inline in hot zones 101 // *excluding places where used sparingly (e.g. nextValueBytes, and other atypical cases)*. 102 // - jsonReadAsisChars *only* called in: appendStringAsBytes 103 // - advance called: everywhere 104 // - jsonReadNum: decNumBytes, DecodeNaked 105 // - From running go test (our anecdotal findings): 106 // - calling jsonReadAsisChars in appendStringAsBytes: 23431 107 // - calling jsonReadNum in decNumBytes: 15251 108 // - calling jsonReadNum in DecodeNaked: 612 109 // Consequently, we manually inline jsonReadAsisChars (in appendStringAsBytes) 110 // and jsonReadNum (in decNumbytes) 111 jsonManualInlineDecRdInHotZones = true 112 113 jsonSpacesOrTabsLen = 128 114 115 // jsonAlwaysReturnInternString = false 116 ) 117 118 var ( 119 // jsonTabs and jsonSpaces are used as caches for indents 120 jsonTabs, jsonSpaces [jsonSpacesOrTabsLen]byte 121 122 jsonCharHtmlSafeSet bitset256 123 jsonCharSafeSet bitset256 124 ) 125 126 func init() { 127 var i byte 128 for i = 0; i < jsonSpacesOrTabsLen; i++ { 129 jsonSpaces[i] = ' ' 130 jsonTabs[i] = '\t' 131 } 132 133 // populate the safe values as true: note: ASCII control characters are (0-31) 134 // jsonCharSafeSet: all true except (0-31) " \ 135 // jsonCharHtmlSafeSet: all true except (0-31) " \ < > & 136 for i = 32; i < utf8.RuneSelf; i++ { 137 switch i { 138 case '"', '\\': 139 case '<', '>', '&': 140 jsonCharSafeSet.set(i) // = true 141 default: 142 jsonCharSafeSet.set(i) 143 jsonCharHtmlSafeSet.set(i) 144 } 145 } 146 } 147 148 // ---------------- 149 150 type jsonEncState struct { 151 di int8 // indent per: if negative, use tabs 152 d bool // indenting? 153 dl uint16 // indent level 154 } 155 156 func (x jsonEncState) captureState() interface{} { return x } 157 func (x *jsonEncState) restoreState(v interface{}) { *x = v.(jsonEncState) } 158 159 type jsonEncDriver struct { 160 noBuiltInTypes 161 h *JsonHandle 162 163 // se interfaceExtWrapper 164 165 // ---- cpu cache line boundary? 166 jsonEncState 167 168 ks bool // map key as string 169 is byte // integer as string 170 171 typical bool 172 rawext bool // rawext configured on the handle 173 174 s *bitset256 // safe set for characters (taking h.HTMLAsIs into consideration) 175 176 // buf *[]byte // used mostly for encoding []byte 177 178 // scratch buffer for: encode time, numbers, etc 179 // 180 // RFC3339Nano uses 35 chars: 2006-01-02T15:04:05.999999999Z07:00 181 // MaxUint64 uses 20 chars: 18446744073709551615 182 // floats are encoded using: f/e fmt, and -1 precision, or 1 if no fractions. 183 // This means we are limited by the number of characters for the 184 // mantissa (up to 17), exponent (up to 3), signs (up to 3), dot (up to 1), E (up to 1) 185 // for a total of 24 characters. 186 // -xxx.yyyyyyyyyyyye-zzz 187 // Consequently, 35 characters should be sufficient for encoding time, integers or floats. 188 // We use up all the remaining bytes to make this use full cache lines. 189 b [56]byte 190 191 e Encoder 192 } 193 194 func (e *jsonEncDriver) encoder() *Encoder { return &e.e } 195 196 func (e *jsonEncDriver) writeIndent() { 197 e.e.encWr.writen1('\n') 198 x := int(e.di) * int(e.dl) 199 if e.di < 0 { 200 x = -x 201 for x > jsonSpacesOrTabsLen { 202 e.e.encWr.writeb(jsonTabs[:]) 203 x -= jsonSpacesOrTabsLen 204 } 205 e.e.encWr.writeb(jsonTabs[:x]) 206 } else { 207 for x > jsonSpacesOrTabsLen { 208 e.e.encWr.writeb(jsonSpaces[:]) 209 x -= jsonSpacesOrTabsLen 210 } 211 e.e.encWr.writeb(jsonSpaces[:x]) 212 } 213 } 214 215 func (e *jsonEncDriver) WriteArrayElem() { 216 if e.e.c != containerArrayStart { 217 e.e.encWr.writen1(',') 218 } 219 if e.d { 220 e.writeIndent() 221 } 222 } 223 224 func (e *jsonEncDriver) WriteMapElemKey() { 225 if e.e.c != containerMapStart { 226 e.e.encWr.writen1(',') 227 } 228 if e.d { 229 e.writeIndent() 230 } 231 } 232 233 func (e *jsonEncDriver) WriteMapElemValue() { 234 if e.d { 235 e.e.encWr.writen2(':', ' ') 236 } else { 237 e.e.encWr.writen1(':') 238 } 239 } 240 241 func (e *jsonEncDriver) EncodeNil() { 242 // We always encode nil as just null (never in quotes) 243 // This allows us to easily decode if a nil in the json stream 244 // ie if initial token is n. 245 246 // e.e.encWr.writeb(jsonLiteralNull) 247 e.e.encWr.writen4([4]byte{'n', 'u', 'l', 'l'}) 248 } 249 250 func (e *jsonEncDriver) EncodeTime(t time.Time) { 251 // Do NOT use MarshalJSON, as it allocates internally. 252 // instead, we call AppendFormat directly, using our scratch buffer (e.b) 253 254 if t.IsZero() { 255 e.EncodeNil() 256 } else { 257 e.b[0] = '"' 258 b := fmtTime(t, time.RFC3339Nano, e.b[1:1]) 259 e.b[len(b)+1] = '"' 260 e.e.encWr.writeb(e.b[:len(b)+2]) 261 } 262 } 263 264 func (e *jsonEncDriver) EncodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) { 265 if ext == SelfExt { 266 e.e.encodeValue(baseRV(rv), e.h.fnNoExt(basetype)) 267 } else if v := ext.ConvertExt(rv); v == nil { 268 e.EncodeNil() 269 } else { 270 e.e.encode(v) 271 } 272 } 273 274 func (e *jsonEncDriver) EncodeRawExt(re *RawExt) { 275 // only encodes re.Value (never re.Data) 276 if re.Value == nil { 277 e.EncodeNil() 278 } else { 279 e.e.encode(re.Value) 280 } 281 } 282 283 func (e *jsonEncDriver) EncodeBool(b bool) { 284 // Use writen with an array instead of writeb with a slice 285 // i.e. in place of e.e.encWr.writeb(jsonLiteralTrueQ) 286 // OR jsonLiteralTrue, jsonLiteralFalse, jsonLiteralFalseQ, etc 287 288 if e.ks && e.e.c == containerMapKey { 289 if b { 290 e.e.encWr.writen4([4]byte{'"', 't', 'r', 'u'}) 291 e.e.encWr.writen2('e', '"') 292 } else { 293 e.e.encWr.writen4([4]byte{'"', 'f', 'a', 'l'}) 294 e.e.encWr.writen2('s', 'e') 295 e.e.encWr.writen1('"') 296 } 297 } else { 298 if b { 299 e.e.encWr.writen4([4]byte{'t', 'r', 'u', 'e'}) 300 } else { 301 e.e.encWr.writen4([4]byte{'f', 'a', 'l', 's'}) 302 e.e.encWr.writen1('e') 303 } 304 } 305 } 306 307 func (e *jsonEncDriver) encodeFloat(f float64, bitsize, fmt byte, prec int8) { 308 var blen uint 309 if e.ks && e.e.c == containerMapKey { 310 blen = 2 + uint(len(strconv.AppendFloat(e.b[1:1], f, fmt, int(prec), int(bitsize)))) 311 // _ = e.b[:blen] 312 e.b[0] = '"' 313 e.b[blen-1] = '"' 314 e.e.encWr.writeb(e.b[:blen]) 315 } else { 316 e.e.encWr.writeb(strconv.AppendFloat(e.b[:0], f, fmt, int(prec), int(bitsize))) 317 } 318 } 319 320 func (e *jsonEncDriver) EncodeFloat64(f float64) { 321 if math.IsNaN(f) || math.IsInf(f, 0) { 322 e.EncodeNil() 323 return 324 } 325 fmt, prec := jsonFloatStrconvFmtPrec64(f) 326 e.encodeFloat(f, 64, fmt, prec) 327 } 328 329 func (e *jsonEncDriver) EncodeFloat32(f float32) { 330 if math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) { 331 e.EncodeNil() 332 return 333 } 334 fmt, prec := jsonFloatStrconvFmtPrec32(f) 335 e.encodeFloat(float64(f), 32, fmt, prec) 336 } 337 338 func (e *jsonEncDriver) encodeUint(neg bool, quotes bool, u uint64) { 339 // copied mostly from std library: strconv 340 // this should only be called on 64bit OS. 341 342 const smallsString = "00010203040506070809" + 343 "10111213141516171819" + 344 "20212223242526272829" + 345 "30313233343536373839" + 346 "40414243444546474849" + 347 "50515253545556575859" + 348 "60616263646566676869" + 349 "70717273747576777879" + 350 "80818283848586878889" + 351 "90919293949596979899" 352 353 // typically, 19 or 20 bytes sufficient for decimal encoding a uint64 354 // var a [24]byte 355 var a = e.b[0:24] 356 var i = uint8(len(a)) 357 358 if quotes { 359 i-- 360 a[i] = '"' 361 } 362 // u guaranteed to fit into a uint (as we are not 32bit OS) 363 var is uint 364 var us = uint(u) 365 for us >= 100 { 366 is = us % 100 * 2 367 us /= 100 368 i -= 2 369 a[i+1] = smallsString[is+1] 370 a[i+0] = smallsString[is+0] 371 } 372 373 // us < 100 374 is = us * 2 375 i-- 376 a[i] = smallsString[is+1] 377 if us >= 10 { 378 i-- 379 a[i] = smallsString[is] 380 } 381 if neg { 382 i-- 383 a[i] = '-' 384 } 385 if quotes { 386 i-- 387 a[i] = '"' 388 } 389 e.e.encWr.writeb(a[i:]) 390 } 391 392 func (e *jsonEncDriver) EncodeInt(v int64) { 393 quotes := e.is == 'A' || e.is == 'L' && (v > 1<<53 || v < -(1<<53)) || 394 (e.ks && e.e.c == containerMapKey) 395 396 if cpu32Bit { 397 if quotes { 398 blen := 2 + len(strconv.AppendInt(e.b[1:1], v, 10)) 399 e.b[0] = '"' 400 e.b[blen-1] = '"' 401 e.e.encWr.writeb(e.b[:blen]) 402 } else { 403 e.e.encWr.writeb(strconv.AppendInt(e.b[:0], v, 10)) 404 } 405 return 406 } 407 408 if v < 0 { 409 e.encodeUint(true, quotes, uint64(-v)) 410 } else { 411 e.encodeUint(false, quotes, uint64(v)) 412 } 413 } 414 415 func (e *jsonEncDriver) EncodeUint(v uint64) { 416 quotes := e.is == 'A' || e.is == 'L' && v > 1<<53 || (e.ks && e.e.c == containerMapKey) 417 418 if cpu32Bit { 419 // use strconv directly, as optimized encodeUint only works on 64-bit alone 420 if quotes { 421 blen := 2 + len(strconv.AppendUint(e.b[1:1], v, 10)) 422 e.b[0] = '"' 423 e.b[blen-1] = '"' 424 e.e.encWr.writeb(e.b[:blen]) 425 } else { 426 e.e.encWr.writeb(strconv.AppendUint(e.b[:0], v, 10)) 427 } 428 return 429 } 430 431 e.encodeUint(false, quotes, v) 432 } 433 434 func (e *jsonEncDriver) EncodeString(v string) { 435 if e.h.StringToRaw { 436 e.EncodeStringBytesRaw(bytesView(v)) 437 return 438 } 439 e.quoteStr(v) 440 } 441 442 func (e *jsonEncDriver) EncodeStringBytesRaw(v []byte) { 443 // if encoding raw bytes and RawBytesExt is configured, use it to encode 444 if v == nil { 445 e.EncodeNil() 446 return 447 } 448 449 if e.rawext { 450 iv := e.h.RawBytesExt.ConvertExt(v) 451 if iv == nil { 452 e.EncodeNil() 453 } else { 454 e.e.encode(iv) 455 } 456 return 457 } 458 459 slen := base64.StdEncoding.EncodedLen(len(v)) + 2 460 461 // bs := e.e.blist.check(*e.buf, n)[:slen] 462 // *e.buf = bs 463 464 bs := e.e.blist.peek(slen, false)[:slen] 465 466 bs[0] = '"' 467 base64.StdEncoding.Encode(bs[1:], v) 468 bs[len(bs)-1] = '"' 469 e.e.encWr.writeb(bs) 470 } 471 472 // indent is done as below: 473 // - newline and indent are added before each mapKey or arrayElem 474 // - newline and indent are added before each ending, 475 // except there was no entry (so we can have {} or []) 476 477 func (e *jsonEncDriver) WriteArrayStart(length int) { 478 if e.d { 479 e.dl++ 480 } 481 e.e.encWr.writen1('[') 482 } 483 484 func (e *jsonEncDriver) WriteArrayEnd() { 485 if e.d { 486 e.dl-- 487 e.writeIndent() 488 } 489 e.e.encWr.writen1(']') 490 } 491 492 func (e *jsonEncDriver) WriteMapStart(length int) { 493 if e.d { 494 e.dl++ 495 } 496 e.e.encWr.writen1('{') 497 } 498 499 func (e *jsonEncDriver) WriteMapEnd() { 500 if e.d { 501 e.dl-- 502 if e.e.c != containerMapStart { 503 e.writeIndent() 504 } 505 } 506 e.e.encWr.writen1('}') 507 } 508 509 func (e *jsonEncDriver) quoteStr(s string) { 510 // adapted from std pkg encoding/json 511 const hex = "0123456789abcdef" 512 w := e.e.w() 513 w.writen1('"') 514 var i, start uint 515 for i < uint(len(s)) { 516 // encode all bytes < 0x20 (except \r, \n). 517 // also encode < > & to prevent security holes when served to some browsers. 518 519 // We optimize for ascii, by assumining that most characters are in the BMP 520 // and natively consumed by json without much computation. 521 522 // if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { 523 // if (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) { 524 if e.s.isset(s[i]) { 525 i++ 526 continue 527 } 528 // b := s[i] 529 if s[i] < utf8.RuneSelf { 530 if start < i { 531 w.writestr(s[start:i]) 532 } 533 switch s[i] { 534 case '\\', '"': 535 w.writen2('\\', s[i]) 536 case '\n': 537 w.writen2('\\', 'n') 538 case '\r': 539 w.writen2('\\', 'r') 540 case '\b': 541 w.writen2('\\', 'b') 542 case '\f': 543 w.writen2('\\', 'f') 544 case '\t': 545 w.writen2('\\', 't') 546 default: 547 w.writestr(`\u00`) 548 w.writen2(hex[s[i]>>4], hex[s[i]&0xF]) 549 } 550 i++ 551 start = i 552 continue 553 } 554 c, size := utf8.DecodeRuneInString(s[i:]) 555 if c == utf8.RuneError && size == 1 { // meaning invalid encoding (so output as-is) 556 if start < i { 557 w.writestr(s[start:i]) 558 } 559 w.writestr(`\uFFFD`) 560 i++ 561 start = i 562 continue 563 } 564 // U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR. 565 // Both technically valid JSON, but bomb on JSONP, so fix here *unconditionally*. 566 if jsonEscapeMultiByteUnicodeSep && (c == '\u2028' || c == '\u2029') { 567 if start < i { 568 w.writestr(s[start:i]) 569 } 570 w.writestr(`\u202`) 571 w.writen1(hex[c&0xF]) 572 i += uint(size) 573 start = i 574 continue 575 } 576 i += uint(size) 577 } 578 if start < uint(len(s)) { 579 w.writestr(s[start:]) 580 } 581 w.writen1('"') 582 } 583 584 func (e *jsonEncDriver) atEndOfEncode() { 585 if e.h.TermWhitespace { 586 var c byte = ' ' // default is that scalar is written, so output space 587 if e.e.c != 0 { 588 c = '\n' // for containers (map/list), output a newline 589 } 590 e.e.encWr.writen1(c) 591 } 592 } 593 594 // ---------- 595 596 type jsonDecState struct { 597 rawext bool // rawext configured on the handle 598 599 tok uint8 // used to store the token read right after skipWhiteSpace 600 _ bool // found null 601 _ byte // padding 602 bstr [4]byte // scratch used for string \UXXX parsing 603 604 // scratch buffer used for base64 decoding (DecodeBytes in reuseBuf mode), 605 // or reading doubleQuoted string (DecodeStringAsBytes, DecodeNaked) 606 buf *[]byte 607 } 608 609 func (x jsonDecState) captureState() interface{} { return x } 610 func (x *jsonDecState) restoreState(v interface{}) { *x = v.(jsonDecState) } 611 612 type jsonDecDriver struct { 613 noBuiltInTypes 614 decDriverNoopNumberHelper 615 h *JsonHandle 616 617 jsonDecState 618 619 // se interfaceExtWrapper 620 621 // ---- cpu cache line boundary? 622 623 d Decoder 624 } 625 626 func (d *jsonDecDriver) descBd() (s string) { panic("descBd unsupported") } 627 628 func (d *jsonDecDriver) decoder() *Decoder { 629 return &d.d 630 } 631 632 func (d *jsonDecDriver) ReadMapStart() int { 633 d.advance() 634 if d.tok == 'n' { 635 d.readLit4Null(d.d.decRd.readn3()) 636 return containerLenNil 637 } 638 if d.tok != '{' { 639 d.d.errorf("read map - expect char '%c' but got char '%c'", '{', d.tok) 640 } 641 d.tok = 0 642 return containerLenUnknown 643 } 644 645 func (d *jsonDecDriver) ReadArrayStart() int { 646 d.advance() 647 if d.tok == 'n' { 648 d.readLit4Null(d.d.decRd.readn3()) 649 return containerLenNil 650 } 651 if d.tok != '[' { 652 d.d.errorf("read array - expect char '%c' but got char '%c'", '[', d.tok) 653 } 654 d.tok = 0 655 return containerLenUnknown 656 } 657 658 func (d *jsonDecDriver) CheckBreak() bool { 659 d.advance() 660 return d.tok == '}' || d.tok == ']' 661 } 662 663 func (d *jsonDecDriver) ReadArrayElem() { 664 const xc uint8 = ',' 665 if d.d.c != containerArrayStart { 666 d.advance() 667 if d.tok != xc { 668 d.readDelimError(xc) 669 } 670 d.tok = 0 671 } 672 } 673 674 func (d *jsonDecDriver) ReadArrayEnd() { 675 const xc uint8 = ']' 676 d.advance() 677 if d.tok != xc { 678 d.readDelimError(xc) 679 } 680 d.tok = 0 681 } 682 683 func (d *jsonDecDriver) ReadMapElemKey() { 684 const xc uint8 = ',' 685 if d.d.c != containerMapStart { 686 d.advance() 687 if d.tok != xc { 688 d.readDelimError(xc) 689 } 690 d.tok = 0 691 } 692 } 693 694 func (d *jsonDecDriver) ReadMapElemValue() { 695 const xc uint8 = ':' 696 d.advance() 697 if d.tok != xc { 698 d.readDelimError(xc) 699 } 700 d.tok = 0 701 } 702 703 func (d *jsonDecDriver) ReadMapEnd() { 704 const xc uint8 = '}' 705 d.advance() 706 if d.tok != xc { 707 d.readDelimError(xc) 708 } 709 d.tok = 0 710 } 711 712 func (d *jsonDecDriver) readDelimError(xc uint8) { 713 d.d.errorf("read json delimiter - expect char '%c' but got char '%c'", xc, d.tok) 714 } 715 716 // MARKER: readLit4XXX takes the readn(3|4) as a parameter so they can be inlined. 717 // We pass the array directly to errorf, as passing slice pushes past inlining threshold, 718 // and passing slice also might cause allocation of the bs array on the heap. 719 720 func (d *jsonDecDriver) readLit4True(bs [4]byte) { 721 // bs := d.d.decRd.readn3() 722 d.tok = 0 723 if jsonValidateSymbols && bs != [...]byte{0, 'r', 'u', 'e'} { // !Equal jsonLiteral4True 724 // d.d.errorf("expecting %s: got %s", jsonLiteral4True, bs[:]) 725 d.d.errorf("expecting true: got t%s", bs) 726 } 727 } 728 729 func (d *jsonDecDriver) readLit4False(bs [4]byte) { 730 // bs := d.d.decRd.readn4() 731 d.tok = 0 732 if jsonValidateSymbols && bs != [4]byte{'a', 'l', 's', 'e'} { // !Equal jsonLiteral4False 733 // d.d.errorf("expecting %s: got %s", jsonLiteral4False, bs) 734 d.d.errorf("expecting false: got f%s", bs) 735 } 736 } 737 738 func (d *jsonDecDriver) readLit4Null(bs [4]byte) { 739 // bs := d.d.decRd.readn3() // readx(3) 740 d.tok = 0 741 if jsonValidateSymbols && bs != [...]byte{0, 'u', 'l', 'l'} { // !Equal jsonLiteral4Null 742 // d.d.errorf("expecting %s: got %s", jsonLiteral4Null, bs[:]) 743 d.d.errorf("expecting null: got n%s", bs) 744 } 745 } 746 747 func (d *jsonDecDriver) advance() { 748 if d.tok == 0 { 749 d.tok = d.d.decRd.skipWhitespace() // skip(&whitespaceCharBitset) 750 } 751 } 752 753 func (d *jsonDecDriver) nextValueBytes(v []byte) []byte { 754 v, cursor := d.nextValueBytesR(v) 755 decNextValueBytesHelper{d: &d.d}.bytesRdV(&v, cursor) 756 return v 757 } 758 759 func (d *jsonDecDriver) nextValueBytesR(v0 []byte) (v []byte, cursor uint) { 760 v = v0 761 var h = decNextValueBytesHelper{d: &d.d} 762 dr := &d.d.decRd 763 764 consumeString := func() { 765 TOP: 766 bs := dr.jsonReadAsisChars() 767 h.appendN(&v, bs...) 768 if bs[len(bs)-1] != '"' { 769 // last char is '\', so consume next one and try again 770 h.append1(&v, dr.readn1()) 771 goto TOP 772 } 773 } 774 775 d.advance() // ignore leading whitespace 776 cursor = d.d.rb.c - 1 // cursor starts just before non-whitespace token 777 778 switch d.tok { 779 default: 780 h.appendN(&v, dr.jsonReadNum()...) 781 case 'n': 782 d.readLit4Null(d.d.decRd.readn3()) 783 h.appendN(&v, jsonLiteralNull...) 784 case 'f': 785 d.readLit4False(d.d.decRd.readn4()) 786 h.appendN(&v, jsonLiteralFalse...) 787 case 't': 788 d.readLit4True(d.d.decRd.readn3()) 789 h.appendN(&v, jsonLiteralTrue...) 790 case '"': 791 h.append1(&v, '"') 792 consumeString() 793 case '{', '[': 794 var elem struct{} 795 var stack []struct{} 796 797 stack = append(stack, elem) 798 799 h.append1(&v, d.tok) 800 801 for len(stack) != 0 { 802 c := dr.readn1() 803 h.append1(&v, c) 804 switch c { 805 case '"': 806 consumeString() 807 case '{', '[': 808 stack = append(stack, elem) 809 case '}', ']': 810 stack = stack[:len(stack)-1] 811 } 812 } 813 } 814 d.tok = 0 815 return 816 } 817 818 func (d *jsonDecDriver) TryNil() bool { 819 d.advance() 820 // we shouldn't try to see if quoted "null" was here, right? 821 // only the plain string: `null` denotes a nil (ie not quotes) 822 if d.tok == 'n' { 823 d.readLit4Null(d.d.decRd.readn3()) 824 return true 825 } 826 return false 827 } 828 829 func (d *jsonDecDriver) DecodeBool() (v bool) { 830 d.advance() 831 if d.tok == 'n' { 832 d.readLit4Null(d.d.decRd.readn3()) 833 return 834 } 835 fquot := d.d.c == containerMapKey && d.tok == '"' 836 if fquot { 837 d.tok = d.d.decRd.readn1() 838 } 839 switch d.tok { 840 case 'f': 841 d.readLit4False(d.d.decRd.readn4()) 842 // v = false 843 case 't': 844 d.readLit4True(d.d.decRd.readn3()) 845 v = true 846 default: 847 d.d.errorf("decode bool: got first char %c", d.tok) 848 // v = false // "unreachable" 849 } 850 if fquot { 851 d.d.decRd.readn1() 852 } 853 return 854 } 855 856 func (d *jsonDecDriver) DecodeTime() (t time.Time) { 857 // read string, and pass the string into json.unmarshal 858 d.advance() 859 if d.tok == 'n' { 860 d.readLit4Null(d.d.decRd.readn3()) 861 return 862 } 863 d.ensureReadingString() 864 bs := d.readUnescapedString() 865 t, err := time.Parse(time.RFC3339, stringView(bs)) 866 d.d.onerror(err) 867 return 868 } 869 870 func (d *jsonDecDriver) ContainerType() (vt valueType) { 871 // check container type by checking the first char 872 d.advance() 873 874 // optimize this, so we don't do 4 checks but do one computation. 875 // return jsonContainerSet[d.tok] 876 877 // ContainerType is mostly called for Map and Array, 878 // so this conditional is good enough (max 2 checks typically) 879 if d.tok == '{' { 880 return valueTypeMap 881 } else if d.tok == '[' { 882 return valueTypeArray 883 } else if d.tok == 'n' { 884 d.readLit4Null(d.d.decRd.readn3()) 885 return valueTypeNil 886 } else if d.tok == '"' { 887 return valueTypeString 888 } 889 return valueTypeUnset 890 } 891 892 func (d *jsonDecDriver) decNumBytes() (bs []byte) { 893 d.advance() 894 dr := &d.d.decRd 895 if d.tok == '"' { 896 bs = dr.readUntil('"') 897 } else if d.tok == 'n' { 898 d.readLit4Null(d.d.decRd.readn3()) 899 } else { 900 if jsonManualInlineDecRdInHotZones { 901 if dr.bytes { 902 bs = dr.rb.jsonReadNum() 903 } else if dr.bufio { 904 bs = dr.bi.jsonReadNum() 905 } else { 906 bs = dr.ri.jsonReadNum() 907 } 908 } else { 909 bs = dr.jsonReadNum() 910 } 911 } 912 d.tok = 0 913 return 914 } 915 916 func (d *jsonDecDriver) DecodeUint64() (u uint64) { 917 b := d.decNumBytes() 918 u, neg, ok := parseInteger_bytes(b) 919 if neg { 920 d.d.errorf("negative number cannot be decoded as uint64") 921 } 922 if !ok { 923 d.d.onerror(strconvParseErr(b, "ParseUint")) 924 } 925 return 926 } 927 928 func (d *jsonDecDriver) DecodeInt64() (v int64) { 929 b := d.decNumBytes() 930 u, neg, ok := parseInteger_bytes(b) 931 if !ok { 932 d.d.onerror(strconvParseErr(b, "ParseInt")) 933 } 934 if chkOvf.Uint2Int(u, neg) { 935 d.d.errorf("overflow decoding number from %s", b) 936 } 937 if neg { 938 v = -int64(u) 939 } else { 940 v = int64(u) 941 } 942 return 943 } 944 945 func (d *jsonDecDriver) DecodeFloat64() (f float64) { 946 var err error 947 bs := d.decNumBytes() 948 if len(bs) == 0 { 949 return 950 } 951 f, err = parseFloat64(bs) 952 d.d.onerror(err) 953 return 954 } 955 956 func (d *jsonDecDriver) DecodeFloat32() (f float32) { 957 var err error 958 bs := d.decNumBytes() 959 if len(bs) == 0 { 960 return 961 } 962 f, err = parseFloat32(bs) 963 d.d.onerror(err) 964 return 965 } 966 967 func (d *jsonDecDriver) DecodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) { 968 d.advance() 969 if d.tok == 'n' { 970 d.readLit4Null(d.d.decRd.readn3()) 971 return 972 } 973 if ext == nil { 974 re := rv.(*RawExt) 975 re.Tag = xtag 976 d.d.decode(&re.Value) 977 } else if ext == SelfExt { 978 d.d.decodeValue(baseRV(rv), d.h.fnNoExt(basetype)) 979 } else { 980 d.d.interfaceExtConvertAndDecode(rv, ext) 981 } 982 } 983 984 func (d *jsonDecDriver) decBytesFromArray(bs []byte) []byte { 985 if bs == nil { 986 bs = []byte{} 987 } else { 988 bs = bs[:0] 989 } 990 d.tok = 0 991 bs = append(bs, uint8(d.DecodeUint64())) 992 d.tok = d.d.decRd.skipWhitespace() // skip(&whitespaceCharBitset) 993 for d.tok != ']' { 994 if d.tok != ',' { 995 d.d.errorf("read array element - expect char '%c' but got char '%c'", ',', d.tok) 996 } 997 d.tok = 0 998 bs = append(bs, uint8(chkOvf.UintV(d.DecodeUint64(), 8))) 999 d.tok = d.d.decRd.skipWhitespace() // skip(&whitespaceCharBitset) 1000 } 1001 d.tok = 0 1002 return bs 1003 } 1004 1005 func (d *jsonDecDriver) DecodeBytes(bs []byte) (bsOut []byte) { 1006 d.d.decByteState = decByteStateNone 1007 d.advance() 1008 if d.tok == 'n' { 1009 d.readLit4Null(d.d.decRd.readn3()) 1010 return nil 1011 } 1012 // if decoding into raw bytes, and the RawBytesExt is configured, use it to decode. 1013 if d.rawext { 1014 bsOut = bs 1015 d.d.interfaceExtConvertAndDecode(&bsOut, d.h.RawBytesExt) 1016 return 1017 } 1018 // check if an "array" of uint8's (see ContainerType for how to infer if an array) 1019 if d.tok == '[' { 1020 // bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d) 1021 if bs == nil { 1022 d.d.decByteState = decByteStateReuseBuf 1023 bs = d.d.b[:] 1024 } 1025 return d.decBytesFromArray(bs) 1026 } 1027 1028 // base64 encodes []byte{} as "", and we encode nil []byte as null. 1029 // Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}. 1030 1031 d.ensureReadingString() 1032 bs1 := d.readUnescapedString() 1033 slen := base64.StdEncoding.DecodedLen(len(bs1)) 1034 if slen == 0 { 1035 bsOut = []byte{} 1036 } else if slen <= cap(bs) { 1037 bsOut = bs[:slen] 1038 } else if bs == nil { 1039 d.d.decByteState = decByteStateReuseBuf 1040 bsOut = d.d.blist.check(*d.buf, slen)[:slen] 1041 *d.buf = bsOut 1042 } else { 1043 bsOut = make([]byte, slen) 1044 } 1045 slen2, err := base64.StdEncoding.Decode(bsOut, bs1) 1046 if err != nil { 1047 d.d.errorf("error decoding base64 binary '%s': %v", bs1, err) 1048 } 1049 if slen != slen2 { 1050 bsOut = bsOut[:slen2] 1051 } 1052 return 1053 } 1054 1055 func (d *jsonDecDriver) DecodeStringAsBytes() (s []byte) { 1056 d.d.decByteState = decByteStateNone 1057 d.advance() 1058 1059 // common case 1060 if d.tok == '"' { 1061 return d.dblQuoteStringAsBytes() 1062 } 1063 1064 // handle non-string scalar: null, true, false or a number 1065 switch d.tok { 1066 case 'n': 1067 d.readLit4Null(d.d.decRd.readn3()) 1068 return nil // []byte{} 1069 case 'f': 1070 d.readLit4False(d.d.decRd.readn4()) 1071 return jsonLiteralFalse 1072 case 't': 1073 d.readLit4True(d.d.decRd.readn3()) 1074 return jsonLiteralTrue 1075 } 1076 1077 // try to parse a valid number 1078 d.tok = 0 1079 return d.d.decRd.jsonReadNum() 1080 } 1081 1082 func (d *jsonDecDriver) ensureReadingString() { 1083 if d.tok != '"' { 1084 d.d.errorf("expecting string starting with '\"'; got '%c'", d.tok) 1085 } 1086 } 1087 1088 func (d *jsonDecDriver) readUnescapedString() (bs []byte) { 1089 // d.ensureReadingString() 1090 bs = d.d.decRd.readUntil('"') 1091 d.tok = 0 1092 return 1093 } 1094 1095 func (d *jsonDecDriver) dblQuoteStringAsBytes() (buf []byte) { 1096 d.d.decByteState = decByteStateNone 1097 // use a local buf variable, so we don't do pointer chasing within loop 1098 buf = (*d.buf)[:0] 1099 dr := &d.d.decRd 1100 d.tok = 0 1101 1102 var bs []byte 1103 var c byte 1104 var firstTime bool = true 1105 1106 for { 1107 if firstTime { 1108 firstTime = false 1109 if dr.bytes { 1110 bs = dr.rb.jsonReadAsisChars() 1111 if bs[len(bs)-1] == '"' { 1112 d.d.decByteState = decByteStateZerocopy 1113 return bs[:len(bs)-1] 1114 } 1115 goto APPEND 1116 } 1117 } 1118 1119 if jsonManualInlineDecRdInHotZones { 1120 if dr.bytes { 1121 bs = dr.rb.jsonReadAsisChars() 1122 } else if dr.bufio { 1123 bs = dr.bi.jsonReadAsisChars() 1124 } else { 1125 bs = dr.ri.jsonReadAsisChars() 1126 } 1127 } else { 1128 bs = dr.jsonReadAsisChars() 1129 } 1130 1131 APPEND: 1132 buf = append(buf, bs[:len(bs)-1]...) 1133 c = bs[len(bs)-1] 1134 1135 if c == '"' { 1136 break 1137 } 1138 1139 // c is now '\' 1140 c = dr.readn1() 1141 1142 switch c { 1143 case '"', '\\', '/', '\'': 1144 buf = append(buf, c) 1145 case 'b': 1146 buf = append(buf, '\b') 1147 case 'f': 1148 buf = append(buf, '\f') 1149 case 'n': 1150 buf = append(buf, '\n') 1151 case 'r': 1152 buf = append(buf, '\r') 1153 case 't': 1154 buf = append(buf, '\t') 1155 case 'u': 1156 buf = append(buf, d.bstr[:utf8.EncodeRune(d.bstr[:], d.appendStringAsBytesSlashU())]...) 1157 default: 1158 *d.buf = buf 1159 d.d.errorf("unsupported escaped value: %c", c) 1160 } 1161 } 1162 *d.buf = buf 1163 d.d.decByteState = decByteStateReuseBuf 1164 return 1165 } 1166 1167 func (d *jsonDecDriver) appendStringAsBytesSlashU() (r rune) { 1168 var rr uint32 1169 var csu [2]byte 1170 var cs [4]byte = d.d.decRd.readn4() 1171 if rr = jsonSlashURune(cs); rr == unicode.ReplacementChar { 1172 return unicode.ReplacementChar 1173 } 1174 r = rune(rr) 1175 if utf16.IsSurrogate(r) { 1176 csu = d.d.decRd.readn2() 1177 cs = d.d.decRd.readn4() 1178 if csu[0] == '\\' && csu[1] == 'u' { 1179 if rr = jsonSlashURune(cs); rr == unicode.ReplacementChar { 1180 return unicode.ReplacementChar 1181 } 1182 return utf16.DecodeRune(r, rune(rr)) 1183 } 1184 return unicode.ReplacementChar 1185 } 1186 return 1187 } 1188 1189 func jsonSlashURune(cs [4]byte) (rr uint32) { 1190 for _, c := range cs { 1191 // best to use explicit if-else 1192 // - not a table, etc which involve memory loads, array lookup with bounds checks, etc 1193 if c >= '0' && c <= '9' { 1194 rr = rr*16 + uint32(c-jsonU4Chk2) 1195 } else if c >= 'a' && c <= 'f' { 1196 rr = rr*16 + uint32(c-jsonU4Chk1) 1197 } else if c >= 'A' && c <= 'F' { 1198 rr = rr*16 + uint32(c-jsonU4Chk0) 1199 } else { 1200 return unicode.ReplacementChar 1201 } 1202 } 1203 return 1204 } 1205 1206 func (d *jsonDecDriver) nakedNum(z *fauxUnion, bs []byte) (err error) { 1207 // Note: nakedNum is NEVER called with a zero-length []byte 1208 if d.h.PreferFloat { 1209 z.v = valueTypeFloat 1210 z.f, err = parseFloat64(bs) 1211 } else { 1212 err = parseNumber(bs, z, d.h.SignedInteger) 1213 } 1214 return 1215 } 1216 1217 func (d *jsonDecDriver) DecodeNaked() { 1218 z := d.d.naked() 1219 1220 d.advance() 1221 var bs []byte 1222 switch d.tok { 1223 case 'n': 1224 d.readLit4Null(d.d.decRd.readn3()) 1225 z.v = valueTypeNil 1226 case 'f': 1227 d.readLit4False(d.d.decRd.readn4()) 1228 z.v = valueTypeBool 1229 z.b = false 1230 case 't': 1231 d.readLit4True(d.d.decRd.readn3()) 1232 z.v = valueTypeBool 1233 z.b = true 1234 case '{': 1235 z.v = valueTypeMap // don't consume. kInterfaceNaked will call ReadMapStart 1236 case '[': 1237 z.v = valueTypeArray // don't consume. kInterfaceNaked will call ReadArrayStart 1238 case '"': 1239 // if a string, and MapKeyAsString, then try to decode it as a nil, bool or number first 1240 bs = d.dblQuoteStringAsBytes() 1241 if len(bs) > 0 && d.d.c == containerMapKey && d.h.MapKeyAsString { 1242 if bytes.Equal(bs, jsonLiteralNull) { 1243 z.v = valueTypeNil 1244 } else if bytes.Equal(bs, jsonLiteralTrue) { 1245 z.v = valueTypeBool 1246 z.b = true 1247 } else if bytes.Equal(bs, jsonLiteralFalse) { 1248 z.v = valueTypeBool 1249 z.b = false 1250 } else { 1251 // check if a number: float, int or uint 1252 if err := d.nakedNum(z, bs); err != nil { 1253 z.v = valueTypeString 1254 z.s = d.d.stringZC(bs) 1255 } 1256 } 1257 } else { 1258 z.v = valueTypeString 1259 z.s = d.d.stringZC(bs) 1260 } 1261 default: // number 1262 bs = d.d.decRd.jsonReadNum() 1263 d.tok = 0 1264 if len(bs) == 0 { 1265 d.d.errorf("decode number from empty string") 1266 } 1267 if err := d.nakedNum(z, bs); err != nil { 1268 d.d.errorf("decode number from %s: %v", bs, err) 1269 } 1270 } 1271 } 1272 1273 //---------------------- 1274 1275 // JsonHandle is a handle for JSON encoding format. 1276 // 1277 // Json is comprehensively supported: 1278 // - decodes numbers into interface{} as int, uint or float64 1279 // based on how the number looks and some config parameters e.g. PreferFloat, SignedInt, etc. 1280 // - decode integers from float formatted numbers e.g. 1.27e+8 1281 // - decode any json value (numbers, bool, etc) from quoted strings 1282 // - configurable way to encode/decode []byte . 1283 // by default, encodes and decodes []byte using base64 Std Encoding 1284 // - UTF-8 support for encoding and decoding 1285 // 1286 // It has better performance than the json library in the standard library, 1287 // by leveraging the performance improvements of the codec library. 1288 // 1289 // In addition, it doesn't read more bytes than necessary during a decode, which allows 1290 // reading multiple values from a stream containing json and non-json content. 1291 // For example, a user can read a json value, then a cbor value, then a msgpack value, 1292 // all from the same stream in sequence. 1293 // 1294 // Note that, when decoding quoted strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are 1295 // not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD. 1296 // 1297 // Note also that the float values for NaN, +Inf or -Inf are encoded as null, 1298 // as suggested by NOTE 4 of the ECMA-262 ECMAScript Language Specification 5.1 edition. 1299 // see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf . 1300 type JsonHandle struct { 1301 textEncodingType 1302 BasicHandle 1303 1304 // Indent indicates how a value is encoded. 1305 // - If positive, indent by that number of spaces. 1306 // - If negative, indent by that number of tabs. 1307 Indent int8 1308 1309 // IntegerAsString controls how integers (signed and unsigned) are encoded. 1310 // 1311 // Per the JSON Spec, JSON numbers are 64-bit floating point numbers. 1312 // Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision. 1313 // This can be mitigated by configuring how to encode integers. 1314 // 1315 // IntegerAsString interpretes the following values: 1316 // - if 'L', then encode integers > 2^53 as a json string. 1317 // - if 'A', then encode all integers as a json string 1318 // containing the exact integer representation as a decimal. 1319 // - else encode all integers as a json number (default) 1320 IntegerAsString byte 1321 1322 // HTMLCharsAsIs controls how to encode some special characters to html: < > & 1323 // 1324 // By default, we encode them as \uXXX 1325 // to prevent security holes when served from some browsers. 1326 HTMLCharsAsIs bool 1327 1328 // PreferFloat says that we will default to decoding a number as a float. 1329 // If not set, we will examine the characters of the number and decode as an 1330 // integer type if it doesn't have any of the characters [.eE]. 1331 PreferFloat bool 1332 1333 // TermWhitespace says that we add a whitespace character 1334 // at the end of an encoding. 1335 // 1336 // The whitespace is important, especially if using numbers in a context 1337 // where multiple items are written to a stream. 1338 TermWhitespace bool 1339 1340 // MapKeyAsString says to encode all map keys as strings. 1341 // 1342 // Use this to enforce strict json output. 1343 // The only caveat is that nil value is ALWAYS written as null (never as "null") 1344 MapKeyAsString bool 1345 1346 // _ uint64 // padding (cache line) 1347 1348 // Note: below, we store hardly-used items e.g. RawBytesExt. 1349 // These values below may straddle a cache line, but they are hardly-used, 1350 // so shouldn't contribute to false-sharing except in rare cases. 1351 1352 // RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way. 1353 // If not configured, raw bytes are encoded to/from base64 text. 1354 RawBytesExt InterfaceExt 1355 } 1356 1357 func (h *JsonHandle) isJson() bool { return true } 1358 1359 // Name returns the name of the handle: json 1360 func (h *JsonHandle) Name() string { return "json" } 1361 1362 func (h *JsonHandle) desc(bd byte) string { return string(bd) } 1363 1364 func (h *JsonHandle) typical() bool { 1365 return h.Indent == 0 && !h.MapKeyAsString && h.IntegerAsString != 'A' && h.IntegerAsString != 'L' 1366 } 1367 1368 func (h *JsonHandle) newEncDriver() encDriver { 1369 var e = &jsonEncDriver{h: h} 1370 // var x []byte 1371 // e.buf = &x 1372 e.e.e = e 1373 e.e.js = true 1374 e.e.init(h) 1375 e.reset() 1376 return e 1377 } 1378 1379 func (h *JsonHandle) newDecDriver() decDriver { 1380 var d = &jsonDecDriver{h: h} 1381 var x []byte 1382 d.buf = &x 1383 d.d.d = d 1384 d.d.js = true 1385 d.d.jsms = h.MapKeyAsString 1386 d.d.init(h) 1387 d.reset() 1388 return d 1389 } 1390 1391 func (e *jsonEncDriver) resetState() { 1392 e.dl = 0 1393 } 1394 1395 func (e *jsonEncDriver) reset() { 1396 e.resetState() 1397 // (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) 1398 // cache values from the handle 1399 e.typical = e.h.typical() 1400 if e.h.HTMLCharsAsIs { 1401 e.s = &jsonCharSafeSet 1402 } else { 1403 e.s = &jsonCharHtmlSafeSet 1404 } 1405 e.rawext = e.h.RawBytesExt != nil 1406 e.di = int8(e.h.Indent) 1407 e.d = e.h.Indent != 0 1408 e.ks = e.h.MapKeyAsString 1409 e.is = e.h.IntegerAsString 1410 } 1411 1412 func (d *jsonDecDriver) resetState() { 1413 *d.buf = d.d.blist.check(*d.buf, 256) 1414 d.tok = 0 1415 } 1416 1417 func (d *jsonDecDriver) reset() { 1418 d.resetState() 1419 d.rawext = d.h.RawBytesExt != nil 1420 } 1421 1422 func jsonFloatStrconvFmtPrec64(f float64) (fmt byte, prec int8) { 1423 fmt = 'f' 1424 prec = -1 1425 fbits := math.Float64bits(f) 1426 abs := math.Float64frombits(fbits &^ (1 << 63)) 1427 if abs == 0 || abs == 1 { 1428 prec = 1 1429 } else if abs < 1e-6 || abs >= 1e21 { 1430 fmt = 'e' 1431 } else if noFrac64(fbits) { 1432 prec = 1 1433 } 1434 return 1435 } 1436 1437 func jsonFloatStrconvFmtPrec32(f float32) (fmt byte, prec int8) { 1438 fmt = 'f' 1439 prec = -1 1440 // directly handle Modf (to get fractions) and Abs (to get absolute) 1441 fbits := math.Float32bits(f) 1442 abs := math.Float32frombits(fbits &^ (1 << 31)) 1443 if abs == 0 || abs == 1 { 1444 prec = 1 1445 } else if abs < 1e-6 || abs >= 1e21 { 1446 fmt = 'e' 1447 } else if noFrac32(fbits) { 1448 prec = 1 1449 } 1450 return 1451 } 1452 1453 var _ decDriverContainerTracker = (*jsonDecDriver)(nil) 1454 var _ encDriverContainerTracker = (*jsonEncDriver)(nil) 1455 var _ decDriver = (*jsonDecDriver)(nil) 1456 1457 var _ encDriver = (*jsonEncDriver)(nil)