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.35 by root, Sat Nov 30 17:19:34 2013 UTC vs.
Revision 1.39 by root, Sun Dec 1 14:45:03 2013 UTC

97}; 97};
98 98
99#define F_SHRINK 0x00000001UL 99#define F_SHRINK 0x00000001UL
100#define F_ALLOW_UNKNOWN 0x00000002UL 100#define F_ALLOW_UNKNOWN 0x00000002UL
101#define F_ALLOW_SHARING 0x00000004UL 101#define F_ALLOW_SHARING 0x00000004UL
102#define F_ALLOW_CYCLES 0x00000008UL
102#define F_PACK_STRINGS 0x00000008UL 103#define F_PACK_STRINGS 0x00000010UL
104#define F_VALIDATE_UTF8 0x00000020UL
103 105
104#define INIT_SIZE 32 // initial scalar size to be allocated 106#define INIT_SIZE 32 // initial scalar size to be allocated
105 107
106#define SB do { 108#define SB do {
107#define SE } while (0) 109#define SE } while (0)
228{ 230{
229 need (enc, 9); 231 need (enc, 9);
230 232
231 if (ecb_expect_true (len < LENGTH_EXT1)) 233 if (ecb_expect_true (len < LENGTH_EXT1))
232 *enc->cur++ = major | len; 234 *enc->cur++ = major | len;
233 else if (ecb_expect_true (len <= 0xff)) 235 else if (ecb_expect_true (len <= 0xffU))
234 { 236 {
235 *enc->cur++ = major | LENGTH_EXT1; 237 *enc->cur++ = major | LENGTH_EXT1;
236 *enc->cur++ = len; 238 *enc->cur++ = len;
237 } 239 }
238 else if (len <= 0xffff) 240 else if (len <= 0xffffU)
239 { 241 {
240 *enc->cur++ = major | LENGTH_EXT2; 242 *enc->cur++ = major | LENGTH_EXT2;
241 *enc->cur++ = len >> 8; 243 *enc->cur++ = len >> 8;
242 *enc->cur++ = len; 244 *enc->cur++ = len;
243 } 245 }
244 else if (len <= 0xffffffff) 246 else if (len <= 0xffffffffU)
245 { 247 {
246 *enc->cur++ = major | LENGTH_EXT4; 248 *enc->cur++ = major | LENGTH_EXT4;
247 *enc->cur++ = len >> 24; 249 *enc->cur++ = len >> 24;
248 *enc->cur++ = len >> 16; 250 *enc->cur++ = len >> 16;
249 *enc->cur++ = len >> 8; 251 *enc->cur++ = len >> 8;
627 U8 m = *dec->cur & MINOR_MASK; 629 U8 m = *dec->cur & MINOR_MASK;
628 ++dec->cur; 630 ++dec->cur;
629 631
630 if (ecb_expect_true (m < LENGTH_EXT1)) 632 if (ecb_expect_true (m < LENGTH_EXT1))
631 return m; 633 return m;
632 634 else if (ecb_expect_true (m == LENGTH_EXT1))
633 switch (m)
634 { 635 {
635 case LENGTH_EXT1:
636 WANT (1); 636 WANT (1);
637 dec->cur += 1; 637 dec->cur += 1;
638 return dec->cur[-1]; 638 return dec->cur[-1];
639 639 }
640 case LENGTH_EXT2: 640 else if (ecb_expect_true (m == LENGTH_EXT2))
641 {
641 WANT (2); 642 WANT (2);
642 dec->cur += 2; 643 dec->cur += 2;
643 return (((UV)dec->cur[-2]) << 8) 644 return (((UV)dec->cur[-2]) << 8)
644 | ((UV)dec->cur[-1]); 645 | ((UV)dec->cur[-1]);
645 646 }
646 case LENGTH_EXT4: 647 else if (ecb_expect_true (m == LENGTH_EXT4))
648 {
647 WANT (4); 649 WANT (4);
648 dec->cur += 4; 650 dec->cur += 4;
649 return (((UV)dec->cur[-4]) << 24) 651 return (((UV)dec->cur[-4]) << 24)
650 | (((UV)dec->cur[-3]) << 16) 652 | (((UV)dec->cur[-3]) << 16)
651 | (((UV)dec->cur[-2]) << 8) 653 | (((UV)dec->cur[-2]) << 8)
652 | ((UV)dec->cur[-1]); 654 | ((UV)dec->cur[-1]);
653 655 }
654 case LENGTH_EXT8: 656 else if (ecb_expect_true (m == LENGTH_EXT8))
657 {
655 WANT (8); 658 WANT (8);
656 dec->cur += 8; 659 dec->cur += 8;
657 660
658 return 661 return
659#if UVSIZE < 8 662#if UVSIZE < 8
660 0 663 0
661#else 664#else
662 (((UV)dec->cur[-8]) << 56) 665 (((UV)dec->cur[-8]) << 56)
663 | (((UV)dec->cur[-7]) << 48) 666 | (((UV)dec->cur[-7]) << 48)
664 | (((UV)dec->cur[-6]) << 40) 667 | (((UV)dec->cur[-6]) << 40)
665 | (((UV)dec->cur[-5]) << 32) 668 | (((UV)dec->cur[-5]) << 32)
666#endif 669#endif
667 | (((UV)dec->cur[-4]) << 24) 670 | (((UV)dec->cur[-4]) << 24)
668 | (((UV)dec->cur[-3]) << 16) 671 | (((UV)dec->cur[-3]) << 16)
669 | (((UV)dec->cur[-2]) << 8) 672 | (((UV)dec->cur[-2]) << 8)
670 | ((UV)dec->cur[-1]); 673 | ((UV)dec->cur[-1]);
671 674 }
672 default: 675 else
673 ERR ("corrupted CBOR data (unsupported integer minor encoding)"); 676 ERR ("corrupted CBOR data (unsupported integer minor encoding)");
674 }
675 677
676fail: 678fail:
677 return 0; 679 return 0;
678} 680}
679 681
705 } 707 }
706 else 708 else
707 { 709 {
708 int i, len = decode_uint (dec); 710 int i, len = decode_uint (dec);
709 711
712 WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays
710 av_fill (av, len - 1); 713 av_fill (av, len - 1);
711 714
712 for (i = 0; i < len; ++i) 715 for (i = 0; i < len; ++i)
713 AvARRAY (av)[i] = decode_sv (dec); 716 AvARRAY (av)[i] = decode_sv (dec);
714 } 717 }
727{ 730{
728 // for speed reasons, we specialcase single-string 731 // for speed reasons, we specialcase single-string
729 // byte or utf-8 strings as keys, but only when !stringref 732 // byte or utf-8 strings as keys, but only when !stringref
730 733
731 if (ecb_expect_true (!dec->stringref)) 734 if (ecb_expect_true (!dec->stringref))
732 if ((*dec->cur - MAJOR_BYTES) <= 27) 735 if (ecb_expect_true ((*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
733 { 736 {
734 I32 len = decode_uint (dec); 737 I32 len = decode_uint (dec);
735 char *key = (char *)dec->cur; 738 char *key = (char *)dec->cur;
736 739
737 dec->cur += len; 740 dec->cur += len;
738 741
739 if (ecb_expect_false (dec->stringref))
740 av_push (dec->stringref, newSVpvn (key, len));
741
742 hv_store (hv, key, len, decode_sv (dec), 0); 742 hv_store (hv, key, len, decode_sv (dec), 0);
743 743
744 return; 744 return;
745 } 745 }
746 else if ((*dec->cur - MAJOR_TEXT) <= 27) 746 else if (ecb_expect_true ((*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
747 { 747 {
748 I32 len = decode_uint (dec); 748 I32 len = decode_uint (dec);
749 char *key = (char *)dec->cur; 749 char *key = (char *)dec->cur;
750 750
751 dec->cur += len; 751 dec->cur += len;
752 752
753 if (ecb_expect_false (dec->stringref)) 753 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
754 av_push (dec->stringref, newSVpvn_utf8 (key, len, 1)); 754 if (!is_utf8_string (key, len))
755 ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
755 756
756 hv_store (hv, key, -len, decode_sv (dec), 0); 757 hv_store (hv, key, -len, decode_sv (dec), 0);
757 758
758 return; 759 return;
759 } 760 }
761 SV *k = decode_sv (dec); 762 SV *k = decode_sv (dec);
762 SV *v = decode_sv (dec); 763 SV *v = decode_sv (dec);
763 764
764 hv_store_ent (hv, k, v, 0); 765 hv_store_ent (hv, k, v, 0);
765 SvREFCNT_dec (k); 766 SvREFCNT_dec (k);
767
768fail:
769 ;
766} 770}
767 771
768static SV * 772static SV *
769decode_hv (dec_t *dec) 773decode_hv (dec_t *dec)
770{ 774{
852 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1)) 856 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
853 av_push (dec->stringref, SvREFCNT_inc_NN (sv)); 857 av_push (dec->stringref, SvREFCNT_inc_NN (sv));
854 } 858 }
855 859
856 if (utf8) 860 if (utf8)
861 {
862 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
863 if (!is_utf8_string (SvPVX (sv), SvCUR (sv)))
864 ERR ("corrupted CBOR data (invalid UTF-8 in text string)");
865
857 SvUTF8_on (sv); 866 SvUTF8_on (sv);
867 }
858 868
859 return sv; 869 return sv;
860 870
861fail: 871fail:
862 SvREFCNT_dec (sv); 872 SvREFCNT_dec (sv);
911 case CBOR_TAG_VALUE_SHAREABLE: 921 case CBOR_TAG_VALUE_SHAREABLE:
912 { 922 {
913 if (ecb_expect_false (!dec->shareable)) 923 if (ecb_expect_false (!dec->shareable))
914 dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); 924 dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
915 925
926 if (dec->cbor.flags & F_ALLOW_CYCLES)
927 {
916 sv = newSV (0); 928 sv = newSV (0);
917 av_push (dec->shareable, SvREFCNT_inc_NN (sv)); 929 av_push (dec->shareable, SvREFCNT_inc_NN (sv));
918 930
919 SV *osv = decode_sv (dec); 931 SV *osv = decode_sv (dec);
920 sv_setsv (sv, osv); 932 sv_setsv (sv, osv);
921 SvREFCNT_dec_NN (osv); 933 SvREFCNT_dec_NN (osv);
934 }
935 else
936 {
937 av_push (dec->shareable, &PL_sv_undef);
938 int idx = AvFILLp (dec->shareable);
939 sv = decode_sv (dec);
940 av_store (dec->shareable, idx, SvREFCNT_inc_NN (sv));
941 }
922 } 942 }
923 break; 943 break;
924 944
925 case CBOR_TAG_VALUE_SHAREDREF: 945 case CBOR_TAG_VALUE_SHAREDREF:
926 { 946 {
931 951
932 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable)) 952 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable))
933 ERR ("corrupted CBOR data (sharedref index out of bounds)"); 953 ERR ("corrupted CBOR data (sharedref index out of bounds)");
934 954
935 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); 955 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
956
957 if (sv == &PL_sv_undef)
958 ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
936 } 959 }
937 break; 960 break;
938 961
939 case CBOR_TAG_PERL_OBJECT: 962 case CBOR_TAG_PERL_OBJECT:
940 { 963 {
1148 if (dec.cur != dec.end && !dec.err) 1171 if (dec.cur != dec.end && !dec.err)
1149 dec.err = "garbage after CBOR object"; 1172 dec.err = "garbage after CBOR object";
1150 1173
1151 if (dec.err) 1174 if (dec.err)
1152 { 1175 {
1176 if (dec.shareable)
1177 {
1178 // need to break cyclic links, which whould all be in shareable
1179 int i;
1180 SV **svp;
1181
1182 for (i = av_len (dec.shareable) + 1; i--; )
1183 if ((svp = av_fetch (dec.shareable, i, 0)))
1184 sv_setsv (*svp, &PL_sv_undef);
1185 }
1186
1153 SvREFCNT_dec (sv); 1187 SvREFCNT_dec (sv);
1154 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); 1188 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1155 } 1189 }
1156 1190
1157 sv = sv_2mortal (sv); 1191 sv = sv_2mortal (sv);
1206void shrink (CBOR *self, int enable = 1) 1240void shrink (CBOR *self, int enable = 1)
1207 ALIAS: 1241 ALIAS:
1208 shrink = F_SHRINK 1242 shrink = F_SHRINK
1209 allow_unknown = F_ALLOW_UNKNOWN 1243 allow_unknown = F_ALLOW_UNKNOWN
1210 allow_sharing = F_ALLOW_SHARING 1244 allow_sharing = F_ALLOW_SHARING
1245 allow_cycles = F_ALLOW_CYCLES
1211 pack_strings = F_PACK_STRINGS 1246 pack_strings = F_PACK_STRINGS
1247 validate_utf8 = F_VALIDATE_UTF8
1212 PPCODE: 1248 PPCODE:
1213{ 1249{
1214 if (enable) 1250 if (enable)
1215 self->flags |= ix; 1251 self->flags |= ix;
1216 else 1252 else
1222void get_shrink (CBOR *self) 1258void get_shrink (CBOR *self)
1223 ALIAS: 1259 ALIAS:
1224 get_shrink = F_SHRINK 1260 get_shrink = F_SHRINK
1225 get_allow_unknown = F_ALLOW_UNKNOWN 1261 get_allow_unknown = F_ALLOW_UNKNOWN
1226 get_allow_sharing = F_ALLOW_SHARING 1262 get_allow_sharing = F_ALLOW_SHARING
1263 get_allow_cycles = F_ALLOW_CYCLES
1227 get_pack_strings = F_PACK_STRINGS 1264 get_pack_strings = F_PACK_STRINGS
1265 get_validate_utf8 = F_VALIDATE_UTF8
1228 PPCODE: 1266 PPCODE:
1229 XPUSHs (boolSV (self->flags & ix)); 1267 XPUSHs (boolSV (self->flags & ix));
1230 1268
1231void max_depth (CBOR *self, U32 max_depth = 0x80000000UL) 1269void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1232 PPCODE: 1270 PPCODE:
1288 cbor_free (self); 1326 cbor_free (self);
1289 1327
1290PROTOTYPES: ENABLE 1328PROTOTYPES: ENABLE
1291 1329
1292void encode_cbor (SV *scalar) 1330void encode_cbor (SV *scalar)
1331 ALIAS:
1332 encode_cbor = 0
1333 encode_cbor_sharing = F_ALLOW_SHARING
1293 PPCODE: 1334 PPCODE:
1294{ 1335{
1295 CBOR cbor; 1336 CBOR cbor;
1296 cbor_init (&cbor); 1337 cbor_init (&cbor);
1338 cbor.flags |= ix;
1297 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN; 1339 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1298 XPUSHs (scalar); 1340 XPUSHs (scalar);
1299} 1341}
1300 1342
1301void decode_cbor (SV *cborstr) 1343void decode_cbor (SV *cborstr)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines