1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 
5 #include <assert.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <limits.h>
10 #include <float.h>
11 
12 #define ECB_NO_THREADS 1
13 #include "ecb.h"
14 
15 // compatibility with perl <5.18
16 #ifndef HvNAMELEN_get
17 # define HvNAMELEN_get(hv) strlen (HvNAME (hv))
18 #endif
19 #ifndef HvNAMELEN
20 # define HvNAMELEN(hv) HvNAMELEN_get (hv)
21 #endif
22 #ifndef HvNAMEUTF8
23 # define HvNAMEUTF8(hv) 0
24 #endif
25 #ifndef SvREFCNT_dec_NN
26 # define SvREFCNT_dec_NN(sv) SvREFCNT_dec (sv)
27 #endif
28 
29 // known major and minor types
30 enum cbor_type
31 {
32   MAJOR_SHIFT   = 5,
33   MINOR_MASK    = 0x1f,
34 
35   MAJOR_POS_INT = 0 << MAJOR_SHIFT,
36   MAJOR_NEG_INT = 1 << MAJOR_SHIFT,
37   MAJOR_BYTES   = 2 << MAJOR_SHIFT,
38   MAJOR_TEXT    = 3 << MAJOR_SHIFT,
39   MAJOR_ARRAY   = 4 << MAJOR_SHIFT,
40   MAJOR_MAP     = 5 << MAJOR_SHIFT,
41   MAJOR_TAG     = 6 << MAJOR_SHIFT,
42   MAJOR_MISC    = 7 << MAJOR_SHIFT,
43 
44   // INT/STRING/ARRAY/MAP subtypes
45   LENGTH_EXT1    = 24,
46   LENGTH_EXT2    = 25,
47   LENGTH_EXT4    = 26,
48   LENGTH_EXT8    = 27,
49 
50   // SIMPLE types (effectively MISC subtypes)
51   SIMPLE_FALSE   = 20,
52   SIMPLE_TRUE    = 21,
53   SIMPLE_NULL    = 22,
54   SIMPLE_UNDEF   = 23,
55 
56   // MISC subtype (unused)
57   MISC_EXT1      = 24,
58   MISC_FLOAT16   = 25,
59   MISC_FLOAT32   = 26,
60   MISC_FLOAT64   = 27,
61 
62   // BYTES/TEXT/ARRAY/MAP
63   MINOR_INDEF    = 31,
64 };
65 
66 // known tags
67 enum cbor_tag
68 {
69   // extensions
70   CBOR_TAG_STRINGREF           =    25, // http://cbor.schmorp.de/stringref
71   CBOR_TAG_PERL_OBJECT         =    26, // http://cbor.schmorp.de/perl-object
72   CBOR_TAG_GENERIC_OBJECT      =    27, // http://cbor.schmorp.de/generic-object
73   CBOR_TAG_VALUE_SHAREABLE     =    28, // http://cbor.schmorp.de/value-sharing
74   CBOR_TAG_VALUE_SHAREDREF     =    29, // http://cbor.schmorp.de/value-sharing
75   CBOR_TAG_STRINGREF_NAMESPACE =   256, // http://cbor.schmorp.de/stringref
76   CBOR_TAG_INDIRECTION	       = 22098, // http://cbor.schmorp.de/indirection
77 
78   // rfc7049
79   CBOR_TAG_DATETIME    =     0, // rfc4287, utf-8
80   CBOR_TAG_TIMESTAMP   =     1, // unix timestamp, any
81   CBOR_TAG_POS_BIGNUM  =     2, // byte string
82   CBOR_TAG_NEG_BIGNUM  =     3, // byte string
83   CBOR_TAG_DECIMAL     =     4, // decimal fraction, array
84   CBOR_TAG_BIGFLOAT    =     5, // array
85 
86   CBOR_TAG_CONV_B64U   =    21, // base64url, any
87   CBOR_TAG_CONV_B64    =    22, // base64, any
88   CBOR_TAG_CONV_HEX    =    23, // base16, any
89   CBOR_TAG_CBOR        =    24, // embedded cbor, byte string
90 
91   CBOR_TAG_URI         =    32, // URI rfc3986, utf-8
92   CBOR_TAG_B64U        =    33, // base64url rfc4648, utf-8
93   CBOR_TAG_B64         =    34, // base6 rfc46484, utf-8
94   CBOR_TAG_REGEX       =    35, // regex pcre/ecma262, utf-8
95   CBOR_TAG_MIME        =    36, // mime message rfc2045, utf-8
96 
97   CBOR_TAG_MAGIC       = 55799, // self-describe cbor
98 };
99 
100 #define F_SHRINK          0x00000001UL
101 #define F_ALLOW_UNKNOWN   0x00000002UL
102 #define F_ALLOW_SHARING   0x00000004UL
103 #define F_ALLOW_CYCLES    0x00000008UL
104 #define F_PACK_STRINGS    0x00000010UL
105 #define F_VALIDATE_UTF8   0x00000020UL
106 
107 #define INIT_SIZE   32 // initial scalar size to be allocated
108 
109 #define SB do {
110 #define SE } while (0)
111 
112 #define IN_RANGE_INC(type,val,beg,end) \
113   ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \
114   <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg)))
115 
116 #define ERR_NESTING_EXCEEDED "cbor text or perl structure exceeds maximum nesting level (max_depth set too low?)"
117 
118 #ifdef USE_ITHREADS
119 # define CBOR_SLOW 1
120 # define CBOR_STASH (cbor_stash ? cbor_stash : gv_stashpv ("CBOR::XS", 1))
121 #else
122 # define CBOR_SLOW 0
123 # define CBOR_STASH cbor_stash
124 #endif
125 
126 static HV *cbor_stash, *types_boolean_stash, *types_error_stash, *cbor_tagged_stash; // CBOR::XS::
127 static SV *types_true, *types_false, *types_error, *sv_cbor, *default_filter;
128 
129 typedef struct {
130   U32 flags;
131   U32 max_depth;
132   STRLEN max_size;
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.
139 } CBOR;
140 
141 ecb_inline void
cbor_init(CBOR * cbor)142 cbor_init (CBOR *cbor)
143 {
144   Zero (cbor, 1, CBOR);
145   cbor->max_depth = 512;
146 }
147 
148 ecb_inline void
cbor_free(CBOR * cbor)149 cbor_free (CBOR *cbor)
150 {
151   SvREFCNT_dec (cbor->filter);
152   SvREFCNT_dec (cbor->incr_count);
153 }
154 
155 /////////////////////////////////////////////////////////////////////////////
156 // utility functions
157 
158 ecb_inline SV *
get_bool(const char * name)159 get_bool (const char *name)
160 {
161   SV *sv = get_sv (name, 1);
162 
163   SvREADONLY_on (sv);
164   SvREADONLY_on (SvRV (sv));
165 
166   return sv;
167 }
168 
169 ecb_inline void
shrink(SV * sv)170 shrink (SV *sv)
171 {
172   sv_utf8_downgrade (sv, 1);
173 
174   if (SvLEN (sv) > SvCUR (sv) + 1)
175     {
176 #ifdef SvPV_shrink_to_cur
177       SvPV_shrink_to_cur (sv);
178 #elif defined (SvPV_renew)
179       SvPV_renew (sv, SvCUR (sv) + 1);
180 #endif
181     }
182 }
183 
184 // minimum length of a string to be registered for stringref
185 ecb_inline int
minimum_string_length(UV idx)186 minimum_string_length (UV idx)
187 {
188   return idx > 23
189          ? idx > 0xffU
190            ? idx > 0xffffU
191              ? idx > 0xffffffffU
192                ? 11
193                : 7
194              : 5
195            : 4
196          : 3;
197 }
198 
199 /////////////////////////////////////////////////////////////////////////////
200 // encoder
201 
202 // structure used for encoding CBOR
203 typedef struct
204 {
205   char *cur;  // SvPVX (sv) + current output position
206   char *end;  // SvEND (sv)
207   SV *sv;     // result scalar
208   CBOR cbor;
209   U32 depth;  // recursion level
210   HV *stringref[2]; // string => index, or 0 ([0] = bytes, [1] = utf-8)
211   UV stringref_idx;
212   HV *shareable; // ptr => index, or 0
213   UV shareable_idx;
214 } enc_t;
215 
216 ecb_inline void
need(enc_t * enc,STRLEN len)217 need (enc_t *enc, STRLEN len)
218 {
219   if (ecb_expect_false (enc->cur + len >= enc->end))
220     {
221       STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
222       SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
223       enc->cur = SvPVX (enc->sv) + cur;
224       enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1;
225     }
226 }
227 
228 ecb_inline void
encode_ch(enc_t * enc,char ch)229 encode_ch (enc_t *enc, char ch)
230 {
231   need (enc, 1);
232   *enc->cur++ = ch;
233 }
234 
235 static void
encode_uint(enc_t * enc,int major,UV len)236 encode_uint (enc_t *enc, int major, UV len)
237 {
238    need (enc, 9);
239 
240    if (ecb_expect_true (len < LENGTH_EXT1))
241       *enc->cur++ = major | len;
242    else if (ecb_expect_true (len <= 0xffU))
243      {
244        *enc->cur++ = major | LENGTH_EXT1;
245        *enc->cur++ = len;
246      }
247    else if (len <= 0xffffU)
248      {
249        *enc->cur++ = major | LENGTH_EXT2;
250        *enc->cur++ = len >> 8;
251        *enc->cur++ = len;
252      }
253    else if (len <= 0xffffffffU)
254      {
255        *enc->cur++ = major | LENGTH_EXT4;
256        *enc->cur++ = len >> 24;
257        *enc->cur++ = len >> 16;
258        *enc->cur++ = len >>  8;
259        *enc->cur++ = len;
260      }
261    else
262      {
263        *enc->cur++ = major | LENGTH_EXT8;
264        *enc->cur++ = len >> 56;
265        *enc->cur++ = len >> 48;
266        *enc->cur++ = len >> 40;
267        *enc->cur++ = len >> 32;
268        *enc->cur++ = len >> 24;
269        *enc->cur++ = len >> 16;
270        *enc->cur++ = len >>  8;
271        *enc->cur++ = len;
272      }
273 }
274 
275 ecb_inline void
encode_tag(enc_t * enc,UV tag)276 encode_tag (enc_t *enc, UV tag)
277 {
278   encode_uint (enc, MAJOR_TAG, tag);
279 }
280 
281 ecb_inline void
encode_str(enc_t * enc,int utf8,char * str,STRLEN len)282 encode_str (enc_t *enc, int utf8, char *str, STRLEN len)
283 {
284   encode_uint (enc, utf8 ? MAJOR_TEXT : MAJOR_BYTES, len);
285   need (enc, len);
286   memcpy (enc->cur, str, len);
287   enc->cur += len;
288 }
289 
290 static void
encode_strref(enc_t * enc,int utf8,char * str,STRLEN len)291 encode_strref (enc_t *enc, int utf8, char *str, STRLEN len)
292 {
293   if (ecb_expect_false (enc->cbor.flags & F_PACK_STRINGS))
294     {
295       SV **svp = hv_fetch (enc->stringref[!!utf8], str, len, 1);
296 
297       if (SvOK (*svp))
298         {
299           // already registered, use stringref
300           encode_tag (enc, CBOR_TAG_STRINGREF);
301           encode_uint (enc, MAJOR_POS_INT, SvUV (*svp));
302           return;
303         }
304       else if (len >= minimum_string_length (enc->stringref_idx))
305         {
306           // register only
307           sv_setuv (*svp, enc->stringref_idx);
308           ++enc->stringref_idx;
309         }
310     }
311 
312   encode_str (enc, utf8, str, len);
313 }
314 
315 static void encode_sv (enc_t *enc, SV *sv);
316 
317 static void
encode_av(enc_t * enc,AV * av)318 encode_av (enc_t *enc, AV *av)
319 {
320   int i, len = av_len (av);
321 
322   if (enc->depth >= enc->cbor.max_depth)
323     croak (ERR_NESTING_EXCEEDED);
324 
325   ++enc->depth;
326 
327   encode_uint (enc, MAJOR_ARRAY, len + 1);
328 
329   if (SvMAGICAL (av))
330     for (i = 0; i <= len; ++i)
331       {
332         SV **svp = av_fetch (av, i, 0);
333         encode_sv (enc, svp ? *svp : &PL_sv_undef);
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       }
341 
342   --enc->depth;
343 }
344 
345 static void
encode_hv(enc_t * enc,HV * hv)346 encode_hv (enc_t *enc, HV *hv)
347 {
348   HE *he;
349 
350   if (enc->depth >= enc->cbor.max_depth)
351     croak (ERR_NESTING_EXCEEDED);
352 
353   ++enc->depth;
354 
355   int pairs = hv_iterinit (hv);
356   int mg = SvMAGICAL (hv);
357 
358   if (mg)
359     encode_ch (enc, MAJOR_MAP | MINOR_INDEF);
360   else
361     encode_uint (enc, MAJOR_MAP, pairs);
362 
363   while ((he = hv_iternext (hv)))
364     {
365       if (HeKLEN (he) == HEf_SVKEY)
366         encode_sv (enc, HeSVKEY (he));
367       else
368         encode_strref (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he));
369 
370       encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he));
371     }
372 
373   if (mg)
374     encode_ch (enc, MAJOR_MISC | MINOR_INDEF);
375 
376   --enc->depth;
377 }
378 
379 // encode objects, arrays and special \0=false and \1=true values.
380 static void
encode_rv(enc_t * enc,SV * sv)381 encode_rv (enc_t *enc, SV *sv)
382 {
383   SvGETMAGIC (sv);
384 
385   svtype svt = SvTYPE (sv);
386 
387   if (ecb_expect_false (SvOBJECT (sv)))
388     {
389       HV *boolean_stash = !CBOR_SLOW || types_boolean_stash
390                           ? types_boolean_stash
391                           : gv_stashpv ("Types::Serialiser::Boolean", 1);
392       HV *error_stash   = !CBOR_SLOW || types_error_stash
393                           ? types_error_stash
394                           : gv_stashpv ("Types::Serialiser::Error", 1);
395       HV *tagged_stash  = !CBOR_SLOW || cbor_tagged_stash
396                           ? cbor_tagged_stash
397                           : gv_stashpv ("CBOR::XS::Tagged" , 1);
398 
399       HV *stash = SvSTASH (sv);
400 
401       if (stash == boolean_stash)
402         {
403           encode_ch (enc, SvIV (sv) ? MAJOR_MISC | SIMPLE_TRUE : MAJOR_MISC | SIMPLE_FALSE);
404           return;
405         }
406       else if (stash == error_stash)
407         {
408           encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
409           return;
410         }
411       else if (stash == tagged_stash)
412         {
413           if (svt != SVt_PVAV)
414             croak ("encountered CBOR::XS::Tagged object that isn't an array");
415 
416           encode_uint (enc, MAJOR_TAG, SvUV (*av_fetch ((AV *)sv, 0, 1)));
417           encode_sv (enc, *av_fetch ((AV *)sv, 1, 1));
418 
419           return;
420         }
421     }
422 
423   if (ecb_expect_false (SvREFCNT (sv) > 1)
424       && ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING))
425     {
426       if (!enc->shareable)
427         enc->shareable = (HV *)sv_2mortal ((SV *)newHV ());
428 
429       SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1);
430 
431       if (SvOK (*svp))
432         {
433           encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF);
434           encode_uint (enc, MAJOR_POS_INT, SvUV (*svp));
435           return;
436         }
437       else
438         {
439           sv_setuv (*svp, enc->shareable_idx);
440           ++enc->shareable_idx;
441           encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE);
442         }
443     }
444 
445   if (ecb_expect_false (SvOBJECT (sv)))
446     {
447       HV *stash = SvSTASH (sv);
448       GV *method;
449 
450       if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0)))
451         {
452           dSP;
453 
454           ENTER; SAVETMPS; PUSHMARK (SP);
455           // we re-bless the reference to get overload and other niceties right
456           XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
457 
458           PUTBACK;
459           // G_SCALAR ensures that return value is 1
460           call_sv ((SV *)GvCV (method), G_SCALAR);
461           SPAGAIN;
462 
463           // catch this surprisingly common error
464           if (SvROK (TOPs) && SvRV (TOPs) == sv)
465             croak ("%s::TO_CBOR method returned same object as was passed instead of a new one", HvNAME (stash));
466 
467           encode_sv (enc, POPs);
468 
469           PUTBACK;
470 
471           FREETMPS; LEAVE;
472         }
473       else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0)
474         {
475           dSP;
476 
477           ENTER; SAVETMPS; PUSHMARK (SP);
478           EXTEND (SP, 2);
479           // we re-bless the reference to get overload and other niceties right
480           PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
481           PUSHs (sv_cbor);
482 
483           PUTBACK;
484           int count = call_sv ((SV *)GvCV (method), G_ARRAY);
485           SPAGAIN;
486 
487           // catch this surprisingly common error
488           if (count == 1 && SvROK (TOPs) && SvRV (TOPs) == sv)
489             croak ("%s::FREEZE(CBOR) method returned same object as was passed instead of a new one", HvNAME (stash));
490 
491           encode_tag (enc, CBOR_TAG_PERL_OBJECT);
492           encode_uint (enc, MAJOR_ARRAY, count + 1);
493           encode_strref (enc, HvNAMEUTF8 (stash), HvNAME (stash), HvNAMELEN (stash));
494 
495           while (count)
496             encode_sv (enc, SP[1 - count--]);
497 
498           PUTBACK;
499 
500           FREETMPS; LEAVE;
501         }
502       else
503         croak ("encountered object '%s', but no TO_CBOR or FREEZE methods available on it",
504                SvPV_nolen (sv_2mortal (newRV_inc (sv))));
505     }
506   else if (svt == SVt_PVHV)
507     encode_hv (enc, (HV *)sv);
508   else if (svt == SVt_PVAV)
509     encode_av (enc, (AV *)sv);
510   else
511     {
512       encode_tag (enc, CBOR_TAG_INDIRECTION);
513       encode_sv (enc, sv);
514     }
515 }
516 
517 static void
encode_nv(enc_t * enc,SV * sv)518 encode_nv (enc_t *enc, SV *sv)
519 {
520   double nv = SvNVX (sv);
521 
522   need (enc, 9);
523 
524   if (ecb_expect_false (nv == (NV)(U32)nv))
525     encode_uint (enc, MAJOR_POS_INT, (U32)nv);
526   //TODO: maybe I32?
527   else if (ecb_expect_false (nv == (float)nv))
528     {
529       uint32_t fp = ecb_float_to_binary32 (nv);
530 
531       *enc->cur++ = MAJOR_MISC | MISC_FLOAT32;
532 
533       if (!ecb_big_endian ())
534         fp = ecb_bswap32 (fp);
535 
536       memcpy (enc->cur, &fp, 4);
537       enc->cur += 4;
538     }
539   else
540     {
541       uint64_t fp = ecb_double_to_binary64 (nv);
542 
543       *enc->cur++ = MAJOR_MISC | MISC_FLOAT64;
544 
545       if (!ecb_big_endian ())
546         fp = ecb_bswap64 (fp);
547 
548       memcpy (enc->cur, &fp, 8);
549       enc->cur += 8;
550     }
551 }
552 
553 static void
encode_sv(enc_t * enc,SV * sv)554 encode_sv (enc_t *enc, SV *sv)
555 {
556   SvGETMAGIC (sv);
557 
558   if (SvPOKp (sv))
559     {
560       STRLEN len;
561       char *str = SvPV (sv, len);
562       encode_strref (enc, SvUTF8 (sv), str, len);
563     }
564   else if (SvNOKp (sv))
565     encode_nv (enc, sv);
566   else if (SvIOKp (sv))
567     {
568       if (SvIsUV (sv))
569         encode_uint (enc, MAJOR_POS_INT, SvUVX (sv));
570       else if (SvIVX (sv) >= 0)
571         encode_uint (enc, MAJOR_POS_INT, SvIVX (sv));
572       else
573         encode_uint (enc, MAJOR_NEG_INT, -(SvIVX (sv) + 1));
574     }
575   else if (SvROK (sv))
576     encode_rv (enc, SvRV (sv));
577   else if (!SvOK (sv))
578     encode_ch (enc, MAJOR_MISC | SIMPLE_NULL);
579   else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
580     encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
581   else
582     croak ("encountered perl type (%s,0x%x) that CBOR cannot handle, check your input data",
583            SvPV_nolen (sv), (unsigned int)SvFLAGS (sv));
584 }
585 
586 static SV *
encode_cbor(SV * scalar,CBOR * cbor)587 encode_cbor (SV *scalar, CBOR *cbor)
588 {
589   enc_t enc = { };
590 
591   enc.cbor      = *cbor;
592   enc.sv        = sv_2mortal (NEWSV (0, INIT_SIZE));
593   enc.cur       = SvPVX (enc.sv);
594   enc.end       = SvEND (enc.sv);
595 
596   SvPOK_only (enc.sv);
597 
598   if (cbor->flags & F_PACK_STRINGS)
599     {
600       encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE);
601       enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ());
602       enc.stringref[1]= (HV *)sv_2mortal ((SV *)newHV ());
603     }
604 
605   encode_sv (&enc, scalar);
606 
607   SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
608   *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings
609 
610   if (enc.cbor.flags & F_SHRINK)
611     shrink (enc.sv);
612 
613   return enc.sv;
614 }
615 
616 /////////////////////////////////////////////////////////////////////////////
617 // decoder
618 
619 // structure used for decoding CBOR
620 typedef struct
621 {
622   U8 *cur; // current parser pointer
623   U8 *end; // end of input string
624   const char *err; // parse error, if != 0
625   CBOR cbor;
626   U32 depth; // recursion depth
627   U32 maxdepth; // recursion depth limit
628   AV *shareable;
629   AV *stringref;
630   SV *decode_tagged;
631 } dec_t;
632 
633 #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
634 
635 #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
636 
637 #define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED)
638 #define DEC_DEC_DEPTH --dec->depth
639 
640 static UV
decode_uint(dec_t * dec)641 decode_uint (dec_t *dec)
642 {
643   U8 m = *dec->cur & MINOR_MASK;
644   ++dec->cur;
645 
646   if (ecb_expect_true (m < LENGTH_EXT1))
647     return m;
648   else if (ecb_expect_true (m == LENGTH_EXT1))
649     {
650       WANT (1);
651       dec->cur += 1;
652       return dec->cur[-1];
653     }
654   else if (ecb_expect_true (m == LENGTH_EXT2))
655     {
656       WANT (2);
657       dec->cur += 2;
658       return (((UV)dec->cur[-2]) <<  8)
659            |  ((UV)dec->cur[-1]);
660     }
661   else if (ecb_expect_true (m == LENGTH_EXT4))
662     {
663       WANT (4);
664       dec->cur += 4;
665       return (((UV)dec->cur[-4]) << 24)
666            | (((UV)dec->cur[-3]) << 16)
667            | (((UV)dec->cur[-2]) <<  8)
668            |  ((UV)dec->cur[-1]);
669     }
670   else if (ecb_expect_true (m == LENGTH_EXT8))
671     {
672       WANT (8);
673       dec->cur += 8;
674 
675       return
676 #if UVSIZE < 8
677              0
678 #else
679              (((UV)dec->cur[-8]) << 56)
680            | (((UV)dec->cur[-7]) << 48)
681            | (((UV)dec->cur[-6]) << 40)
682            | (((UV)dec->cur[-5]) << 32)
683 #endif
684            | (((UV)dec->cur[-4]) << 24)
685            | (((UV)dec->cur[-3]) << 16)
686            | (((UV)dec->cur[-2]) <<  8)
687            |  ((UV)dec->cur[-1]);
688     }
689   else
690     ERR ("corrupted CBOR data (unsupported integer minor encoding)");
691 
692 fail:
693   return 0;
694 }
695 
696 static SV *decode_sv (dec_t *dec);
697 
698 static SV *
decode_av(dec_t * dec)699 decode_av (dec_t *dec)
700 {
701   AV *av = newAV ();
702 
703   DEC_INC_DEPTH;
704 
705   if (*dec->cur == (MAJOR_ARRAY | MINOR_INDEF))
706     {
707       ++dec->cur;
708 
709       for (;;)
710         {
711           WANT (1);
712 
713           if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
714             {
715               ++dec->cur;
716               break;
717             }
718 
719           av_push (av, decode_sv (dec));
720         }
721     }
722   else
723     {
724       int i, len = decode_uint (dec);
725 
726       WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays
727       av_fill (av, len - 1);
728 
729       for (i = 0; i < len; ++i)
730         AvARRAY (av)[i] = decode_sv (dec);
731     }
732 
733   DEC_DEC_DEPTH;
734   return newRV_noinc ((SV *)av);
735 
736 fail:
737   SvREFCNT_dec (av);
738   DEC_DEC_DEPTH;
739   return &PL_sv_undef;
740 }
741 
742 static void
decode_he(dec_t * dec,HV * hv)743 decode_he (dec_t *dec, HV *hv)
744 {
745   // for speed reasons, we specialcase single-string
746   // byte or utf-8 strings as keys, but only when !stringref
747 
748   if (ecb_expect_true (!dec->stringref))
749     if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
750       {
751         I32 len = decode_uint (dec);
752         char *key = (char *)dec->cur;
753 
754         dec->cur += len;
755 
756         hv_store (hv, key,  len, decode_sv (dec), 0);
757 
758         return;
759       }
760     else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
761       {
762         I32 len = decode_uint (dec);
763         char *key = (char *)dec->cur;
764 
765         dec->cur += len;
766 
767         if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
768           if (!is_utf8_string (key, len))
769             ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
770 
771         hv_store (hv, key, -len, decode_sv (dec), 0);
772 
773         return;
774       }
775 
776   SV *k = decode_sv (dec);
777   SV *v = decode_sv (dec);
778 
779   hv_store_ent (hv, k, v, 0);
780   SvREFCNT_dec (k);
781 
782 fail:
783   ;
784 }
785 
786 static SV *
decode_hv(dec_t * dec)787 decode_hv (dec_t *dec)
788 {
789   HV *hv = newHV ();
790 
791   DEC_INC_DEPTH;
792 
793   if (*dec->cur == (MAJOR_MAP | MINOR_INDEF))
794     {
795       ++dec->cur;
796 
797       for (;;)
798         {
799           WANT (1);
800 
801           if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
802             {
803               ++dec->cur;
804               break;
805             }
806 
807           decode_he (dec, hv);
808         }
809     }
810   else
811     {
812       int pairs = decode_uint (dec);
813 
814       while (pairs--)
815         decode_he (dec, hv);
816     }
817 
818   DEC_DEC_DEPTH;
819   return newRV_noinc ((SV *)hv);
820 
821 fail:
822   SvREFCNT_dec (hv);
823   DEC_DEC_DEPTH;
824   return &PL_sv_undef;
825 }
826 
827 static SV *
decode_str(dec_t * dec,int utf8)828 decode_str (dec_t *dec, int utf8)
829 {
830   SV *sv = 0;
831 
832   if ((*dec->cur & MINOR_MASK) == MINOR_INDEF)
833     {
834       // indefinite length strings
835       ++dec->cur;
836 
837       U8 major = *dec->cur & MAJOR_MISC;
838 
839       sv = newSVpvn ("", 0);
840 
841       for (;;)
842         {
843           WANT (1);
844 
845           if ((*dec->cur - major) > LENGTH_EXT8)
846             if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
847               {
848                 ++dec->cur;
849                 break;
850               }
851             else
852               ERR ("corrupted CBOR data (invalid chunks in indefinite length string)");
853 
854           STRLEN len = decode_uint (dec);
855 
856           WANT (len);
857           sv_catpvn (sv, dec->cur, len);
858           dec->cur += len;
859         }
860     }
861   else
862     {
863       STRLEN len = decode_uint (dec);
864 
865       WANT (len);
866       sv = newSVpvn (dec->cur, len);
867       dec->cur += len;
868 
869       if (ecb_expect_false (dec->stringref)
870           && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
871         av_push (dec->stringref, SvREFCNT_inc_NN (sv));
872     }
873 
874   if (utf8)
875     {
876       if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
877         if (!is_utf8_string (SvPVX (sv), SvCUR (sv)))
878           ERR ("corrupted CBOR data (invalid UTF-8 in text string)");
879 
880       SvUTF8_on (sv);
881     }
882 
883   return sv;
884 
885 fail:
886   SvREFCNT_dec (sv);
887   return &PL_sv_undef;
888 }
889 
890 static SV *
decode_tagged(dec_t * dec)891 decode_tagged (dec_t *dec)
892 {
893   SV *sv = 0;
894   UV tag = decode_uint (dec);
895 
896   WANT (1);
897 
898   switch (tag)
899     {
900       case CBOR_TAG_MAGIC:
901         sv = decode_sv (dec);
902         break;
903 
904       case CBOR_TAG_INDIRECTION:
905         sv = newRV_noinc (decode_sv (dec));
906         break;
907 
908       case CBOR_TAG_STRINGREF_NAMESPACE:
909         {
910           ENTER; SAVETMPS;
911 
912           SAVESPTR (dec->stringref);
913           dec->stringref = (AV *)sv_2mortal ((SV *)newAV ());
914 
915           sv = decode_sv (dec);
916 
917           FREETMPS; LEAVE;
918         }
919         break;
920 
921       case CBOR_TAG_STRINGREF:
922         {
923           if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
924             ERR ("corrupted CBOR data (stringref index not an unsigned integer)");
925 
926           UV idx = decode_uint (dec);
927 
928           if (!dec->stringref || (int)idx > AvFILLp (dec->stringref))
929             ERR ("corrupted CBOR data (stringref index out of bounds or outside namespace)");
930 
931           sv = newSVsv (AvARRAY (dec->stringref)[idx]);
932         }
933         break;
934 
935       case CBOR_TAG_VALUE_SHAREABLE:
936         {
937           if (ecb_expect_false (!dec->shareable))
938             dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
939 
940           if (dec->cbor.flags & F_ALLOW_CYCLES)
941             {
942               sv = newSV (0);
943               av_push (dec->shareable, SvREFCNT_inc_NN (sv));
944 
945               SV *osv = decode_sv (dec);
946               sv_setsv (sv, osv);
947               SvREFCNT_dec_NN (osv);
948             }
949           else
950             {
951               av_push (dec->shareable, &PL_sv_undef);
952               int idx = AvFILLp (dec->shareable);
953               sv = decode_sv (dec);
954               av_store (dec->shareable, idx, SvREFCNT_inc_NN (sv));
955             }
956         }
957         break;
958 
959       case CBOR_TAG_VALUE_SHAREDREF:
960         {
961           if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
962             ERR ("corrupted CBOR data (sharedref index not an unsigned integer)");
963 
964           UV idx = decode_uint (dec);
965 
966           if (!dec->shareable || (int)idx > AvFILLp (dec->shareable))
967             ERR ("corrupted CBOR data (sharedref index out of bounds)");
968 
969           sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
970 
971           if (sv == &PL_sv_undef)
972             ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
973         }
974         break;
975 
976       case CBOR_TAG_PERL_OBJECT:
977         {
978           sv = decode_sv (dec);
979 
980           if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
981             ERR ("corrupted CBOR data (non-array perl object)");
982 
983           AV *av = (AV *)SvRV (sv);
984           int len = av_len (av) + 1;
985           HV *stash = gv_stashsv (*av_fetch (av, 0, 1), 0);
986 
987           if (!stash)
988             ERR ("cannot decode perl-object (package does not exist)");
989 
990           GV *method = gv_fetchmethod_autoload (stash, "THAW", 0);
991 
992           if (!method)
993             ERR ("cannot decode perl-object (package does not have a THAW method)");
994 
995           dSP;
996 
997           ENTER; SAVETMPS; PUSHMARK (SP);
998           EXTEND (SP, len + 1);
999           // we re-bless the reference to get overload and other niceties right
1000           PUSHs (*av_fetch (av, 0, 1));
1001           PUSHs (sv_cbor);
1002 
1003           int i;
1004 
1005           for (i = 1; i < len; ++i)
1006             PUSHs (*av_fetch (av, i, 1));
1007 
1008           PUTBACK;
1009           call_sv ((SV *)GvCV (method), G_SCALAR | G_EVAL);
1010           SPAGAIN;
1011 
1012           if (SvTRUE (ERRSV))
1013             {
1014               FREETMPS; LEAVE;
1015               ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV))));
1016             }
1017 
1018           SvREFCNT_dec (sv);
1019           sv = SvREFCNT_inc (POPs);
1020 
1021           PUTBACK;
1022 
1023           FREETMPS; LEAVE;
1024         }
1025         break;
1026 
1027       default:
1028         {
1029           sv = decode_sv (dec);
1030 
1031           dSP;
1032           ENTER; SAVETMPS; PUSHMARK (SP);
1033           EXTEND (SP, 2);
1034           PUSHs (newSVuv (tag));
1035           PUSHs (sv);
1036 
1037           PUTBACK;
1038           int count = call_sv (dec->cbor.filter ? dec->cbor.filter : default_filter, G_ARRAY | G_EVAL);
1039           SPAGAIN;
1040 
1041           if (SvTRUE (ERRSV))
1042             {
1043               FREETMPS; LEAVE;
1044               ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV))));
1045             }
1046 
1047           if (count)
1048             {
1049               SvREFCNT_dec (sv);
1050               sv = SvREFCNT_inc (POPs);
1051             }
1052           else
1053             {
1054               AV *av = newAV ();
1055               av_push (av, newSVuv (tag));
1056               av_push (av, sv);
1057 
1058               HV *tagged_stash  = !CBOR_SLOW || cbor_tagged_stash
1059                                   ? cbor_tagged_stash
1060                                   : gv_stashpv ("CBOR::XS::Tagged" , 1);
1061               sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash);
1062             }
1063 
1064           PUTBACK;
1065 
1066           FREETMPS; LEAVE;
1067         }
1068         break;
1069     }
1070 
1071   return sv;
1072 
1073 fail:
1074   SvREFCNT_dec (sv);
1075   return &PL_sv_undef;
1076 }
1077 
1078 static SV *
decode_sv(dec_t * dec)1079 decode_sv (dec_t *dec)
1080 {
1081   WANT (1);
1082 
1083   switch (*dec->cur >> MAJOR_SHIFT)
1084     {
1085       case MAJOR_POS_INT >> MAJOR_SHIFT: return newSVuv (decode_uint (dec));
1086       case MAJOR_NEG_INT >> MAJOR_SHIFT: return newSViv (-1 - (IV)decode_uint (dec));
1087       case MAJOR_BYTES   >> MAJOR_SHIFT: return decode_str (dec, 0);
1088       case MAJOR_TEXT    >> MAJOR_SHIFT: return decode_str (dec, 1);
1089       case MAJOR_ARRAY   >> MAJOR_SHIFT: return decode_av (dec);
1090       case MAJOR_MAP     >> MAJOR_SHIFT: return decode_hv (dec);
1091       case MAJOR_TAG     >> MAJOR_SHIFT: return decode_tagged (dec);
1092 
1093       case MAJOR_MISC    >> MAJOR_SHIFT:
1094         switch (*dec->cur++ & MINOR_MASK)
1095           {
1096             case SIMPLE_FALSE:
1097 #if CBOR_SLOW
1098               types_false = get_bool ("Types::Serialiser::false");
1099 #endif
1100               return newSVsv (types_false);
1101             case SIMPLE_TRUE:
1102 #if CBOR_SLOW
1103               types_true = get_bool ("Types::Serialiser::true");
1104 #endif
1105               return newSVsv (types_true);
1106             case SIMPLE_NULL:
1107               return newSVsv (&PL_sv_undef);
1108             case SIMPLE_UNDEF:
1109 #if CBOR_SLOW
1110               types_error = get_bool ("Types::Serialiser::error");
1111 #endif
1112               return newSVsv (types_error);
1113 
1114             case MISC_FLOAT16:
1115               {
1116                 WANT (2);
1117 
1118                 uint16_t fp = (dec->cur[0] << 8) | dec->cur[1];
1119                 dec->cur += 2;
1120 
1121                 return newSVnv (ecb_binary16_to_float (fp));
1122               }
1123 
1124             case MISC_FLOAT32:
1125               {
1126                 uint32_t fp;
1127                 WANT (4);
1128                 memcpy (&fp, dec->cur, 4);
1129                 dec->cur += 4;
1130 
1131                 if (!ecb_big_endian ())
1132                   fp = ecb_bswap32 (fp);
1133 
1134                 return newSVnv (ecb_binary32_to_float (fp));
1135               }
1136 
1137             case MISC_FLOAT64:
1138               {
1139                 uint64_t fp;
1140                 WANT (8);
1141                 memcpy (&fp, dec->cur, 8);
1142                 dec->cur += 8;
1143 
1144                 if (!ecb_big_endian ())
1145                   fp = ecb_bswap64 (fp);
1146 
1147                 return newSVnv (ecb_binary64_to_double (fp));
1148               }
1149 
1150             // 0..19 unassigned simple
1151             // 24 reserved + unassigned simple (reserved values are not encodable)
1152             // 28-30 unassigned misc
1153             // 31 break code
1154             default:
1155               ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1156           }
1157 
1158         break;
1159   }
1160 
1161 fail:
1162   return &PL_sv_undef;
1163 }
1164 
1165 static SV *
decode_cbor(SV * string,CBOR * cbor,char ** offset_return)1166 decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1167 {
1168   dec_t dec = { };
1169   SV *sv;
1170   STRLEN len;
1171   char *data = SvPVbyte (string, len);
1172 
1173   if (len > cbor->max_size && cbor->max_size)
1174     croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1175            (unsigned long)len, (unsigned long)cbor->max_size);
1176 
1177   dec.cbor  = *cbor;
1178   dec.cur   = (U8 *)data;
1179   dec.end   = (U8 *)data + len;
1180 
1181   sv = decode_sv (&dec);
1182 
1183   if (offset_return)
1184     *offset_return = dec.cur;
1185 
1186   if (!(offset_return || !sv))
1187     if (dec.cur != dec.end && !dec.err)
1188       dec.err = "garbage after CBOR object";
1189 
1190   if (dec.err)
1191     {
1192       if (dec.shareable)
1193         {
1194           // need to break cyclic links, which whould all be in shareable
1195           int i;
1196           SV **svp;
1197 
1198           for (i = av_len (dec.shareable) + 1; i--; )
1199             if ((svp = av_fetch (dec.shareable, i, 0)))
1200               sv_setsv (*svp, &PL_sv_undef);
1201         }
1202 
1203       SvREFCNT_dec (sv);
1204       croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1205     }
1206 
1207   sv = sv_2mortal (sv);
1208 
1209   return sv;
1210 }
1211 
1212 /////////////////////////////////////////////////////////////////////////////
1213 // incremental parser
1214 
1215 #define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1216 
1217 // returns 0 for notyet, 1 for success or error
1218 static int
incr_parse(CBOR * self,SV * cborstr)1219 incr_parse (CBOR *self, SV *cborstr)
1220 {
1221   STRLEN cur;
1222   SvPV (cborstr, cur);
1223 
1224   while (ecb_expect_true (self->incr_need <= cur))
1225     {
1226       // table of integer count bytes
1227       static I8 incr_len[MINOR_MASK + 1] = {
1228         0, 0, 0, 0, 0, 0, 0, 0,
1229         0, 0, 0, 0, 0, 0, 0, 0,
1230         0, 0, 0, 0, 0, 0, 0, 0,
1231         1, 2, 4, 8,-1,-1,-1,-2
1232       };
1233 
1234       const U8 *p = SvPVX (cborstr) + self->incr_pos;
1235       U8 m = *p & MINOR_MASK;
1236       IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1237       I8 ilen = incr_len[m];
1238 
1239       self->incr_need = self->incr_pos + 1;
1240 
1241       if (ecb_expect_false (ilen < 0))
1242         {
1243           if (m != MINOR_INDEF)
1244             return 1; // error
1245 
1246           if (*p == (MAJOR_MISC | MINOR_INDEF))
1247             {
1248               if (count >= 0)
1249                 return 1; // error
1250 
1251               count = 1;
1252             }
1253           else
1254             {
1255               av_push (self->incr_count, newSViv (-1)); //TODO: nest
1256               count = -1;
1257             }
1258         }
1259       else
1260         {
1261           self->incr_need += ilen;
1262           if (ecb_expect_false (self->incr_need > cur))
1263             return 0;
1264 
1265           int major = *p >> MAJOR_SHIFT;
1266 
1267           switch (major)
1268             {
1269               case MAJOR_TAG     >> MAJOR_SHIFT:
1270                 ++count; // tags merely prefix another value
1271                 break;
1272 
1273               case MAJOR_BYTES   >> MAJOR_SHIFT:
1274               case MAJOR_TEXT    >> MAJOR_SHIFT:
1275               case MAJOR_ARRAY   >> MAJOR_SHIFT:
1276               case MAJOR_MAP     >> MAJOR_SHIFT:
1277                 {
1278                   UV len;
1279 
1280                   if (ecb_expect_false (ilen))
1281                     {
1282                       len = 0;
1283 
1284                       do {
1285                         len = (len << 8) | *++p;
1286                       } while (--ilen);
1287                     }
1288                   else
1289                     len = m;
1290 
1291                   switch (major)
1292                     {
1293                       case MAJOR_BYTES   >> MAJOR_SHIFT:
1294                       case MAJOR_TEXT    >> MAJOR_SHIFT:
1295                         self->incr_need += len;
1296                         if (ecb_expect_false (self->incr_need > cur))
1297                           return 0;
1298 
1299                         break;
1300 
1301                       case MAJOR_MAP     >> MAJOR_SHIFT:
1302                         len <<= 1;
1303                       case MAJOR_ARRAY   >> MAJOR_SHIFT:
1304                         if (len)
1305                           {
1306                             av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1307                             count = len + 1;
1308                           }
1309                         break;
1310                     }
1311                 }
1312             }
1313         }
1314 
1315       self->incr_pos = self->incr_need;
1316 
1317       if (count > 0)
1318         {
1319           while (!--count)
1320             {
1321               if (!AvFILLp (self->incr_count))
1322                 return 1; // done
1323 
1324               SvREFCNT_dec_NN (av_pop (self->incr_count));
1325               count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1326             }
1327 
1328           SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1329         }
1330     }
1331 
1332   return 0;
1333 }
1334 
1335 
1336 /////////////////////////////////////////////////////////////////////////////
1337 // XS interface functions
1338 
1339 MODULE = CBOR::XS		PACKAGE = CBOR::XS
1340 
1341 BOOT:
1342 {
1343 	cbor_stash         = gv_stashpv ("CBOR::XS"         , 1);
1344 	cbor_tagged_stash  = gv_stashpv ("CBOR::XS::Tagged" , 1);
1345 
1346 	types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
1347 	types_error_stash   = gv_stashpv ("Types::Serialiser::Error"  , 1);
1348 
1349         types_true  = get_bool ("Types::Serialiser::true" );
1350         types_false = get_bool ("Types::Serialiser::false");
1351         types_error = get_bool ("Types::Serialiser::error");
1352 
1353         default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1354 
1355         sv_cbor = newSVpv ("CBOR", 0);
1356         SvREADONLY_on (sv_cbor);
1357 }
1358 
1359 PROTOTYPES: DISABLE
1360 
1361 void CLONE (...)
1362 	CODE:
1363         cbor_stash          = 0;
1364         cbor_tagged_stash   = 0;
1365         types_error_stash   = 0;
1366         types_boolean_stash = 0;
1367 
new(char * klass)1368 void new (char *klass)
1369 	PPCODE:
1370 {
1371 	SV *pv = NEWSV (0, sizeof (CBOR));
1372         SvPOK_only (pv);
1373         cbor_init ((CBOR *)SvPVX (pv));
1374         XPUSHs (sv_2mortal (sv_bless (
1375            newRV_noinc (pv),
1376            strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
1377         )));
1378 }
1379 
1380 void shrink (CBOR *self, int enable = 1)
1381 	ALIAS:
1382         shrink          = F_SHRINK
1383         allow_unknown   = F_ALLOW_UNKNOWN
1384         allow_sharing   = F_ALLOW_SHARING
1385         allow_cycles    = F_ALLOW_CYCLES
1386         pack_strings    = F_PACK_STRINGS
1387         validate_utf8   = F_VALIDATE_UTF8
1388 	PPCODE:
1389 {
1390         if (enable)
1391           self->flags |=  ix;
1392         else
1393           self->flags &= ~ix;
1394 
1395         XPUSHs (ST (0));
1396 }
1397 
1398 void get_shrink (CBOR *self)
1399 	ALIAS:
1400         get_shrink          = F_SHRINK
1401         get_allow_unknown   = F_ALLOW_UNKNOWN
1402         get_allow_sharing   = F_ALLOW_SHARING
1403         get_allow_cycles    = F_ALLOW_CYCLES
1404         get_pack_strings    = F_PACK_STRINGS
1405         get_validate_utf8   = F_VALIDATE_UTF8
1406 	PPCODE:
1407         XPUSHs (boolSV (self->flags & ix));
1408 
1409 void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1410 	PPCODE:
1411         self->max_depth = max_depth;
1412         XPUSHs (ST (0));
1413 
1414 U32 get_max_depth (CBOR *self)
1415 	CODE:
1416         RETVAL = self->max_depth;
1417 	OUTPUT:
1418         RETVAL
1419 
1420 void max_size (CBOR *self, U32 max_size = 0)
1421 	PPCODE:
1422         self->max_size = max_size;
1423         XPUSHs (ST (0));
1424 
1425 int get_max_size (CBOR *self)
1426 	CODE:
1427         RETVAL = self->max_size;
1428 	OUTPUT:
1429         RETVAL
1430 
1431 void filter (CBOR *self, SV *filter = 0)
1432 	PPCODE:
1433         SvREFCNT_dec (self->filter);
1434         self->filter = filter ? newSVsv (filter) : filter;
1435         XPUSHs (ST (0));
1436 
1437 SV *get_filter (CBOR *self)
1438 	CODE:
1439         RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1440 	OUTPUT:
1441         RETVAL
1442 
1443 void encode (CBOR *self, SV *scalar)
1444 	PPCODE:
1445         PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
1446         XPUSHs (scalar);
1447 
1448 void decode (CBOR *self, SV *cborstr)
1449 	PPCODE:
1450         PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
1451         XPUSHs (cborstr);
1452 
decode_prefix(CBOR * self,SV * cborstr)1453 void decode_prefix (CBOR *self, SV *cborstr)
1454 	PPCODE:
1455 {
1456 	SV *sv;
1457         char *offset;
1458         PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1459         EXTEND (SP, 2);
1460         PUSHs (sv);
1461         PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1462 }
1463 
incr_parse(CBOR * self,SV * cborstr)1464 void incr_parse (CBOR *self, SV *cborstr)
1465 	ALIAS:
1466         incr_parse_multiple = 1
1467 	PPCODE:
1468 {
1469         if (SvUTF8 (cborstr))
1470           sv_utf8_downgrade (cborstr, 0);
1471 
1472         if (!self->incr_count)
1473           {
1474             self->incr_count = newAV ();
1475             self->incr_pos   = 0;
1476             self->incr_need  = 1;
1477 
1478             av_push (self->incr_count, newSViv (1));
1479           }
1480 
1481         do
1482           {
1483             if (!incr_parse (self, cborstr))
1484               {
1485                 if (self->incr_need > self->max_size && self->max_size)
1486                   croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1487                          (unsigned long)self->incr_need, (unsigned long)self->max_size);
1488 
1489                 break;
1490               }
1491 
1492             SV *sv;
1493             char *offset;
1494 
1495             PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1496             XPUSHs (sv);
1497 
1498             sv_chop (cborstr, offset);
1499 
1500             av_clear (self->incr_count);
1501             av_push (self->incr_count, newSViv (1));
1502 
1503             self->incr_pos = 0;
1504             self->incr_need = self->incr_pos + 1;
1505           }
1506         while (ix);
1507 }
1508 
incr_reset(CBOR * self)1509 void incr_reset (CBOR *self)
1510 	CODE:
1511 {
1512 	SvREFCNT_dec (self->incr_count);
1513         self->incr_count = 0;
1514 }
1515 
1516 void DESTROY (CBOR *self)
1517 	PPCODE:
1518 	cbor_free (self);
1519 
1520 PROTOTYPES: ENABLE
1521 
encode_cbor(SV * scalar)1522 void encode_cbor (SV *scalar)
1523 	ALIAS:
1524         encode_cbor         = 0
1525         encode_cbor_sharing = F_ALLOW_SHARING
1526 	PPCODE:
1527 {
1528         CBOR cbor;
1529         cbor_init (&cbor);
1530         cbor.flags |= ix;
1531         PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1532         XPUSHs (scalar);
1533 }
1534 
decode_cbor(SV * cborstr)1535 void decode_cbor (SV *cborstr)
1536 	PPCODE:
1537 {
1538         CBOR cbor;
1539         cbor_init (&cbor);
1540         PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
1541         XPUSHs (cborstr);
1542 }
1543 
1544