ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.43
Committed: Sun Jan 5 14:24:54 2014 UTC (10 years, 4 months ago) by root
Branch: MAIN
CVS Tags: rel-1_25
Changes since 1.42: +2 -2 lines
Log Message:
1.25

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