… | |
… | |
162 | #endif |
162 | #endif |
163 | } |
163 | } |
164 | } |
164 | } |
165 | |
165 | |
166 | /* adds two STRLENs together, slow, and with paranoia */ |
166 | /* adds two STRLENs together, slow, and with paranoia */ |
167 | STRLEN |
167 | static STRLEN |
168 | strlen_sum (STRLEN l1, STRLEN l2) |
168 | strlen_sum (STRLEN l1, STRLEN l2) |
169 | { |
169 | { |
170 | size_t sum = l1 + l2; |
170 | size_t sum = l1 + l2; |
171 | |
171 | |
172 | if (sum < (size_t)l2 || sum != (size_t)(STRLEN)sum) |
172 | if (sum < (size_t)l2 || sum != (size_t)(STRLEN)sum) |
… | |
… | |
826 | |
826 | |
827 | encode_sv (enc, TOPs); |
827 | encode_sv (enc, TOPs); |
828 | SP -= count; |
828 | SP -= count; |
829 | } |
829 | } |
830 | |
830 | |
|
|
831 | PUTBACK; |
|
|
832 | |
831 | encode_ch (enc, ']'); |
833 | encode_ch (enc, ']'); |
832 | |
834 | |
833 | FREETMPS; LEAVE; |
835 | FREETMPS; LEAVE; |
834 | } |
836 | } |
835 | else if ((enc->json.flags & F_CONV_BLESSED) && (method = gv_fetchmethod_autoload (stash, "TO_JSON", 0))) |
837 | else if ((enc->json.flags & F_CONV_BLESSED) && (method = gv_fetchmethod_autoload (stash, "TO_JSON", 0))) |
… | |
… | |
916 | if (SvIsUV (sv) ? SvUVX (sv) <= 59000 |
918 | if (SvIsUV (sv) ? SvUVX (sv) <= 59000 |
917 | : SvIVX (sv) <= 59000 && SvIVX (sv) >= -59000) |
919 | : SvIVX (sv) <= 59000 && SvIVX (sv) >= -59000) |
918 | { |
920 | { |
919 | // optimise the "small number case" |
921 | // optimise the "small number case" |
920 | // code will likely be branchless and use only a single multiplication |
922 | // code will likely be branchless and use only a single multiplication |
921 | // works for numbers up to 59074 |
923 | // 4.28 works for numbers up to 59074 |
922 | I32 i = SvIVX (sv); |
924 | I32 i = SvIVX (sv); |
923 | U32 u; |
925 | U32 u; |
924 | char digit, nz = 0; |
926 | char digit, nz = 0; |
925 | |
927 | |
926 | need (enc, 6); |
928 | need (enc, 6); |
… | |
… | |
1036 | else |
1038 | else |
1037 | break; |
1039 | break; |
1038 | } |
1040 | } |
1039 | else if (ch != 0x20 && ch != 0x0a && ch != 0x0d && ch != 0x09) |
1041 | else if (ch != 0x20 && ch != 0x0a && ch != 0x0d && ch != 0x09) |
1040 | break; // parse error, but let higher level handle it, gives better error messages |
1042 | break; // parse error, but let higher level handle it, gives better error messages |
1041 | |
1043 | else |
1042 | ++dec->cur; |
1044 | ++dec->cur; |
1043 | } |
1045 | } |
1044 | } |
1046 | } |
1045 | |
1047 | |
1046 | #define ERR(reason) SB dec->err = reason; goto fail; SE |
1048 | #define ERR(reason) SB dec->err = reason; goto fail; SE |
1047 | |
1049 | |
… | |
… | |
1504 | |
1506 | |
1505 | DEC_DEC_DEPTH; |
1507 | DEC_DEC_DEPTH; |
1506 | sv = newRV_noinc ((SV *)hv); |
1508 | sv = newRV_noinc ((SV *)hv); |
1507 | |
1509 | |
1508 | // check filter callbacks |
1510 | // check filter callbacks |
1509 | if (dec->json.flags & F_HOOK) |
1511 | if (expect_false (dec->json.flags & F_HOOK)) |
1510 | { |
1512 | { |
1511 | if (dec->json.cb_sk_object && HvKEYS (hv) == 1) |
1513 | if (dec->json.cb_sk_object && HvKEYS (hv) == 1) |
1512 | { |
1514 | { |
1513 | HE *cb, *he; |
1515 | HE *cb, *he; |
1514 | |
1516 | |
… | |
… | |
1533 | PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN; |
1535 | PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN; |
1534 | |
1536 | |
1535 | if (count == 1) |
1537 | if (count == 1) |
1536 | { |
1538 | { |
1537 | sv = newSVsv (POPs); |
1539 | sv = newSVsv (POPs); |
|
|
1540 | PUTBACK; |
1538 | FREETMPS; LEAVE; |
1541 | FREETMPS; LEAVE; |
1539 | return sv; |
1542 | return sv; |
1540 | } |
1543 | } |
1541 | else if (count) |
1544 | else if (count) |
1542 | croak ("filter_json_single_key_object callbacks must not return more than one scalar"); |
1545 | croak ("filter_json_single_key_object callbacks must not return more than one scalar"); |
1543 | |
1546 | |
|
|
1547 | PUTBACK; |
|
|
1548 | |
1544 | SvREFCNT_inc (sv); |
1549 | SvREFCNT_inc (sv); |
|
|
1550 | |
1545 | FREETMPS; LEAVE; |
1551 | FREETMPS; LEAVE; |
1546 | } |
1552 | } |
1547 | } |
1553 | } |
1548 | |
1554 | |
1549 | if (dec->json.cb_object) |
1555 | if (dec->json.cb_object) |
… | |
… | |
1556 | XPUSHs (sv_2mortal (sv)); |
1562 | XPUSHs (sv_2mortal (sv)); |
1557 | |
1563 | |
1558 | PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN; |
1564 | PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN; |
1559 | |
1565 | |
1560 | if (count == 1) |
1566 | if (count == 1) |
1561 | { |
|
|
1562 | sv = newSVsv (POPs); |
1567 | sv = newSVsv (POPs); |
1563 | FREETMPS; LEAVE; |
|
|
1564 | return sv; |
|
|
1565 | } |
|
|
1566 | else if (count) |
1568 | else if (count == 0) |
|
|
1569 | SvREFCNT_inc (sv); |
|
|
1570 | else |
1567 | croak ("filter_json_object callbacks must not return more than one scalar"); |
1571 | croak ("filter_json_object callbacks must not return more than one scalar"); |
1568 | |
1572 | |
1569 | SvREFCNT_inc (sv); |
1573 | PUTBACK; |
|
|
1574 | |
1570 | FREETMPS; LEAVE; |
1575 | FREETMPS; LEAVE; |
1571 | } |
1576 | } |
1572 | } |
1577 | } |
1573 | |
1578 | |
1574 | return sv; |
1579 | return sv; |