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.19 by root, Wed Nov 20 02:03:09 2013 UTC vs.
Revision 1.20 by root, Wed Nov 20 11:06:42 2013 UTC

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
145ecb_inline void 146ecb_inline void
237 } 238 }
238 239
239 --enc->depth; 240 --enc->depth;
240} 241}
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));
250}
251
242static void 252static void
243encode_hv (enc_t *enc, HV *hv) 253encode_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
721fail: 768fail:
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
838fail: 916fail:
839 SvREFCNT_dec (sv); 917 SvREFCNT_dec (sv);
840 return &PL_sv_undef; 918 return &PL_sv_undef;
841} 919}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines