… | |
… | |
15 | |
15 | |
16 | // some old perls do not have this, try to make it work, no |
16 | // some old perls do not have this, try to make it work, no |
17 | // guarantees, though. if it breaks, you get to keep the pieces. |
17 | // guarantees, though. if it breaks, you get to keep the pieces. |
18 | #ifndef UTF8_MAXBYTES |
18 | #ifndef UTF8_MAXBYTES |
19 | # define UTF8_MAXBYTES 13 |
19 | # define UTF8_MAXBYTES 13 |
|
|
20 | #endif |
|
|
21 | |
|
|
22 | // compatibility with perl <5.18 |
|
|
23 | #ifndef HvNAMELEN_get |
|
|
24 | # define HvNAMELEN_get(hv) strlen (HvNAME (hv)) |
|
|
25 | #endif |
|
|
26 | #ifndef HvNAMELEN |
|
|
27 | # define HvNAMELEN(hv) HvNAMELEN_get (hv) |
|
|
28 | #endif |
|
|
29 | #ifndef HvNAMEUTF8 |
|
|
30 | # define HvNAMEUTF8(hv) 0 |
20 | #endif |
31 | #endif |
21 | |
32 | |
22 | // three extra for rounding, sign, and end of string |
33 | // three extra for rounding, sign, and end of string |
23 | #define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 3) |
34 | #define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 3) |
24 | |
35 | |
… | |
… | |
683 | // encode objects, arrays and special \0=false and \1=true values. |
694 | // encode objects, arrays and special \0=false and \1=true values. |
684 | static void |
695 | static void |
685 | encode_rv (enc_t *enc, SV *sv) |
696 | encode_rv (enc_t *enc, SV *sv) |
686 | { |
697 | { |
687 | svtype svt; |
698 | svtype svt; |
|
|
699 | GV *method; |
688 | |
700 | |
689 | SvGETMAGIC (sv); |
701 | SvGETMAGIC (sv); |
690 | svt = SvTYPE (sv); |
702 | svt = SvTYPE (sv); |
691 | |
703 | |
692 | if (expect_false (SvOBJECT (sv))) |
704 | if (expect_false (SvOBJECT (sv))) |
… | |
… | |
701 | if (SvIV (sv)) |
713 | if (SvIV (sv)) |
702 | encode_str (enc, "true", 4, 0); |
714 | encode_str (enc, "true", 4, 0); |
703 | else |
715 | else |
704 | encode_str (enc, "false", 5, 0); |
716 | encode_str (enc, "false", 5, 0); |
705 | } |
717 | } |
706 | else if (enc->json.flags & F_CONV_BLESSED) |
718 | else if ((enc->json.flags & F_ALLOW_TAGS) && (method = gv_fetchmethod_autoload (stash, "FREEZE", 0))) |
707 | { |
719 | { |
708 | GV *to_json = gv_fetchmethod_autoload (stash, "TO_JSON", 0); |
720 | int count; |
|
|
721 | dSP; |
709 | |
722 | |
|
|
723 | ENTER; SAVETMPS; |
|
|
724 | SAVESTACK_POS (); |
|
|
725 | PUSHMARK (SP); |
|
|
726 | EXTEND (SP, 2); |
|
|
727 | // we re-bless the reference to get overload and other niceties right |
|
|
728 | PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); |
710 | if (to_json) |
729 | PUSHs (sv_json); |
|
|
730 | |
|
|
731 | PUTBACK; |
|
|
732 | count = call_sv ((SV *)GvCV (method), G_ARRAY); |
|
|
733 | SPAGAIN; |
|
|
734 | |
|
|
735 | // catch this surprisingly common error |
|
|
736 | if (SvROK (TOPs) && SvRV (TOPs) == sv) |
|
|
737 | croak ("%s::FREEZE method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); |
|
|
738 | |
|
|
739 | encode_ch (enc, '('); |
|
|
740 | encode_ch (enc, '"'); |
|
|
741 | encode_str (enc, HvNAME (stash), HvNAMELEN (stash), HvNAMEUTF8 (stash)); |
|
|
742 | encode_ch (enc, '"'); |
|
|
743 | encode_ch (enc, ')'); |
|
|
744 | encode_ch (enc, '['); |
|
|
745 | |
|
|
746 | while (count) |
711 | { |
747 | { |
712 | dSP; |
748 | encode_sv (enc, SP[1 - count--]); |
713 | |
749 | |
714 | ENTER; SAVETMPS; PUSHMARK (SP); |
750 | if (count) |
715 | // we re-bless the reference to get overload and other niceties right |
|
|
716 | XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); |
|
|
717 | |
|
|
718 | // calling with G_SCALAR ensures that we always get a 1 return value |
|
|
719 | PUTBACK; |
|
|
720 | call_sv ((SV *)GvCV (to_json), G_SCALAR); |
|
|
721 | SPAGAIN; |
|
|
722 | |
|
|
723 | // catch this surprisingly common error |
|
|
724 | if (SvROK (TOPs) && SvRV (TOPs) == sv) |
|
|
725 | croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); |
|
|
726 | |
|
|
727 | sv = POPs; |
|
|
728 | PUTBACK; |
|
|
729 | |
|
|
730 | encode_sv (enc, sv); |
751 | encode_ch (enc, ','); |
731 | |
|
|
732 | FREETMPS; LEAVE; |
|
|
733 | } |
752 | } |
734 | else if (enc->json.flags & F_ALLOW_BLESSED) |
753 | |
735 | encode_str (enc, "null", 4, 0); |
754 | encode_ch (enc, ']'); |
736 | else |
755 | |
737 | croak ("encountered object '%s' when conv_object is enabled, but TO_JSON is missing and allow_blessed disabled", |
756 | FREETMPS; LEAVE; |
738 | SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
|
|
739 | } |
757 | } |
740 | else if (enc->json.flags & F_ALLOW_TAGS) |
758 | else if ((enc->json.flags & F_CONV_BLESSED) && (method = gv_fetchmethod_autoload (stash, "TO_JSON", 0))) |
741 | { |
759 | { |
742 | GV *method = gv_fetchmethod_autoload (stash, "FREEZE", 0); |
|
|
743 | |
|
|
744 | if (method) |
|
|
745 | { |
|
|
746 | int count; |
|
|
747 | dSP; |
760 | dSP; |
748 | |
761 | |
749 | ENTER; SAVETMPS; PUSHMARK (SP); |
762 | ENTER; SAVETMPS; |
750 | EXTEND (SP, 2); |
763 | PUSHMARK (SP); |
751 | // we re-bless the reference to get overload and other niceties right |
764 | // we re-bless the reference to get overload and other niceties right |
752 | PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); |
765 | XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); |
753 | PUSHs (sv_json); |
|
|
754 | |
766 | |
|
|
767 | // calling with G_SCALAR ensures that we always get a 1 return value |
755 | PUTBACK; |
768 | PUTBACK; |
756 | count = call_sv ((SV *)GvCV (method), G_ARRAY); |
769 | call_sv ((SV *)GvCV (method), G_SCALAR); |
757 | SPAGAIN; |
770 | SPAGAIN; |
758 | |
771 | |
759 | // catch this surprisingly common error |
772 | // catch this surprisingly common error |
760 | if (SvROK (TOPs) && SvRV (TOPs) == sv) |
773 | if (SvROK (TOPs) && SvRV (TOPs) == sv) |
761 | croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); |
774 | croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); |
762 | |
775 | |
763 | encode_ch (enc, '('); |
776 | sv = POPs; |
764 | encode_ch (enc, '"'); |
|
|
765 | encode_str (enc, HvNAME (stash), HvNAMELEN (stash), HvNAMEUTF8 (stash)); |
|
|
766 | encode_ch (enc, '"'); |
|
|
767 | encode_ch (enc, ')'); |
|
|
768 | encode_ch (enc, '['); |
|
|
769 | |
|
|
770 | while (count) |
|
|
771 | { |
|
|
772 | encode_sv (enc, SP[1 - count--]); |
|
|
773 | |
|
|
774 | if (count) |
|
|
775 | encode_ch (enc, ','); |
|
|
776 | } |
|
|
777 | |
|
|
778 | encode_ch (enc, ']'); |
|
|
779 | |
|
|
780 | PUTBACK; |
777 | PUTBACK; |
781 | |
778 | |
|
|
779 | encode_sv (enc, sv); |
|
|
780 | |
782 | FREETMPS; LEAVE; |
781 | FREETMPS; LEAVE; |
783 | } |
|
|
784 | else if (enc->json.flags & F_ALLOW_BLESSED) |
|
|
785 | encode_str (enc, "null", 4, 0); |
|
|
786 | else |
|
|
787 | croak ("encountered object '%s' when allow_tags is enabled, but FREEZE is missing and allow_blessed disabled", |
|
|
788 | SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
|
|
789 | } |
782 | } |
790 | else if (enc->json.flags & F_ALLOW_BLESSED) |
783 | else if (enc->json.flags & F_ALLOW_BLESSED) |
791 | encode_str (enc, "null", 4, 0); |
784 | encode_str (enc, "null", 4, 0); |
792 | else |
785 | else |
793 | croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled", |
786 | croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", |
794 | SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
787 | SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
795 | } |
788 | } |
796 | else if (svt == SVt_PVHV) |
789 | else if (svt == SVt_PVHV) |
797 | encode_hv (enc, (HV *)sv); |
790 | encode_hv (enc, (HV *)sv); |
798 | else if (svt == SVt_PVAV) |
791 | else if (svt == SVt_PVAV) |
… | |
… | |
890 | else |
883 | else |
891 | croak ("encountered perl type (%s,0x%x) that JSON cannot handle, check your input data", |
884 | croak ("encountered perl type (%s,0x%x) that JSON cannot handle, check your input data", |
892 | SvPV_nolen (sv), (unsigned int)SvFLAGS (sv)); |
885 | SvPV_nolen (sv), (unsigned int)SvFLAGS (sv)); |
893 | } |
886 | } |
894 | |
887 | |
|
|
888 | static int |
|
|
889 | json_scalar (SV *scalar) |
|
|
890 | { |
|
|
891 | return 0;//D |
|
|
892 | if (!SvROK (scalar)) |
|
|
893 | return 1; |
|
|
894 | } |
|
|
895 | |
895 | static SV * |
896 | static SV * |
896 | encode_json (SV *scalar, JSON *json) |
897 | encode_json (SV *scalar, JSON *json) |
897 | { |
898 | { |
898 | enc_t enc; |
899 | enc_t enc; |
899 | |
900 | |
900 | if (!(json->flags & F_ALLOW_NONREF) && !SvROK (scalar)) |
901 | if (!(json->flags & F_ALLOW_NONREF) && json_scalar (scalar)) |
901 | croak ("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)"); |
902 | croak ("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)"); |
902 | |
903 | |
903 | enc.json = *json; |
904 | enc.json = *json; |
904 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
905 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
905 | enc.cur = SvPVX (enc.sv); |
906 | enc.cur = SvPVX (enc.sv); |
… | |
… | |
1112 | *cur++ = *dec_cur++; |
1113 | *cur++ = *dec_cur++; |
1113 | while (--clen); |
1114 | while (--clen); |
1114 | |
1115 | |
1115 | utf8 = 1; |
1116 | utf8 = 1; |
1116 | } |
1117 | } |
|
|
1118 | else if (ch == '\t' && dec->json.flags & F_RELAXED) |
|
|
1119 | *cur++ = ch; |
1117 | else |
1120 | else |
1118 | { |
1121 | { |
1119 | --dec_cur; |
1122 | --dec_cur; |
1120 | |
1123 | |
1121 | if (!ch) |
1124 | if (!ch) |
… | |
… | |
1443 | |
1446 | |
1444 | hv_iterinit (hv); |
1447 | hv_iterinit (hv); |
1445 | he = hv_iternext (hv); |
1448 | he = hv_iternext (hv); |
1446 | hv_iterinit (hv); |
1449 | hv_iterinit (hv); |
1447 | |
1450 | |
1448 | // the next line creates a mortal sv each time its called. |
1451 | // the next line creates a mortal sv each time it's called. |
1449 | // might want to optimise this for common cases. |
1452 | // might want to optimise this for common cases. |
1450 | cb = hv_fetch_ent (dec->json.cb_sk_object, hv_iterkeysv (he), 0, 0); |
1453 | cb = hv_fetch_ent (dec->json.cb_sk_object, hv_iterkeysv (he), 0, 0); |
1451 | |
1454 | |
1452 | if (cb) |
1455 | if (cb) |
1453 | { |
1456 | { |
1454 | dSP; |
1457 | dSP; |
1455 | int count; |
1458 | int count; |
1456 | |
1459 | |
1457 | ENTER; SAVETMPS; PUSHMARK (SP); |
1460 | ENTER; SAVETMPS; |
|
|
1461 | SAVESTACK_POS (); |
|
|
1462 | PUSHMARK (SP); |
1458 | XPUSHs (HeVAL (he)); |
1463 | XPUSHs (HeVAL (he)); |
1459 | sv_2mortal (sv); |
1464 | sv_2mortal (sv); |
1460 | |
1465 | |
1461 | PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN; |
1466 | PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN; |
1462 | |
1467 | |
… | |
… | |
1475 | if (dec->json.cb_object) |
1480 | if (dec->json.cb_object) |
1476 | { |
1481 | { |
1477 | dSP; |
1482 | dSP; |
1478 | int count; |
1483 | int count; |
1479 | |
1484 | |
1480 | ENTER; SAVETMPS; PUSHMARK (SP); |
1485 | ENTER; SAVETMPS; |
|
|
1486 | SAVESTACK_POS (); |
|
|
1487 | PUSHMARK (SP); |
1481 | XPUSHs (sv_2mortal (sv)); |
1488 | XPUSHs (sv_2mortal (sv)); |
1482 | |
1489 | |
1483 | PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN; |
1490 | PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN; |
1484 | |
1491 | |
1485 | if (count == 1) |
1492 | if (count == 1) |
… | |
… | |
1511 | if (!(dec->json.flags & F_ALLOW_TAGS)) |
1518 | if (!(dec->json.flags & F_ALLOW_TAGS)) |
1512 | ERR ("malformed JSON string, neither array, object, number, string or atom"); |
1519 | ERR ("malformed JSON string, neither array, object, number, string or atom"); |
1513 | |
1520 | |
1514 | ++dec->cur; |
1521 | ++dec->cur; |
1515 | |
1522 | |
|
|
1523 | decode_ws (dec); |
|
|
1524 | |
1516 | tag = decode_sv (dec); |
1525 | tag = decode_sv (dec); |
1517 | if (!tag) |
1526 | if (!tag) |
1518 | goto fail; |
1527 | goto fail; |
1519 | |
1528 | |
1520 | if (!SvPOK (tag)) |
1529 | if (!SvPOK (tag)) |
1521 | ERR ("malformed JSON string, (tag) must be a string"); |
1530 | ERR ("malformed JSON string, (tag) must be a string"); |
1522 | |
1531 | |
|
|
1532 | decode_ws (dec); |
|
|
1533 | |
1523 | if (*dec->cur != ')') |
1534 | if (*dec->cur != ')') |
1524 | ERR (") expected after tag"); |
1535 | ERR (") expected after tag"); |
1525 | |
1536 | |
1526 | ++dec->cur; |
1537 | ++dec->cur; |
|
|
1538 | |
|
|
1539 | decode_ws (dec); |
1527 | |
1540 | |
1528 | val = decode_sv (dec); |
1541 | val = decode_sv (dec); |
1529 | if (!val) |
1542 | if (!val) |
1530 | goto fail; |
1543 | goto fail; |
1531 | |
1544 | |
… | |
… | |
1546 | if (!method) |
1559 | if (!method) |
1547 | ERR ("cannot decode perl-object (package does not have a THAW method)"); |
1560 | ERR ("cannot decode perl-object (package does not have a THAW method)"); |
1548 | |
1561 | |
1549 | dSP; |
1562 | dSP; |
1550 | |
1563 | |
1551 | ENTER; SAVETMPS; PUSHMARK (SP); |
1564 | ENTER; SAVETMPS; |
|
|
1565 | PUSHMARK (SP); |
1552 | EXTEND (SP, len + 2); |
1566 | EXTEND (SP, len + 2); |
1553 | // we re-bless the reference to get overload and other niceties right |
1567 | // we re-bless the reference to get overload and other niceties right |
1554 | PUSHs (tag); |
1568 | PUSHs (tag); |
1555 | PUSHs (sv_json); |
1569 | PUSHs (sv_json); |
1556 | |
1570 | |