… | |
… | |
135 | char *cur; // SvPVX (sv) + current output position |
135 | char *cur; // SvPVX (sv) + current output position |
136 | char *end; // SvEND (sv) |
136 | char *end; // SvEND (sv) |
137 | SV *sv; // result scalar |
137 | SV *sv; // result scalar |
138 | CBOR cbor; |
138 | CBOR cbor; |
139 | U32 depth; // recursion level |
139 | U32 depth; // recursion level |
140 | HV *stringref; // string => index, or 0 |
140 | HV *stringref[2]; // string => index, or 0 ([0] = bytes, [1] = utf-8) |
|
|
141 | UV stringref_idx; |
141 | HV *shareable; // ptr => index, or 0 |
142 | HV *shareable; // ptr => index, or 0 |
142 | UV shareable_idx; |
143 | UV shareable_idx; |
143 | } enc_t; |
144 | } enc_t; |
144 | |
145 | |
145 | ecb_inline void |
146 | ecb_inline void |
… | |
… | |
237 | } |
238 | } |
238 | |
239 | |
239 | --enc->depth; |
240 | --enc->depth; |
240 | } |
241 | } |
241 | |
242 | |
|
|
243 | ecb_inline void |
|
|
244 | encode_he (enc_t *enc, HE *he) |
|
|
245 | { |
|
|
246 | if (HeKLEN (he) == HEf_SVKEY) |
|
|
247 | encode_sv (enc, HeSVKEY (he)); |
|
|
248 | else |
|
|
249 | encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he)); |
|
|
250 | } |
|
|
251 | |
242 | static void |
252 | static void |
243 | encode_hv (enc_t *enc, HV *hv) |
253 | encode_hv (enc_t *enc, HV *hv) |
244 | { |
254 | { |
245 | HE *he; |
255 | HE *he; |
246 | |
256 | |
… | |
… | |
257 | else |
267 | else |
258 | encode_uint (enc, 0xa0, pairs); |
268 | encode_uint (enc, 0xa0, pairs); |
259 | |
269 | |
260 | while ((he = hv_iternext (hv))) |
270 | while ((he = hv_iternext (hv))) |
261 | { |
271 | { |
|
|
272 | if (ecb_expect_false (enc->cbor.flags & (F_DEDUP_STRINGS | F_DEDUP_KEYS))) |
|
|
273 | { |
|
|
274 | SV **svp; |
|
|
275 | |
262 | if (HeKLEN (he) == HEf_SVKEY) |
276 | if (HeKLEN (he) == HEf_SVKEY) |
263 | encode_sv (enc, HeSVKEY (he)); |
277 | svp = hv_fetch_ent (enc->stringref[!! SvUTF8 (HeSVKEY (he))], HeSVKEY (he) , 1, 0);//TODO return HE :/ |
|
|
278 | else |
|
|
279 | svp = hv_fetch (enc->stringref[!! HeKUTF8 (he) ], HeKEY (he), HeKLEN (he), 1); |
|
|
280 | |
|
|
281 | if (SvOK (*svp)) |
|
|
282 | { |
|
|
283 | encode_tag (enc, CBOR_TAG_STRINGREF); |
|
|
284 | encode_uint (enc, 0x00, SvUV (*svp)); |
|
|
285 | } |
|
|
286 | else |
|
|
287 | { |
|
|
288 | sv_setuv (*svp, enc->stringref_idx); |
|
|
289 | ++enc->stringref_idx; |
|
|
290 | encode_he (enc, he); |
|
|
291 | } |
|
|
292 | } |
264 | else |
293 | else |
265 | encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he)); |
294 | encode_he (enc, he); |
266 | |
295 | |
267 | encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he)); |
296 | encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he)); |
268 | } |
297 | } |
269 | |
298 | |
270 | if (mg) |
299 | if (mg) |
… | |
… | |
475 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
504 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
476 | enc.cur = SvPVX (enc.sv); |
505 | enc.cur = SvPVX (enc.sv); |
477 | enc.end = SvEND (enc.sv); |
506 | enc.end = SvEND (enc.sv); |
478 | |
507 | |
479 | SvPOK_only (enc.sv); |
508 | SvPOK_only (enc.sv); |
|
|
509 | |
|
|
510 | if (cbor->flags & (F_DEDUP_STRINGS | F_DEDUP_KEYS)) |
|
|
511 | { |
|
|
512 | encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE); |
|
|
513 | enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ()); |
|
|
514 | enc.stringref[1]= (HV *)sv_2mortal ((SV *)newHV ()); |
|
|
515 | } |
|
|
516 | |
480 | encode_sv (&enc, scalar); |
517 | encode_sv (&enc, scalar); |
481 | |
518 | |
482 | SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); |
519 | SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); |
483 | *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings |
520 | *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings |
484 | |
521 | |
… | |
… | |
499 | const char *err; // parse error, if != 0 |
536 | const char *err; // parse error, if != 0 |
500 | CBOR cbor; |
537 | CBOR cbor; |
501 | U32 depth; // recursion depth |
538 | U32 depth; // recursion depth |
502 | U32 maxdepth; // recursion depth limit |
539 | U32 maxdepth; // recursion depth limit |
503 | AV *shareable; |
540 | AV *shareable; |
|
|
541 | AV *stringref; |
504 | } dec_t; |
542 | } dec_t; |
505 | |
543 | |
506 | #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE |
544 | #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE |
507 | |
545 | |
508 | #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") |
546 | #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") |
… | |
… | |
615 | I32 len = decode_uint (dec); |
653 | I32 len = decode_uint (dec); |
616 | char *key = (char *)dec->cur; |
654 | char *key = (char *)dec->cur; |
617 | |
655 | |
618 | dec->cur += len; |
656 | dec->cur += len; |
619 | |
657 | |
|
|
658 | if (ecb_expect_false (dec->stringref)) |
|
|
659 | av_push (dec->stringref, newSVpvn (key, len)); |
|
|
660 | |
620 | hv_store (hv, key, len, decode_sv (dec), 0); |
661 | hv_store (hv, key, len, decode_sv (dec), 0); |
621 | } |
662 | } |
622 | else if (*dec->cur >= 0x60 && *dec->cur <= 0x60 + 27) |
663 | else if (*dec->cur >= 0x60 && *dec->cur <= 0x60 + 27) |
623 | { |
664 | { |
624 | I32 len = decode_uint (dec); |
665 | I32 len = decode_uint (dec); |
625 | char *key = (char *)dec->cur; |
666 | char *key = (char *)dec->cur; |
626 | |
667 | |
627 | dec->cur += len; |
668 | dec->cur += len; |
|
|
669 | |
|
|
670 | if (ecb_expect_false (dec->stringref)) |
|
|
671 | av_push (dec->stringref, newSVpvn_utf8 (key, len, 1)); |
628 | |
672 | |
629 | hv_store (hv, key, -len, decode_sv (dec), 0); |
673 | hv_store (hv, key, -len, decode_sv (dec), 0); |
630 | } |
674 | } |
631 | else |
675 | else |
632 | { |
676 | { |
… | |
… | |
714 | } |
758 | } |
715 | |
759 | |
716 | if (utf8) |
760 | if (utf8) |
717 | SvUTF8_on (sv); |
761 | SvUTF8_on (sv); |
718 | |
762 | |
|
|
763 | if (ecb_expect_false (dec->stringref)) |
|
|
764 | av_push (dec->stringref, SvREFCNT_inc_NN (sv)); |
|
|
765 | |
719 | return sv; |
766 | return sv; |
720 | |
767 | |
721 | fail: |
768 | fail: |
722 | SvREFCNT_dec (sv); |
769 | SvREFCNT_dec (sv); |
723 | return &PL_sv_undef; |
770 | return &PL_sv_undef; |
… | |
… | |
732 | WANT (1); |
779 | WANT (1); |
733 | |
780 | |
734 | switch (tag) |
781 | switch (tag) |
735 | { |
782 | { |
736 | case CBOR_TAG_MAGIC: |
783 | case CBOR_TAG_MAGIC: |
737 | return decode_sv (dec); |
784 | sv = decode_sv (dec); |
|
|
785 | break; |
738 | |
786 | |
739 | case CBOR_TAG_INDIRECTION: |
787 | case CBOR_TAG_INDIRECTION: |
740 | return newRV_noinc (decode_sv (dec)); |
788 | sv = newRV_noinc (decode_sv (dec)); |
|
|
789 | break; |
|
|
790 | |
|
|
791 | case CBOR_TAG_STRINGREF_NAMESPACE: |
|
|
792 | { |
|
|
793 | ENTER; SAVETMPS; |
|
|
794 | |
|
|
795 | SAVESPTR (dec->stringref); |
|
|
796 | dec->stringref = (AV *)sv_2mortal ((SV *)newAV ()); |
|
|
797 | |
|
|
798 | sv = decode_sv (dec); |
|
|
799 | |
|
|
800 | FREETMPS; LEAVE; |
|
|
801 | } |
|
|
802 | break; |
|
|
803 | |
|
|
804 | case CBOR_TAG_STRINGREF: |
|
|
805 | { |
|
|
806 | if ((*dec->cur >> 5) != 0) |
|
|
807 | ERR ("corrupted CBOR data (stringref index not an unsigned integer)"); |
|
|
808 | |
|
|
809 | UV idx = decode_uint (dec); |
|
|
810 | |
|
|
811 | if (!dec->stringref || (int)idx > AvFILLp (dec->stringref)) |
|
|
812 | ERR ("corrupted CBOR data (stringref index out of bounds or outside namespace)"); |
|
|
813 | |
|
|
814 | sv = newSVsv (AvARRAY (dec->stringref)[idx]); |
|
|
815 | } |
|
|
816 | break; |
741 | |
817 | |
742 | case CBOR_TAG_VALUE_SHAREABLE: |
818 | case CBOR_TAG_VALUE_SHAREABLE: |
743 | { |
819 | { |
744 | if (ecb_expect_false (!dec->shareable)) |
820 | if (ecb_expect_false (!dec->shareable)) |
745 | dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); |
821 | dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); |
… | |
… | |
749 | |
825 | |
750 | SV *osv = decode_sv (dec); |
826 | SV *osv = decode_sv (dec); |
751 | sv_setsv (sv, osv); |
827 | sv_setsv (sv, osv); |
752 | SvREFCNT_dec_NN (osv); |
828 | SvREFCNT_dec_NN (osv); |
753 | } |
829 | } |
754 | |
830 | break; |
755 | return sv; |
|
|
756 | |
831 | |
757 | case CBOR_TAG_VALUE_SHAREDREF: |
832 | case CBOR_TAG_VALUE_SHAREDREF: |
758 | { |
833 | { |
759 | if ((*dec->cur >> 5) != 0) |
834 | if ((*dec->cur >> 5) != 0) |
760 | ERR ("corrupted CBOR data (sharedref index not an unsigned integer)"); |
835 | ERR ("corrupted CBOR data (sharedref index not an unsigned integer)"); |
761 | |
836 | |
762 | UV idx = decode_uint (dec); |
837 | UV idx = decode_uint (dec); |
763 | |
838 | |
764 | if (!dec->shareable || idx > AvFILLp (dec->shareable)) |
839 | if (!dec->shareable || (int)idx > AvFILLp (dec->shareable)) |
765 | ERR ("corrupted CBOR data (sharedref index out of bounds)"); |
840 | ERR ("corrupted CBOR data (sharedref index out of bounds)"); |
766 | |
841 | |
767 | return SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); |
842 | sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); |
768 | } |
843 | } |
|
|
844 | break; |
769 | |
845 | |
770 | case CBOR_TAG_PERL_OBJECT: |
846 | case CBOR_TAG_PERL_OBJECT: |
771 | { |
847 | { |
772 | sv = decode_sv (dec); |
848 | sv = decode_sv (dec); |
773 | |
849 | |
… | |
… | |
813 | sv = SvREFCNT_inc (POPs); |
889 | sv = SvREFCNT_inc (POPs); |
814 | |
890 | |
815 | PUTBACK; |
891 | PUTBACK; |
816 | |
892 | |
817 | FREETMPS; LEAVE; |
893 | FREETMPS; LEAVE; |
818 | |
|
|
819 | return sv; |
|
|
820 | } |
894 | } |
|
|
895 | break; |
821 | |
896 | |
822 | default: |
897 | default: |
823 | { |
898 | { |
824 | sv = decode_sv (dec); |
899 | sv = decode_sv (dec); |
825 | |
900 | |
… | |
… | |
829 | |
904 | |
830 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
905 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
831 | ? cbor_tagged_stash |
906 | ? cbor_tagged_stash |
832 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
907 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
833 | |
908 | |
834 | return sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
909 | sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
835 | } |
910 | } |
|
|
911 | break; |
836 | } |
912 | } |
|
|
913 | |
|
|
914 | return sv; |
837 | |
915 | |
838 | fail: |
916 | fail: |
839 | SvREFCNT_dec (sv); |
917 | SvREFCNT_dec (sv); |
840 | return &PL_sv_undef; |
918 | return &PL_sv_undef; |
841 | } |
919 | } |