… | |
… | |
497 | encode_str (enc, str, len, SvUTF8 (sv)); |
497 | encode_str (enc, str, len, SvUTF8 (sv)); |
498 | encode_ch (enc, '"'); |
498 | encode_ch (enc, '"'); |
499 | } |
499 | } |
500 | else if (SvNOKp (sv)) |
500 | else if (SvNOKp (sv)) |
501 | { |
501 | { |
|
|
502 | // trust that perl will do the right thing w.r.t. JSON syntax. |
502 | need (enc, NV_DIG + 32); |
503 | need (enc, NV_DIG + 32); |
503 | Gconvert (SvNVX (sv), NV_DIG, 0, enc->cur); |
504 | Gconvert (SvNVX (sv), NV_DIG, 0, enc->cur); |
504 | enc->cur += strlen (enc->cur); |
505 | enc->cur += strlen (enc->cur); |
505 | } |
506 | } |
506 | else if (SvIOKp (sv)) |
507 | else if (SvIOKp (sv)) |
507 | { |
508 | { |
508 | // we assume we can always read an IV as a UV |
509 | // we assume we can always read an IV as a UV |
509 | if (SvUV (sv) & ~(UV)0x7fff) |
510 | if (SvUV (sv) & ~(UV)0x7fff) |
510 | { |
511 | { |
|
|
512 | // large integer, use the (rather slow) snprintf way. |
511 | need (enc, sizeof (UV) * 3); |
513 | need (enc, sizeof (UV) * 3); |
512 | enc->cur += |
514 | enc->cur += |
513 | SvIsUV(sv) |
515 | SvIsUV(sv) |
514 | ? snprintf (enc->cur, sizeof (UV) * 3, "%"UVuf, (UV)SvUVX (sv)) |
516 | ? snprintf (enc->cur, sizeof (UV) * 3, "%"UVuf, (UV)SvUVX (sv)) |
515 | : snprintf (enc->cur, sizeof (UV) * 3, "%"IVdf, (IV)SvIVX (sv)); |
517 | : snprintf (enc->cur, sizeof (UV) * 3, "%"IVdf, (IV)SvIVX (sv)); |
… | |
… | |
518 | { |
520 | { |
519 | // optimise the "small number case" |
521 | // optimise the "small number case" |
520 | // code will likely be branchless and use only a single multiplication |
522 | // code will likely be branchless and use only a single multiplication |
521 | I32 i = SvIV (sv); |
523 | I32 i = SvIV (sv); |
522 | U32 u; |
524 | U32 u; |
|
|
525 | char digit, nz = 0; |
523 | |
526 | |
524 | need (enc, 6); |
527 | need (enc, 6); |
525 | |
528 | |
526 | *enc->cur = '-'; enc->cur += i < 0 ? 1 : 0; |
529 | *enc->cur = '-'; enc->cur += i < 0 ? 1 : 0; |
527 | u = i < 0 ? -i : i; |
530 | u = i < 0 ? -i : i; |
528 | |
531 | |
529 | // convert to 4.28 fixed-point representation |
532 | // convert to 4.28 fixed-point representation |
530 | u = u * ((0xfffffff + 10000) / 10000); // 10**5, 5 fractional digits |
533 | u = u * ((0xfffffff + 10000) / 10000); // 10**5, 5 fractional digits |
531 | |
534 | |
532 | char digit, nz = 0; |
535 | // now output digit by digit, each time masking out the integer part |
533 | |
536 | // and multiplying by 5 while moving the decimal point one to the right, |
|
|
537 | // resulting in a net multiplication by 10. |
|
|
538 | // we always write the digit to memory but conditionally increment |
|
|
539 | // the pointer, to ease the usage of conditional move instructions. |
534 | digit = u >> 28; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0xfffffff) * 5; |
540 | digit = u >> 28; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0xfffffff) * 5; |
535 | digit = u >> 27; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x7ffffff) * 5; |
541 | digit = u >> 27; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x7ffffff) * 5; |
536 | digit = u >> 26; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x3ffffff) * 5; |
542 | digit = u >> 26; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x3ffffff) * 5; |
537 | digit = u >> 25; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x1ffffff) * 5; |
543 | digit = u >> 25; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x1ffffff) * 5; |
538 | digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; |
544 | digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; // correctly generate '0' |
539 | } |
545 | } |
540 | } |
546 | } |
541 | else if (SvROK (sv)) |
547 | else if (SvROK (sv)) |
542 | encode_rv (enc, SvRV (sv)); |
548 | encode_rv (enc, SvRV (sv)); |
543 | else if (!SvOK (sv)) |
549 | else if (!SvOK (sv)) |