ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.44
Committed: Tue Feb 18 22:12:12 2014 UTC (10 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-1_26
Changes since 1.43: +1 -0 lines
Log Message:
*** empty log message ***

File Contents

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