… | |
… | |
26 | enum cbor_tag |
26 | enum cbor_tag |
27 | { |
27 | { |
28 | // inofficial extensions (pending iana registration) |
28 | // inofficial extensions (pending iana registration) |
29 | CBOR_TAG_PERL_OBJECT = 24, // http://cbor.schmorp.de/perl-object |
29 | CBOR_TAG_PERL_OBJECT = 24, // http://cbor.schmorp.de/perl-object |
30 | CBOR_TAG_GENERIC_OBJECT = 25, // http://cbor.schmorp.de/generic-object |
30 | CBOR_TAG_GENERIC_OBJECT = 25, // http://cbor.schmorp.de/generic-object |
31 | CBOR_TAG_VALUE_SHARABLE = 26, // http://cbor.schmorp.de/value-sharing |
31 | CBOR_TAG_VALUE_SHAREABLE = 26, // http://cbor.schmorp.de/value-sharing |
32 | CBOR_TAG_VALUE_SHAREDREF = 27, // http://cbor.schmorp.de/value-sharing |
32 | CBOR_TAG_VALUE_SHAREDREF = 27, // http://cbor.schmorp.de/value-sharing |
33 | CBOR_TAG_STRINGREF_NAMESPACE = 65537, // http://cbor.schmorp.de/stringref |
33 | CBOR_TAG_STRINGREF_NAMESPACE = 65537, // http://cbor.schmorp.de/stringref |
34 | CBOR_TAG_STRINGREF = 28, // http://cbor.schmorp.de/stringref |
34 | CBOR_TAG_STRINGREF = 28, // http://cbor.schmorp.de/stringref |
35 | CBOR_TAG_INDIRECTION = 22098, // http://cbor.schmorp.de/indirection |
35 | CBOR_TAG_INDIRECTION = 22098, // http://cbor.schmorp.de/indirection |
36 | |
36 | |
… | |
… | |
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 *sharable; // ptr => index, or 0 |
142 | HV *shareable; // ptr => index, or 0 |
142 | HV *sharable_idx; |
143 | UV shareable_idx; |
143 | } enc_t; |
144 | } enc_t; |
144 | |
145 | |
145 | ecb_inline void |
146 | ecb_inline void |
146 | need (enc_t *enc, STRLEN len) |
147 | need (enc_t *enc, STRLEN len) |
147 | { |
148 | { |
… | |
… | |
214 | encode_tag (enc_t *enc, UV tag) |
215 | encode_tag (enc_t *enc, UV tag) |
215 | { |
216 | { |
216 | encode_uint (enc, 0xc0, tag); |
217 | encode_uint (enc, 0xc0, tag); |
217 | } |
218 | } |
218 | |
219 | |
219 | static int |
|
|
220 | encode_sharable2 (enc_t *enc, SV *sv) |
|
|
221 | { |
|
|
222 | if (!enc->sharable) |
|
|
223 | enc->sharable = (HV *)sv_2mortal ((SV *)newHV ()); |
|
|
224 | |
|
|
225 | SV **svp = hv_fetch (enc->sharable, &sv, sizeof (sv), 1); |
|
|
226 | |
|
|
227 | if (SvOK (*svp)) |
|
|
228 | { |
|
|
229 | encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF); |
|
|
230 | encode_uint (enc, 0x00, SvUV (*svp)); |
|
|
231 | |
|
|
232 | return 1; |
|
|
233 | } |
|
|
234 | else |
|
|
235 | { |
|
|
236 | sv_setuv (*svp, enc->sharable_idx++); |
|
|
237 | encode_tag (enc, CBOR_TAG_VALUE_SHARABLE); |
|
|
238 | |
|
|
239 | return 0; |
|
|
240 | } |
|
|
241 | } |
|
|
242 | |
|
|
243 | ecb_inline int |
|
|
244 | encode_sharable (enc_t *enc, SV *sv) |
|
|
245 | { |
|
|
246 | if (ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING) |
|
|
247 | && ecb_expect_false (SvREFCNT (sv) > 1)) |
|
|
248 | return encode_sharable2 (enc, sv); |
|
|
249 | |
|
|
250 | return 0; |
|
|
251 | } |
|
|
252 | |
|
|
253 | static void encode_sv (enc_t *enc, SV *sv); |
220 | static void encode_sv (enc_t *enc, SV *sv); |
254 | |
221 | |
255 | static void |
222 | static void |
256 | encode_av (enc_t *enc, AV *av) |
223 | encode_av (enc_t *enc, AV *av) |
257 | { |
224 | { |
… | |
… | |
269 | SV **svp = av_fetch (av, i, 0); |
236 | SV **svp = av_fetch (av, i, 0); |
270 | encode_sv (enc, svp ? *svp : &PL_sv_undef); |
237 | encode_sv (enc, svp ? *svp : &PL_sv_undef); |
271 | } |
238 | } |
272 | |
239 | |
273 | --enc->depth; |
240 | --enc->depth; |
|
|
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)); |
274 | } |
250 | } |
275 | |
251 | |
276 | static void |
252 | static void |
277 | encode_hv (enc_t *enc, HV *hv) |
253 | encode_hv (enc_t *enc, HV *hv) |
278 | { |
254 | { |
… | |
… | |
291 | else |
267 | else |
292 | encode_uint (enc, 0xa0, pairs); |
268 | encode_uint (enc, 0xa0, pairs); |
293 | |
269 | |
294 | while ((he = hv_iternext (hv))) |
270 | while ((he = hv_iternext (hv))) |
295 | { |
271 | { |
|
|
272 | if (ecb_expect_false (enc->cbor.flags & (F_DEDUP_STRINGS | F_DEDUP_KEYS))) |
|
|
273 | { |
|
|
274 | SV **svp; |
|
|
275 | |
296 | if (HeKLEN (he) == HEf_SVKEY) |
276 | if (HeKLEN (he) == HEf_SVKEY) |
297 | 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 | } |
298 | else |
293 | else |
299 | encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he)); |
294 | encode_he (enc, he); |
300 | |
295 | |
301 | 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)); |
302 | } |
297 | } |
303 | |
298 | |
304 | if (mg) |
299 | if (mg) |
… | |
… | |
309 | |
304 | |
310 | // encode objects, arrays and special \0=false and \1=true values. |
305 | // encode objects, arrays and special \0=false and \1=true values. |
311 | static void |
306 | static void |
312 | encode_rv (enc_t *enc, SV *sv) |
307 | encode_rv (enc_t *enc, SV *sv) |
313 | { |
308 | { |
314 | svtype svt; |
|
|
315 | |
|
|
316 | SvGETMAGIC (sv); |
309 | SvGETMAGIC (sv); |
|
|
310 | |
|
|
311 | if (ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING) |
|
|
312 | && ecb_expect_false (SvREFCNT (sv) > 1)) |
|
|
313 | { |
|
|
314 | if (!enc->shareable) |
|
|
315 | enc->shareable = (HV *)sv_2mortal ((SV *)newHV ()); |
|
|
316 | |
|
|
317 | SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1); |
|
|
318 | |
|
|
319 | if (SvOK (*svp)) |
|
|
320 | { |
|
|
321 | encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF); |
|
|
322 | encode_uint (enc, 0x00, SvUV (*svp)); |
|
|
323 | return; |
|
|
324 | } |
|
|
325 | else |
|
|
326 | { |
|
|
327 | sv_setuv (*svp, enc->shareable_idx); |
|
|
328 | ++enc->shareable_idx; |
|
|
329 | encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE); |
|
|
330 | } |
|
|
331 | } |
|
|
332 | |
317 | svt = SvTYPE (sv); |
333 | svtype svt = SvTYPE (sv); |
318 | |
|
|
319 | if (encode_sharable (enc, sv)) |
|
|
320 | return; |
|
|
321 | |
334 | |
322 | if (ecb_expect_false (SvOBJECT (sv))) |
335 | if (ecb_expect_false (SvOBJECT (sv))) |
323 | { |
336 | { |
324 | HV *boolean_stash = !CBOR_SLOW || types_boolean_stash |
337 | HV *boolean_stash = !CBOR_SLOW || types_boolean_stash |
325 | ? types_boolean_stash |
338 | ? types_boolean_stash |
… | |
… | |
452 | static void |
465 | static void |
453 | encode_sv (enc_t *enc, SV *sv) |
466 | encode_sv (enc_t *enc, SV *sv) |
454 | { |
467 | { |
455 | SvGETMAGIC (sv); |
468 | SvGETMAGIC (sv); |
456 | |
469 | |
457 | if (encode_sharable (enc, sv)) |
|
|
458 | return; |
|
|
459 | |
|
|
460 | if (SvPOKp (sv)) |
470 | if (SvPOKp (sv)) |
461 | { |
471 | { |
462 | STRLEN len; |
472 | STRLEN len; |
463 | char *str = SvPV (sv, len); |
473 | char *str = SvPV (sv, len); |
464 | encode_str (enc, SvUTF8 (sv), str, len); |
474 | encode_str (enc, SvUTF8 (sv), str, len); |
… | |
… | |
494 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
504 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
495 | enc.cur = SvPVX (enc.sv); |
505 | enc.cur = SvPVX (enc.sv); |
496 | enc.end = SvEND (enc.sv); |
506 | enc.end = SvEND (enc.sv); |
497 | |
507 | |
498 | 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 | |
499 | encode_sv (&enc, scalar); |
517 | encode_sv (&enc, scalar); |
500 | |
518 | |
501 | SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); |
519 | SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); |
502 | *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 |
503 | |
521 | |
… | |
… | |
517 | U8 *end; // end of input string |
535 | U8 *end; // end of input string |
518 | const char *err; // parse error, if != 0 |
536 | const char *err; // parse error, if != 0 |
519 | CBOR cbor; |
537 | CBOR cbor; |
520 | U32 depth; // recursion depth |
538 | U32 depth; // recursion depth |
521 | U32 maxdepth; // recursion depth limit |
539 | U32 maxdepth; // recursion depth limit |
522 | AV *sharable; |
540 | AV *shareable; |
|
|
541 | AV *stringref; |
523 | } dec_t; |
542 | } dec_t; |
524 | |
543 | |
525 | #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 |
526 | |
545 | |
527 | #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") |
… | |
… | |
634 | I32 len = decode_uint (dec); |
653 | I32 len = decode_uint (dec); |
635 | char *key = (char *)dec->cur; |
654 | char *key = (char *)dec->cur; |
636 | |
655 | |
637 | dec->cur += len; |
656 | dec->cur += len; |
638 | |
657 | |
|
|
658 | if (ecb_expect_false (dec->stringref)) |
|
|
659 | av_push (dec->stringref, newSVpvn (key, len)); |
|
|
660 | |
639 | hv_store (hv, key, len, decode_sv (dec), 0); |
661 | hv_store (hv, key, len, decode_sv (dec), 0); |
640 | } |
662 | } |
641 | else if (*dec->cur >= 0x60 && *dec->cur <= 0x60 + 27) |
663 | else if (*dec->cur >= 0x60 && *dec->cur <= 0x60 + 27) |
642 | { |
664 | { |
643 | I32 len = decode_uint (dec); |
665 | I32 len = decode_uint (dec); |
644 | char *key = (char *)dec->cur; |
666 | char *key = (char *)dec->cur; |
645 | |
667 | |
646 | 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)); |
647 | |
672 | |
648 | hv_store (hv, key, -len, decode_sv (dec), 0); |
673 | hv_store (hv, key, -len, decode_sv (dec), 0); |
649 | } |
674 | } |
650 | else |
675 | else |
651 | { |
676 | { |
… | |
… | |
733 | } |
758 | } |
734 | |
759 | |
735 | if (utf8) |
760 | if (utf8) |
736 | SvUTF8_on (sv); |
761 | SvUTF8_on (sv); |
737 | |
762 | |
|
|
763 | if (ecb_expect_false (dec->stringref)) |
|
|
764 | av_push (dec->stringref, SvREFCNT_inc_NN (sv)); |
|
|
765 | |
738 | return sv; |
766 | return sv; |
739 | |
767 | |
740 | fail: |
768 | fail: |
741 | SvREFCNT_dec (sv); |
769 | SvREFCNT_dec (sv); |
742 | return &PL_sv_undef; |
770 | return &PL_sv_undef; |
743 | } |
771 | } |
744 | |
772 | |
745 | static SV * |
773 | static SV * |
746 | decode_tagged (dec_t *dec) |
774 | decode_tagged (dec_t *dec) |
747 | { |
775 | { |
|
|
776 | SV *sv = 0; |
748 | UV tag = decode_uint (dec); |
777 | UV tag = decode_uint (dec); |
749 | SV *sv = decode_sv (dec); |
778 | |
|
|
779 | WANT (1); |
750 | |
780 | |
751 | switch (tag) |
781 | switch (tag) |
752 | { |
782 | { |
753 | case CBOR_TAG_MAGIC: |
783 | case CBOR_TAG_MAGIC: |
754 | return sv; |
784 | sv = decode_sv (dec); |
|
|
785 | break; |
755 | |
786 | |
756 | case CBOR_TAG_INDIRECTION: |
787 | case CBOR_TAG_INDIRECTION: |
757 | return newRV_noinc (sv); |
788 | sv = newRV_noinc (decode_sv (dec)); |
|
|
789 | break; |
758 | |
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; |
|
|
817 | |
759 | case CBOR_TAG_VALUE_SHARABLE: |
818 | case CBOR_TAG_VALUE_SHAREABLE: |
|
|
819 | { |
760 | if (ecb_expect_false (!dec->sharable)) |
820 | if (ecb_expect_false (!dec->shareable)) |
761 | dec->sharable = (AV *)sv_2mortal ((SV *)newAV ()); |
821 | dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); |
762 | |
822 | |
|
|
823 | sv = newSV (0); |
763 | av_push (dec->sharable, SvREFCNT_inc_NN (sv)); |
824 | av_push (dec->shareable, SvREFCNT_inc_NN (sv)); |
764 | |
825 | |
765 | return sv; |
826 | SV *osv = decode_sv (dec); |
|
|
827 | sv_setsv (sv, osv); |
|
|
828 | SvREFCNT_dec_NN (osv); |
|
|
829 | } |
|
|
830 | break; |
766 | |
831 | |
767 | case CBOR_TAG_VALUE_SHAREDREF: |
832 | case CBOR_TAG_VALUE_SHAREDREF: |
768 | { |
833 | { |
769 | // TODO: should verify that the sv atcually was a CBOR unsigned integer |
834 | if ((*dec->cur >> 5) != 0) |
770 | UV idx = SvUV (sv); |
835 | ERR ("corrupted CBOR data (sharedref index not an unsigned integer)"); |
771 | |
836 | |
|
|
837 | UV idx = decode_uint (dec); |
|
|
838 | |
772 | if (!dec->sharable || idx > AvFILLp (dec->sharable)) |
839 | if (!dec->shareable || (int)idx > AvFILLp (dec->shareable)) |
773 | ERR ("corrupted CBOR data (sharedref index out of bounds)"); |
840 | ERR ("corrupted CBOR data (sharedref index out of bounds)"); |
774 | |
841 | |
775 | SvREFCNT_dec (sv); |
|
|
776 | |
|
|
777 | return SvREFCNT_inc_NN (AvARRAY (dec->sharable)[idx]); |
842 | sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); |
778 | } |
843 | } |
|
|
844 | break; |
779 | |
845 | |
780 | case CBOR_TAG_PERL_OBJECT: |
846 | case CBOR_TAG_PERL_OBJECT: |
781 | { |
847 | { |
|
|
848 | sv = decode_sv (dec); |
|
|
849 | |
782 | if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) |
850 | if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) |
783 | ERR ("corrupted CBOR data (non-array perl object)"); |
851 | ERR ("corrupted CBOR data (non-array perl object)"); |
784 | |
852 | |
785 | AV *av = (AV *)SvRV (sv); |
853 | AV *av = (AV *)SvRV (sv); |
786 | int len = av_len (av) + 1; |
854 | int len = av_len (av) + 1; |
… | |
… | |
821 | sv = SvREFCNT_inc (POPs); |
889 | sv = SvREFCNT_inc (POPs); |
822 | |
890 | |
823 | PUTBACK; |
891 | PUTBACK; |
824 | |
892 | |
825 | FREETMPS; LEAVE; |
893 | FREETMPS; LEAVE; |
826 | |
|
|
827 | return sv; |
|
|
828 | } |
894 | } |
|
|
895 | break; |
829 | |
896 | |
830 | default: |
897 | default: |
831 | { |
898 | { |
|
|
899 | sv = decode_sv (dec); |
|
|
900 | |
832 | AV *av = newAV (); |
901 | AV *av = newAV (); |
833 | av_push (av, newSVuv (tag)); |
902 | av_push (av, newSVuv (tag)); |
834 | av_push (av, sv); |
903 | av_push (av, sv); |
835 | |
904 | |
836 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
905 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
837 | ? cbor_tagged_stash |
906 | ? cbor_tagged_stash |
838 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
907 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
839 | |
908 | |
840 | return sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
909 | sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
841 | } |
910 | } |
|
|
911 | break; |
842 | } |
912 | } |
|
|
913 | |
|
|
914 | return sv; |
843 | |
915 | |
844 | fail: |
916 | fail: |
845 | SvREFCNT_dec (sv); |
917 | SvREFCNT_dec (sv); |
846 | return &PL_sv_undef; |
918 | return &PL_sv_undef; |
847 | } |
919 | } |