… | |
… | |
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 | |
… | |
… | |
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) |
… | |
… | |
1561 | sv = newSVsv (POPs); |
1567 | sv = newSVsv (POPs); |
1562 | else if (count == 0) |
1568 | else if (count == 0) |
1563 | SvREFCNT_inc (sv); |
1569 | SvREFCNT_inc (sv); |
1564 | else |
1570 | else |
1565 | 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"); |
|
|
1572 | |
|
|
1573 | PUTBACK; |
1566 | |
1574 | |
1567 | FREETMPS; LEAVE; |
1575 | FREETMPS; LEAVE; |
1568 | } |
1576 | } |
1569 | } |
1577 | } |
1570 | |
1578 | |
… | |
… | |
2206 | XPUSHs (ST (0)); |
2214 | XPUSHs (ST (0)); |
2207 | } |
2215 | } |
2208 | |
2216 | |
2209 | void encode (JSON *self, SV *scalar) |
2217 | void encode (JSON *self, SV *scalar) |
2210 | PPCODE: |
2218 | PPCODE: |
2211 | PUTBACK; XPUSHs (encode_json (scalar, self)); |
2219 | PUTBACK; scalar = encode_json (scalar, self); SPAGAIN; |
|
|
2220 | XPUSHs (scalar); |
2212 | |
2221 | |
2213 | void decode (JSON *self, SV *jsonstr) |
2222 | void decode (JSON *self, SV *jsonstr) |
2214 | PPCODE: |
2223 | PPCODE: |
2215 | PUTBACK; XPUSHs (decode_json (jsonstr, self, 0)); |
2224 | PUTBACK; jsonstr = decode_json (jsonstr, self, 0); SPAGAIN; |
|
|
2225 | XPUSHs (jsonstr); |
2216 | |
2226 | |
2217 | void decode_prefix (JSON *self, SV *jsonstr) |
2227 | void decode_prefix (JSON *self, SV *jsonstr) |
2218 | PPCODE: |
2228 | PPCODE: |
2219 | { |
2229 | { |
2220 | SV *sv; |
2230 | SV *sv; |
2221 | STRLEN offset; |
2231 | STRLEN offset; |
2222 | PUTBACK; sv = decode_json (jsonstr, self, &offset); |
2232 | PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN; |
2223 | EXTEND (SP, 2); |
2233 | EXTEND (SP, 2); |
2224 | PUSHs (sv); |
2234 | PUSHs (sv); |
2225 | PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset)))); |
2235 | PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset)))); |
2226 | } |
2236 | } |
2227 | |
2237 | |
… | |
… | |
2300 | |
2310 | |
2301 | break; |
2311 | break; |
2302 | } |
2312 | } |
2303 | } |
2313 | } |
2304 | |
2314 | |
2305 | PUTBACK; sv = decode_json (self->incr_text, self, &offset); |
2315 | PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN; |
2306 | XPUSHs (sv); |
2316 | XPUSHs (sv); |
2307 | |
2317 | |
2308 | self->incr_pos -= offset; |
2318 | self->incr_pos -= offset; |
2309 | self->incr_nest = 0; |
2319 | self->incr_nest = 0; |
2310 | self->incr_mode = 0; |
2320 | self->incr_mode = 0; |
… | |
… | |
2362 | PPCODE: |
2372 | PPCODE: |
2363 | { |
2373 | { |
2364 | JSON json; |
2374 | JSON json; |
2365 | json_init (&json); |
2375 | json_init (&json); |
2366 | json.flags |= F_UTF8; |
2376 | json.flags |= F_UTF8; |
2367 | PUTBACK; XPUSHs (encode_json (scalar, &json)); |
2377 | PUTBACK; scalar = encode_json (scalar, &json); SPAGAIN; |
|
|
2378 | XPUSHs (scalar); |
2368 | } |
2379 | } |
2369 | |
2380 | |
2370 | void decode_json (SV *jsonstr) |
2381 | void decode_json (SV *jsonstr) |
2371 | PPCODE: |
2382 | PPCODE: |
2372 | { |
2383 | { |
2373 | JSON json; |
2384 | JSON json; |
2374 | json_init (&json); |
2385 | json_init (&json); |
2375 | json.flags |= F_UTF8; |
2386 | json.flags |= F_UTF8; |
2376 | PUTBACK; XPUSHs (decode_json (jsonstr, &json, 0)); |
2387 | PUTBACK; jsonstr = decode_json (jsonstr, &json, 0); SPAGAIN; |
|
|
2388 | XPUSHs (jsonstr); |
2377 | } |
2389 | } |
2378 | |
2390 | |