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.50 by root, Thu Feb 25 02:29:22 2016 UTC

7#include <stdlib.h> 7#include <stdlib.h>
8#include <stdio.h> 8#include <stdio.h>
9#include <limits.h> 9#include <limits.h>
10#include <float.h> 10#include <float.h>
11 11
12#define ECB_NO_THREADS 1
12#include "ecb.h" 13#include "ecb.h"
13 14
14// compatibility with perl <5.18 15// compatibility with perl <5.18
15#ifndef HvNAMELEN_get 16#ifndef HvNAMELEN_get
16# define HvNAMELEN_get(hv) strlen (HvNAME (hv)) 17# define HvNAMELEN_get(hv) strlen (HvNAME (hv))
97}; 98};
98 99
99#define F_SHRINK 0x00000001UL 100#define F_SHRINK 0x00000001UL
100#define F_ALLOW_UNKNOWN 0x00000002UL 101#define F_ALLOW_UNKNOWN 0x00000002UL
101#define F_ALLOW_SHARING 0x00000004UL 102#define F_ALLOW_SHARING 0x00000004UL
103#define F_ALLOW_CYCLES 0x00000008UL
102#define F_PACK_STRINGS 0x00000008UL 104#define F_PACK_STRINGS 0x00000010UL
105#define F_VALIDATE_UTF8 0x00000020UL
103 106
104#define INIT_SIZE 32 // initial scalar size to be allocated 107#define INIT_SIZE 32 // initial scalar size to be allocated
105 108
106#define SB do { 109#define SB do {
107#define SE } while (0) 110#define SE } while (0)
126typedef struct { 129typedef struct {
127 U32 flags; 130 U32 flags;
128 U32 max_depth; 131 U32 max_depth;
129 STRLEN max_size; 132 STRLEN max_size;
130 SV *filter; 133 SV *filter;
134
135 // for the incremental parser
136 STRLEN incr_pos; // the current offset into the text
137 STRLEN incr_need; // minimum bytes needed to decode
138 AV *incr_count; // for every nesting level, the number of outstanding values, or -1 for indef.
131} CBOR; 139} CBOR;
132 140
133ecb_inline void 141ecb_inline void
134cbor_init (CBOR *cbor) 142cbor_init (CBOR *cbor)
135{ 143{
139 147
140ecb_inline void 148ecb_inline void
141cbor_free (CBOR *cbor) 149cbor_free (CBOR *cbor)
142{ 150{
143 SvREFCNT_dec (cbor->filter); 151 SvREFCNT_dec (cbor->filter);
152 SvREFCNT_dec (cbor->incr_count);
144} 153}
145 154
146///////////////////////////////////////////////////////////////////////////// 155/////////////////////////////////////////////////////////////////////////////
147// utility functions 156// utility functions
148 157
228{ 237{
229 need (enc, 9); 238 need (enc, 9);
230 239
231 if (ecb_expect_true (len < LENGTH_EXT1)) 240 if (ecb_expect_true (len < LENGTH_EXT1))
232 *enc->cur++ = major | len; 241 *enc->cur++ = major | len;
233 else if (ecb_expect_true (len <= 0xff)) 242 else if (ecb_expect_true (len <= 0xffU))
234 { 243 {
235 *enc->cur++ = major | LENGTH_EXT1; 244 *enc->cur++ = major | LENGTH_EXT1;
236 *enc->cur++ = len; 245 *enc->cur++ = len;
237 } 246 }
238 else if (len <= 0xffff) 247 else if (len <= 0xffffU)
239 { 248 {
240 *enc->cur++ = major | LENGTH_EXT2; 249 *enc->cur++ = major | LENGTH_EXT2;
241 *enc->cur++ = len >> 8; 250 *enc->cur++ = len >> 8;
242 *enc->cur++ = len; 251 *enc->cur++ = len;
243 } 252 }
244 else if (len <= 0xffffffff) 253 else if (len <= 0xffffffffU)
245 { 254 {
246 *enc->cur++ = major | LENGTH_EXT4; 255 *enc->cur++ = major | LENGTH_EXT4;
247 *enc->cur++ = len >> 24; 256 *enc->cur++ = len >> 24;
248 *enc->cur++ = len >> 16; 257 *enc->cur++ = len >> 16;
249 *enc->cur++ = len >> 8; 258 *enc->cur++ = len >> 8;
315 324
316 ++enc->depth; 325 ++enc->depth;
317 326
318 encode_uint (enc, MAJOR_ARRAY, len + 1); 327 encode_uint (enc, MAJOR_ARRAY, len + 1);
319 328
329 if (SvMAGICAL (av))
320 for (i = 0; i <= len; ++i) 330 for (i = 0; i <= len; ++i)
321 { 331 {
322 SV **svp = av_fetch (av, i, 0); 332 SV **svp = av_fetch (av, i, 0);
323 encode_sv (enc, svp ? *svp : &PL_sv_undef); 333 encode_sv (enc, svp ? *svp : &PL_sv_undef);
324 } 334 }
335 else
336 for (i = 0; i <= len; ++i)
337 {
338 SV *sv = AvARRAY (av)[i];
339 encode_sv (enc, sv ? sv : &PL_sv_undef);
340 }
325 341
326 --enc->depth; 342 --enc->depth;
327} 343}
328 344
329static void 345static void
433 449
434 if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0))) 450 if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0)))
435 { 451 {
436 dSP; 452 dSP;
437 453
438 ENTER; SAVETMPS; PUSHMARK (SP); 454 ENTER; SAVETMPS;
455 PUSHMARK (SP);
439 // we re-bless the reference to get overload and other niceties right 456 // we re-bless the reference to get overload and other niceties right
440 XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); 457 XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
441 458
442 PUTBACK; 459 PUTBACK;
443 // G_SCALAR ensures that return value is 1 460 // G_SCALAR ensures that return value is 1
456 } 473 }
457 else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0) 474 else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0)
458 { 475 {
459 dSP; 476 dSP;
460 477
461 ENTER; SAVETMPS; PUSHMARK (SP); 478 ENTER; SAVETMPS;
479 SAVESTACK_POS ();
480 PUSHMARK (SP);
462 EXTEND (SP, 2); 481 EXTEND (SP, 2);
463 // we re-bless the reference to get overload and other niceties right 482 // we re-bless the reference to get overload and other niceties right
464 PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); 483 PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
465 PUSHs (sv_cbor); 484 PUSHs (sv_cbor);
466 485
568} 587}
569 588
570static SV * 589static SV *
571encode_cbor (SV *scalar, CBOR *cbor) 590encode_cbor (SV *scalar, CBOR *cbor)
572{ 591{
573 enc_t enc = { }; 592 enc_t enc = { 0 };
574 593
575 enc.cbor = *cbor; 594 enc.cbor = *cbor;
576 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); 595 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
577 enc.cur = SvPVX (enc.sv); 596 enc.cur = SvPVX (enc.sv);
578 enc.end = SvEND (enc.sv); 597 enc.end = SvEND (enc.sv);
627 U8 m = *dec->cur & MINOR_MASK; 646 U8 m = *dec->cur & MINOR_MASK;
628 ++dec->cur; 647 ++dec->cur;
629 648
630 if (ecb_expect_true (m < LENGTH_EXT1)) 649 if (ecb_expect_true (m < LENGTH_EXT1))
631 return m; 650 return m;
632 651 else if (ecb_expect_true (m == LENGTH_EXT1))
633 switch (m)
634 { 652 {
635 case LENGTH_EXT1:
636 WANT (1); 653 WANT (1);
637 dec->cur += 1; 654 dec->cur += 1;
638 return dec->cur[-1]; 655 return dec->cur[-1];
639 656 }
640 case LENGTH_EXT2: 657 else if (ecb_expect_true (m == LENGTH_EXT2))
658 {
641 WANT (2); 659 WANT (2);
642 dec->cur += 2; 660 dec->cur += 2;
643 return (((UV)dec->cur[-2]) << 8) 661 return (((UV)dec->cur[-2]) << 8)
644 | ((UV)dec->cur[-1]); 662 | ((UV)dec->cur[-1]);
645 663 }
646 case LENGTH_EXT4: 664 else if (ecb_expect_true (m == LENGTH_EXT4))
665 {
647 WANT (4); 666 WANT (4);
648 dec->cur += 4; 667 dec->cur += 4;
649 return (((UV)dec->cur[-4]) << 24) 668 return (((UV)dec->cur[-4]) << 24)
650 | (((UV)dec->cur[-3]) << 16) 669 | (((UV)dec->cur[-3]) << 16)
651 | (((UV)dec->cur[-2]) << 8) 670 | (((UV)dec->cur[-2]) << 8)
652 | ((UV)dec->cur[-1]); 671 | ((UV)dec->cur[-1]);
653 672 }
654 case LENGTH_EXT8: 673 else if (ecb_expect_true (m == LENGTH_EXT8))
674 {
655 WANT (8); 675 WANT (8);
656 dec->cur += 8; 676 dec->cur += 8;
657 677
658 return 678 return
659#if UVSIZE < 8 679#if UVSIZE < 8
660 0 680 0
661#else 681#else
662 (((UV)dec->cur[-8]) << 56) 682 (((UV)dec->cur[-8]) << 56)
663 | (((UV)dec->cur[-7]) << 48) 683 | (((UV)dec->cur[-7]) << 48)
664 | (((UV)dec->cur[-6]) << 40) 684 | (((UV)dec->cur[-6]) << 40)
665 | (((UV)dec->cur[-5]) << 32) 685 | (((UV)dec->cur[-5]) << 32)
666#endif 686#endif
667 | (((UV)dec->cur[-4]) << 24) 687 | (((UV)dec->cur[-4]) << 24)
668 | (((UV)dec->cur[-3]) << 16) 688 | (((UV)dec->cur[-3]) << 16)
669 | (((UV)dec->cur[-2]) << 8) 689 | (((UV)dec->cur[-2]) << 8)
670 | ((UV)dec->cur[-1]); 690 | ((UV)dec->cur[-1]);
671 691 }
672 default: 692 else
673 ERR ("corrupted CBOR data (unsupported integer minor encoding)"); 693 ERR ("corrupted CBOR data (unsupported integer minor encoding)");
674 }
675 694
676fail: 695fail:
677 return 0; 696 return 0;
678} 697}
679 698
705 } 724 }
706 else 725 else
707 { 726 {
708 int i, len = decode_uint (dec); 727 int i, len = decode_uint (dec);
709 728
729 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); 730 av_fill (av, len - 1);
711 731
712 for (i = 0; i < len; ++i) 732 for (i = 0; i < len; ++i)
713 AvARRAY (av)[i] = decode_sv (dec); 733 AvARRAY (av)[i] = decode_sv (dec);
714 } 734 }
727{ 747{
728 // for speed reasons, we specialcase single-string 748 // for speed reasons, we specialcase single-string
729 // byte or utf-8 strings as keys, but only when !stringref 749 // byte or utf-8 strings as keys, but only when !stringref
730 750
731 if (ecb_expect_true (!dec->stringref)) 751 if (ecb_expect_true (!dec->stringref))
732 if ((*dec->cur - MAJOR_BYTES) <= 27) 752 if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
733 { 753 {
734 I32 len = decode_uint (dec); 754 I32 len = decode_uint (dec);
735 char *key = (char *)dec->cur; 755 char *key = (char *)dec->cur;
736 756
757 WANT (len);
737 dec->cur += len; 758 dec->cur += len;
738 759
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); 760 hv_store (hv, key, len, decode_sv (dec), 0);
743 761
744 return; 762 return;
745 } 763 }
746 else if ((*dec->cur - MAJOR_TEXT) <= 27) 764 else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
747 { 765 {
748 I32 len = decode_uint (dec); 766 I32 len = decode_uint (dec);
749 char *key = (char *)dec->cur; 767 char *key = (char *)dec->cur;
750 768
769 WANT (len);
751 dec->cur += len; 770 dec->cur += len;
752 771
753 if (ecb_expect_false (dec->stringref)) 772 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
754 av_push (dec->stringref, newSVpvn_utf8 (key, len, 1)); 773 if (!is_utf8_string (key, len))
774 ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
755 775
756 hv_store (hv, key, -len, decode_sv (dec), 0); 776 hv_store (hv, key, -len, decode_sv (dec), 0);
757 777
758 return; 778 return;
759 } 779 }
761 SV *k = decode_sv (dec); 781 SV *k = decode_sv (dec);
762 SV *v = decode_sv (dec); 782 SV *v = decode_sv (dec);
763 783
764 hv_store_ent (hv, k, v, 0); 784 hv_store_ent (hv, k, v, 0);
765 SvREFCNT_dec (k); 785 SvREFCNT_dec (k);
786
787fail:
788 ;
766} 789}
767 790
768static SV * 791static SV *
769decode_hv (dec_t *dec) 792decode_hv (dec_t *dec)
770{ 793{
852 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1)) 875 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
853 av_push (dec->stringref, SvREFCNT_inc_NN (sv)); 876 av_push (dec->stringref, SvREFCNT_inc_NN (sv));
854 } 877 }
855 878
856 if (utf8) 879 if (utf8)
880 {
881 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
882 if (!is_utf8_string (SvPVX (sv), SvCUR (sv)))
883 ERR ("corrupted CBOR data (invalid UTF-8 in text string)");
884
857 SvUTF8_on (sv); 885 SvUTF8_on (sv);
886 }
858 887
859 return sv; 888 return sv;
860 889
861fail: 890fail:
862 SvREFCNT_dec (sv); 891 SvREFCNT_dec (sv);
911 case CBOR_TAG_VALUE_SHAREABLE: 940 case CBOR_TAG_VALUE_SHAREABLE:
912 { 941 {
913 if (ecb_expect_false (!dec->shareable)) 942 if (ecb_expect_false (!dec->shareable))
914 dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); 943 dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
915 944
945 if (dec->cbor.flags & F_ALLOW_CYCLES)
946 {
916 sv = newSV (0); 947 sv = newSV (0);
917 av_push (dec->shareable, SvREFCNT_inc_NN (sv)); 948 av_push (dec->shareable, SvREFCNT_inc_NN (sv));
918 949
919 SV *osv = decode_sv (dec); 950 SV *osv = decode_sv (dec);
920 sv_setsv (sv, osv); 951 sv_setsv (sv, osv);
921 SvREFCNT_dec_NN (osv); 952 SvREFCNT_dec_NN (osv);
953 }
954 else
955 {
956 av_push (dec->shareable, &PL_sv_undef);
957 int idx = AvFILLp (dec->shareable);
958 sv = decode_sv (dec);
959 av_store (dec->shareable, idx, SvREFCNT_inc_NN (sv));
960 }
922 } 961 }
923 break; 962 break;
924 963
925 case CBOR_TAG_VALUE_SHAREDREF: 964 case CBOR_TAG_VALUE_SHAREDREF:
926 { 965 {
931 970
932 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable)) 971 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable))
933 ERR ("corrupted CBOR data (sharedref index out of bounds)"); 972 ERR ("corrupted CBOR data (sharedref index out of bounds)");
934 973
935 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); 974 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
975
976 if (sv == &PL_sv_undef)
977 ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
936 } 978 }
937 break; 979 break;
938 980
939 case CBOR_TAG_PERL_OBJECT: 981 case CBOR_TAG_PERL_OBJECT:
940 { 982 {
955 if (!method) 997 if (!method)
956 ERR ("cannot decode perl-object (package does not have a THAW method)"); 998 ERR ("cannot decode perl-object (package does not have a THAW method)");
957 999
958 dSP; 1000 dSP;
959 1001
960 ENTER; SAVETMPS; PUSHMARK (SP); 1002 ENTER; SAVETMPS;
1003 PUSHMARK (SP);
961 EXTEND (SP, len + 1); 1004 EXTEND (SP, len + 1);
962 // we re-bless the reference to get overload and other niceties right 1005 // we re-bless the reference to get overload and other niceties right
963 PUSHs (*av_fetch (av, 0, 1)); 1006 PUSHs (*av_fetch (av, 0, 1));
964 PUSHs (sv_cbor); 1007 PUSHs (sv_cbor);
965 1008
990 default: 1033 default:
991 { 1034 {
992 sv = decode_sv (dec); 1035 sv = decode_sv (dec);
993 1036
994 dSP; 1037 dSP;
995 ENTER; SAVETMPS; PUSHMARK (SP); 1038 ENTER; SAVETMPS;
1039 SAVESTACK_POS ();
1040 PUSHMARK (SP);
996 EXTEND (SP, 2); 1041 EXTEND (SP, 2);
997 PUSHs (newSVuv (tag)); 1042 PUSHs (newSVuv (tag));
998 PUSHs (sv); 1043 PUSHs (sv);
999 1044
1000 PUTBACK; 1045 PUTBACK;
1109 1154
1110 return newSVnv (ecb_binary64_to_double (fp)); 1155 return newSVnv (ecb_binary64_to_double (fp));
1111 } 1156 }
1112 1157
1113 // 0..19 unassigned simple 1158 // 0..19 unassigned simple
1114 // 24 reserved + unassigned (reserved values are not encodable) 1159 // 24 reserved + unassigned simple (reserved values are not encodable)
1160 // 28-30 unassigned misc
1161 // 31 break code
1115 default: 1162 default:
1116 ERR ("corrupted CBOR data (reserved/unassigned major 7 value)"); 1163 ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1117 } 1164 }
1118 1165
1119 break; 1166 break;
1120 } 1167 }
1121 1168
1124} 1171}
1125 1172
1126static SV * 1173static SV *
1127decode_cbor (SV *string, CBOR *cbor, char **offset_return) 1174decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1128{ 1175{
1129 dec_t dec = { }; 1176 dec_t dec = { 0 };
1130 SV *sv; 1177 SV *sv;
1131 STRLEN len; 1178 STRLEN len;
1132 char *data = SvPVbyte (string, len); 1179 char *data = SvPVbyte (string, len);
1133 1180
1134 if (len > cbor->max_size && cbor->max_size) 1181 if (len > cbor->max_size && cbor->max_size)
1148 if (dec.cur != dec.end && !dec.err) 1195 if (dec.cur != dec.end && !dec.err)
1149 dec.err = "garbage after CBOR object"; 1196 dec.err = "garbage after CBOR object";
1150 1197
1151 if (dec.err) 1198 if (dec.err)
1152 { 1199 {
1200 if (dec.shareable)
1201 {
1202 // need to break cyclic links, which whould all be in shareable
1203 int i;
1204 SV **svp;
1205
1206 for (i = av_len (dec.shareable) + 1; i--; )
1207 if ((svp = av_fetch (dec.shareable, i, 0)))
1208 sv_setsv (*svp, &PL_sv_undef);
1209 }
1210
1153 SvREFCNT_dec (sv); 1211 SvREFCNT_dec (sv);
1154 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); 1212 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1155 } 1213 }
1156 1214
1157 sv = sv_2mortal (sv); 1215 sv = sv_2mortal (sv);
1158 1216
1159 return sv; 1217 return sv;
1160} 1218}
1161 1219
1220/////////////////////////////////////////////////////////////////////////////
1221// incremental parser
1222
1223#define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1224
1225// returns 0 for notyet, 1 for success or error
1226static int
1227incr_parse (CBOR *self, SV *cborstr)
1228{
1229 STRLEN cur;
1230 SvPV (cborstr, cur);
1231
1232 while (ecb_expect_true (self->incr_need <= cur))
1233 {
1234 // table of integer count bytes
1235 static I8 incr_len[MINOR_MASK + 1] = {
1236 0, 0, 0, 0, 0, 0, 0, 0,
1237 0, 0, 0, 0, 0, 0, 0, 0,
1238 0, 0, 0, 0, 0, 0, 0, 0,
1239 1, 2, 4, 8,-1,-1,-1,-2
1240 };
1241
1242 const U8 *p = SvPVX (cborstr) + self->incr_pos;
1243 U8 m = *p & MINOR_MASK;
1244 IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1245 I8 ilen = incr_len[m];
1246
1247 self->incr_need = self->incr_pos + 1;
1248
1249 if (ecb_expect_false (ilen < 0))
1250 {
1251 if (m != MINOR_INDEF)
1252 return 1; // error
1253
1254 if (*p == (MAJOR_MISC | MINOR_INDEF))
1255 {
1256 if (count >= 0)
1257 return 1; // error
1258
1259 count = 1;
1260 }
1261 else
1262 {
1263 av_push (self->incr_count, newSViv (-1)); //TODO: nest
1264 count = -1;
1265 }
1266 }
1267 else
1268 {
1269 self->incr_need += ilen;
1270 if (ecb_expect_false (self->incr_need > cur))
1271 return 0;
1272
1273 int major = *p >> MAJOR_SHIFT;
1274
1275 switch (major)
1276 {
1277 case MAJOR_TAG >> MAJOR_SHIFT:
1278 ++count; // tags merely prefix another value
1279 break;
1280
1281 case MAJOR_BYTES >> MAJOR_SHIFT:
1282 case MAJOR_TEXT >> MAJOR_SHIFT:
1283 case MAJOR_ARRAY >> MAJOR_SHIFT:
1284 case MAJOR_MAP >> MAJOR_SHIFT:
1285 {
1286 UV len;
1287
1288 if (ecb_expect_false (ilen))
1289 {
1290 len = 0;
1291
1292 do {
1293 len = (len << 8) | *++p;
1294 } while (--ilen);
1295 }
1296 else
1297 len = m;
1298
1299 switch (major)
1300 {
1301 case MAJOR_BYTES >> MAJOR_SHIFT:
1302 case MAJOR_TEXT >> MAJOR_SHIFT:
1303 self->incr_need += len;
1304 if (ecb_expect_false (self->incr_need > cur))
1305 return 0;
1306
1307 break;
1308
1309 case MAJOR_MAP >> MAJOR_SHIFT:
1310 len <<= 1;
1311 case MAJOR_ARRAY >> MAJOR_SHIFT:
1312 if (len)
1313 {
1314 av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1315 count = len + 1;
1316 }
1317 break;
1318 }
1319 }
1320 }
1321 }
1322
1323 self->incr_pos = self->incr_need;
1324
1325 if (count > 0)
1326 {
1327 while (!--count)
1328 {
1329 if (!AvFILLp (self->incr_count))
1330 return 1; // done
1331
1332 SvREFCNT_dec_NN (av_pop (self->incr_count));
1333 count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1334 }
1335
1336 SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1337 }
1338 }
1339
1340 return 0;
1341}
1342
1343
1162///////////////////////////////////////////////////////////////////////////// 1344/////////////////////////////////////////////////////////////////////////////
1163// XS interface functions 1345// XS interface functions
1164 1346
1165MODULE = CBOR::XS PACKAGE = CBOR::XS 1347MODULE = CBOR::XS PACKAGE = CBOR::XS
1166 1348
1206void shrink (CBOR *self, int enable = 1) 1388void shrink (CBOR *self, int enable = 1)
1207 ALIAS: 1389 ALIAS:
1208 shrink = F_SHRINK 1390 shrink = F_SHRINK
1209 allow_unknown = F_ALLOW_UNKNOWN 1391 allow_unknown = F_ALLOW_UNKNOWN
1210 allow_sharing = F_ALLOW_SHARING 1392 allow_sharing = F_ALLOW_SHARING
1393 allow_cycles = F_ALLOW_CYCLES
1211 pack_strings = F_PACK_STRINGS 1394 pack_strings = F_PACK_STRINGS
1395 validate_utf8 = F_VALIDATE_UTF8
1212 PPCODE: 1396 PPCODE:
1213{ 1397{
1214 if (enable) 1398 if (enable)
1215 self->flags |= ix; 1399 self->flags |= ix;
1216 else 1400 else
1222void get_shrink (CBOR *self) 1406void get_shrink (CBOR *self)
1223 ALIAS: 1407 ALIAS:
1224 get_shrink = F_SHRINK 1408 get_shrink = F_SHRINK
1225 get_allow_unknown = F_ALLOW_UNKNOWN 1409 get_allow_unknown = F_ALLOW_UNKNOWN
1226 get_allow_sharing = F_ALLOW_SHARING 1410 get_allow_sharing = F_ALLOW_SHARING
1411 get_allow_cycles = F_ALLOW_CYCLES
1227 get_pack_strings = F_PACK_STRINGS 1412 get_pack_strings = F_PACK_STRINGS
1413 get_validate_utf8 = F_VALIDATE_UTF8
1228 PPCODE: 1414 PPCODE:
1229 XPUSHs (boolSV (self->flags & ix)); 1415 XPUSHs (boolSV (self->flags & ix));
1230 1416
1231void max_depth (CBOR *self, U32 max_depth = 0x80000000UL) 1417void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1232 PPCODE: 1418 PPCODE:
1281 EXTEND (SP, 2); 1467 EXTEND (SP, 2);
1282 PUSHs (sv); 1468 PUSHs (sv);
1283 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr)))); 1469 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1284} 1470}
1285 1471
1472void incr_parse (CBOR *self, SV *cborstr)
1473 ALIAS:
1474 incr_parse_multiple = 1
1475 PPCODE:
1476{
1477 if (SvUTF8 (cborstr))
1478 sv_utf8_downgrade (cborstr, 0);
1479
1480 if (!self->incr_count)
1481 {
1482 self->incr_count = newAV ();
1483 self->incr_pos = 0;
1484 self->incr_need = 1;
1485
1486 av_push (self->incr_count, newSViv (1));
1487 }
1488
1489 do
1490 {
1491 if (!incr_parse (self, cborstr))
1492 {
1493 if (self->incr_need > self->max_size && self->max_size)
1494 croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1495 (unsigned long)self->incr_need, (unsigned long)self->max_size);
1496
1497 break;
1498 }
1499
1500 SV *sv;
1501 char *offset;
1502
1503 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1504 XPUSHs (sv);
1505
1506 sv_chop (cborstr, offset);
1507
1508 av_clear (self->incr_count);
1509 av_push (self->incr_count, newSViv (1));
1510
1511 self->incr_pos = 0;
1512 self->incr_need = self->incr_pos + 1;
1513 }
1514 while (ix);
1515}
1516
1517void incr_reset (CBOR *self)
1518 CODE:
1519{
1520 SvREFCNT_dec (self->incr_count);
1521 self->incr_count = 0;
1522}
1523
1286void DESTROY (CBOR *self) 1524void DESTROY (CBOR *self)
1287 PPCODE: 1525 PPCODE:
1288 cbor_free (self); 1526 cbor_free (self);
1289 1527
1290PROTOTYPES: ENABLE 1528PROTOTYPES: ENABLE
1291 1529
1292void encode_cbor (SV *scalar) 1530void encode_cbor (SV *scalar)
1531 ALIAS:
1532 encode_cbor = 0
1533 encode_cbor_sharing = F_ALLOW_SHARING
1293 PPCODE: 1534 PPCODE:
1294{ 1535{
1295 CBOR cbor; 1536 CBOR cbor;
1296 cbor_init (&cbor); 1537 cbor_init (&cbor);
1538 cbor.flags |= ix;
1297 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN; 1539 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1298 XPUSHs (scalar); 1540 XPUSHs (scalar);
1299} 1541}
1300 1542
1301void decode_cbor (SV *cborstr) 1543void decode_cbor (SV *cborstr)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines