ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
(Generate patch)

Comparing CBOR-XS/XS.xs (file contents):
Revision 1.18 by root, Wed Nov 20 01:09:46 2013 UTC vs.
Revision 1.20 by root, Wed Nov 20 11:06:42 2013 UTC

26enum cbor_tag 26enum 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
145ecb_inline void 146ecb_inline void
146need (enc_t *enc, STRLEN len) 147need (enc_t *enc, STRLEN len)
147{ 148{
214encode_tag (enc_t *enc, UV tag) 215encode_tag (enc_t *enc, UV tag)
215{ 216{
216 encode_uint (enc, 0xc0, tag); 217 encode_uint (enc, 0xc0, tag);
217} 218}
218 219
219static int
220encode_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
243ecb_inline int
244encode_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
253static void encode_sv (enc_t *enc, SV *sv); 220static void encode_sv (enc_t *enc, SV *sv);
254 221
255static void 222static void
256encode_av (enc_t *enc, AV *av) 223encode_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
243ecb_inline void
244encode_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
276static void 252static void
277encode_hv (enc_t *enc, HV *hv) 253encode_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.
311static void 306static void
312encode_rv (enc_t *enc, SV *sv) 307encode_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
452static void 465static void
453encode_sv (enc_t *enc, SV *sv) 466encode_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
740fail: 768fail:
741 SvREFCNT_dec (sv); 769 SvREFCNT_dec (sv);
742 return &PL_sv_undef; 770 return &PL_sv_undef;
743} 771}
744 772
745static SV * 773static SV *
746decode_tagged (dec_t *dec) 774decode_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
844fail: 916fail:
845 SvREFCNT_dec (sv); 917 SvREFCNT_dec (sv);
846 return &PL_sv_undef; 918 return &PL_sv_undef;
847} 919}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines