ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.46
Committed: Sun Dec 14 05:57:22 2014 UTC (9 years, 5 months ago) by root
Branch: MAIN
Changes since 1.45: +4 -1 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 root 1.45 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 root 1.46 {
338     SV *sv = AvARRAY (av)[i];
339     encode_sv (enc, sv ? sv : &PL_sv_undef);
340     }
341 root 1.1
342     --enc->depth;
343     }
344    
345     static void
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 root 1.35 encode_ch (enc, MAJOR_MAP | MINOR_INDEF);
360 root 1.1 else
361 root 1.35 encode_uint (enc, MAJOR_MAP, pairs);
362 root 1.1
363     while ((he = hv_iternext (hv)))
364     {
365 root 1.21 if (HeKLEN (he) == HEf_SVKEY)
366     encode_sv (enc, HeSVKEY (he));
367 root 1.1 else
368 root 1.30 encode_strref (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he));
369 root 1.1
370 root 1.5 encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he));
371 root 1.1 }
372    
373     if (mg)
374 root 1.35 encode_ch (enc, MAJOR_MISC | MINOR_INDEF);
375 root 1.1
376     --enc->depth;
377     }
378    
379     // encode objects, arrays and special \0=false and \1=true values.
380     static void
381     encode_rv (enc_t *enc, SV *sv)
382     {
383 root 1.19 SvGETMAGIC (sv);
384 root 1.1
385 root 1.19 svtype svt = SvTYPE (sv);
386 root 1.18
387 root 1.5 if (ecb_expect_false (SvOBJECT (sv)))
388 root 1.1 {
389 root 1.10 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 root 1.6 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
396     ? cbor_tagged_stash
397     : gv_stashpv ("CBOR::XS::Tagged" , 1);
398 root 1.1
399 root 1.11 HV *stash = SvSTASH (sv);
400    
401     if (stash == boolean_stash)
402 root 1.34 {
403 root 1.35 encode_ch (enc, SvIV (sv) ? MAJOR_MISC | SIMPLE_TRUE : MAJOR_MISC | SIMPLE_FALSE);
404 root 1.34 return;
405     }
406 root 1.11 else if (stash == error_stash)
407 root 1.34 {
408 root 1.35 encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
409 root 1.34 return;
410     }
411 root 1.11 else if (stash == tagged_stash)
412 root 1.6 {
413     if (svt != SVt_PVAV)
414     croak ("encountered CBOR::XS::Tagged object that isn't an array");
415    
416 root 1.35 encode_uint (enc, MAJOR_TAG, SvUV (*av_fetch ((AV *)sv, 0, 1)));
417 root 1.6 encode_sv (enc, *av_fetch ((AV *)sv, 1, 1));
418 root 1.34
419     return;
420 root 1.6 }
421 root 1.34 }
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 root 1.35 encode_uint (enc, MAJOR_POS_INT, SvUV (*svp));
435 root 1.34 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 root 1.1 {
452 root 1.11 dSP;
453    
454     ENTER; SAVETMPS; PUSHMARK (SP);
455 root 1.6 // we re-bless the reference to get overload and other niceties right
456 root 1.11 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 root 1.6
477 root 1.11 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 root 1.1
483 root 1.11 PUTBACK;
484     int count = call_sv ((SV *)GvCV (method), G_ARRAY);
485     SPAGAIN;
486 root 1.6
487 root 1.11 // 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 root 1.6
491 root 1.18 encode_tag (enc, CBOR_TAG_PERL_OBJECT);
492 root 1.35 encode_uint (enc, MAJOR_ARRAY, count + 1);
493 root 1.30 encode_strref (enc, HvNAMEUTF8 (stash), HvNAME (stash), HvNAMELEN (stash));
494 root 1.6
495 root 1.11 while (count)
496     encode_sv (enc, SP[1 - count--]);
497 root 1.6
498 root 1.11 PUTBACK;
499 root 1.6
500 root 1.11 FREETMPS; LEAVE;
501 root 1.1 }
502 root 1.11 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 root 1.1 }
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 root 1.18 else
511 root 1.1 {
512 root 1.18 encode_tag (enc, CBOR_TAG_INDIRECTION);
513     encode_sv (enc, sv);
514 root 1.1 }
515     }
516    
517     static void
518     encode_nv (enc_t *enc, SV *sv)
519     {
520     double nv = SvNVX (sv);
521    
522     need (enc, 9);
523    
524 root 1.35 if (ecb_expect_false (nv == (NV)(U32)nv))
525     encode_uint (enc, MAJOR_POS_INT, (U32)nv);
526 root 1.1 //TODO: maybe I32?
527 root 1.5 else if (ecb_expect_false (nv == (float)nv))
528 root 1.1 {
529     uint32_t fp = ecb_float_to_binary32 (nv);
530    
531 root 1.35 *enc->cur++ = MAJOR_MISC | MISC_FLOAT32;
532 root 1.1
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 root 1.35 *enc->cur++ = MAJOR_MISC | MISC_FLOAT64;
544 root 1.1
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
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 root 1.30 encode_strref (enc, SvUTF8 (sv), str, len);
563 root 1.1 }
564     else if (SvNOKp (sv))
565     encode_nv (enc, sv);
566     else if (SvIOKp (sv))
567     {
568     if (SvIsUV (sv))
569 root 1.35 encode_uint (enc, MAJOR_POS_INT, SvUVX (sv));
570 root 1.1 else if (SvIVX (sv) >= 0)
571 root 1.35 encode_uint (enc, MAJOR_POS_INT, SvIVX (sv));
572 root 1.1 else
573 root 1.35 encode_uint (enc, MAJOR_NEG_INT, -(SvIVX (sv) + 1));
574 root 1.1 }
575     else if (SvROK (sv))
576     encode_rv (enc, SvRV (sv));
577     else if (!SvOK (sv))
578 root 1.35 encode_ch (enc, MAJOR_MISC | SIMPLE_NULL);
579 root 1.1 else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
580 root 1.35 encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
581 root 1.1 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 *
587     encode_cbor (SV *scalar, CBOR *cbor)
588     {
589 root 1.18 enc_t enc = { };
590 root 1.1
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 root 1.20
598 root 1.32 if (cbor->flags & F_PACK_STRINGS)
599 root 1.20 {
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 root 1.1 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 root 1.19 AV *shareable;
629 root 1.20 AV *stringref;
630 root 1.27 SV *decode_tagged;
631 root 1.1 } dec_t;
632    
633     #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
634    
635 root 1.5 #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
636 root 1.1
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
641     decode_uint (dec_t *dec)
642     {
643 root 1.35 U8 m = *dec->cur & MINOR_MASK;
644     ++dec->cur;
645    
646     if (ecb_expect_true (m < LENGTH_EXT1))
647     return m;
648 root 1.36 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 root 1.1 {
672 root 1.36 WANT (8);
673     dec->cur += 8;
674 root 1.34
675 root 1.36 return
676 root 1.34 #if UVSIZE < 8
677 root 1.36 0
678 root 1.34 #else
679 root 1.36 (((UV)dec->cur[-8]) << 56)
680     | (((UV)dec->cur[-7]) << 48)
681     | (((UV)dec->cur[-6]) << 40)
682     | (((UV)dec->cur[-5]) << 32)
683 root 1.34 #endif
684 root 1.36 | (((UV)dec->cur[-4]) << 24)
685     | (((UV)dec->cur[-3]) << 16)
686     | (((UV)dec->cur[-2]) << 8)
687     | ((UV)dec->cur[-1]);
688 root 1.1 }
689 root 1.36 else
690     ERR ("corrupted CBOR data (unsupported integer minor encoding)");
691 root 1.1
692     fail:
693     return 0;
694     }
695    
696     static SV *decode_sv (dec_t *dec);
697    
698     static SV *
699     decode_av (dec_t *dec)
700     {
701     AV *av = newAV ();
702    
703     DEC_INC_DEPTH;
704    
705 root 1.35 if (*dec->cur == (MAJOR_ARRAY | MINOR_INDEF))
706 root 1.1 {
707     ++dec->cur;
708    
709     for (;;)
710     {
711     WANT (1);
712    
713 root 1.35 if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
714 root 1.1 {
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 root 1.36 WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays
727 root 1.1 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 root 1.16 static void
743     decode_he (dec_t *dec, HV *hv)
744     {
745     // for speed reasons, we specialcase single-string
746 root 1.21 // byte or utf-8 strings as keys, but only when !stringref
747    
748 root 1.23 if (ecb_expect_true (!dec->stringref))
749 root 1.43 if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
750 root 1.21 {
751     I32 len = decode_uint (dec);
752     char *key = (char *)dec->cur;
753 root 1.16
754 root 1.21 dec->cur += len;
755    
756     hv_store (hv, key, len, decode_sv (dec), 0);
757 root 1.16
758 root 1.21 return;
759     }
760 root 1.43 else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
761 root 1.21 {
762     I32 len = decode_uint (dec);
763     char *key = (char *)dec->cur;
764 root 1.16
765 root 1.21 dec->cur += len;
766 root 1.20
767 root 1.38 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 root 1.16
771 root 1.21 hv_store (hv, key, -len, decode_sv (dec), 0);
772 root 1.16
773 root 1.21 return;
774     }
775 root 1.20
776 root 1.21 SV *k = decode_sv (dec);
777     SV *v = decode_sv (dec);
778 root 1.16
779 root 1.21 hv_store_ent (hv, k, v, 0);
780     SvREFCNT_dec (k);
781 root 1.38
782     fail:
783     ;
784 root 1.16 }
785    
786 root 1.1 static SV *
787     decode_hv (dec_t *dec)
788     {
789     HV *hv = newHV ();
790    
791     DEC_INC_DEPTH;
792    
793 root 1.35 if (*dec->cur == (MAJOR_MAP | MINOR_INDEF))
794 root 1.1 {
795     ++dec->cur;
796    
797     for (;;)
798     {
799     WANT (1);
800    
801 root 1.35 if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
802 root 1.1 {
803     ++dec->cur;
804     break;
805     }
806    
807 root 1.16 decode_he (dec, hv);
808 root 1.1 }
809     }
810     else
811     {
812 root 1.16 int pairs = decode_uint (dec);
813 root 1.1
814 root 1.16 while (pairs--)
815     decode_he (dec, hv);
816 root 1.1 }
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 *
828     decode_str (dec_t *dec, int utf8)
829     {
830 root 1.6 SV *sv = 0;
831 root 1.1
832 root 1.35 if ((*dec->cur & MINOR_MASK) == MINOR_INDEF)
833 root 1.1 {
834 root 1.33 // indefinite length strings
835 root 1.1 ++dec->cur;
836    
837 root 1.35 U8 major = *dec->cur & MAJOR_MISC;
838 root 1.33
839 root 1.1 sv = newSVpvn ("", 0);
840    
841     for (;;)
842     {
843     WANT (1);
844    
845 root 1.35 if ((*dec->cur - major) > LENGTH_EXT8)
846     if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
847 root 1.33 {
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 root 1.1
856 root 1.33 WANT (len);
857     sv_catpvn (sv, dec->cur, len);
858     dec->cur += len;
859 root 1.1 }
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 root 1.25
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 root 1.1 }
873    
874     if (utf8)
875 root 1.38 {
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 root 1.1
883     return sv;
884    
885     fail:
886 root 1.6 SvREFCNT_dec (sv);
887 root 1.1 return &PL_sv_undef;
888     }
889    
890     static SV *
891 root 1.3 decode_tagged (dec_t *dec)
892     {
893 root 1.19 SV *sv = 0;
894 root 1.3 UV tag = decode_uint (dec);
895 root 1.19
896     WANT (1);
897 root 1.3
898 root 1.18 switch (tag)
899     {
900     case CBOR_TAG_MAGIC:
901 root 1.20 sv = decode_sv (dec);
902     break;
903 root 1.18
904     case CBOR_TAG_INDIRECTION:
905 root 1.20 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 root 1.35 if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
924 root 1.20 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 root 1.11
935 root 1.19 case CBOR_TAG_VALUE_SHAREABLE:
936     {
937     if (ecb_expect_false (!dec->shareable))
938     dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
939    
940 root 1.37 if (dec->cbor.flags & F_ALLOW_CYCLES)
941     {
942     sv = newSV (0);
943     av_push (dec->shareable, SvREFCNT_inc_NN (sv));
944 root 1.18
945 root 1.37 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 root 1.19 }
957 root 1.20 break;
958 root 1.18
959     case CBOR_TAG_VALUE_SHAREDREF:
960 root 1.17 {
961 root 1.35 if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
962 root 1.19 ERR ("corrupted CBOR data (sharedref index not an unsigned integer)");
963 root 1.18
964 root 1.19 UV idx = decode_uint (dec);
965    
966 root 1.20 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable))
967 root 1.18 ERR ("corrupted CBOR data (sharedref index out of bounds)");
968    
969 root 1.20 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
970 root 1.37
971     if (sv == &PL_sv_undef)
972     ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
973 root 1.17 }
974 root 1.20 break;
975 root 1.17
976 root 1.18 case CBOR_TAG_PERL_OBJECT:
977     {
978 root 1.19 sv = decode_sv (dec);
979    
980 root 1.18 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 root 1.11
1021 root 1.18 PUTBACK;
1022 root 1.11
1023 root 1.18 FREETMPS; LEAVE;
1024     }
1025 root 1.20 break;
1026 root 1.9
1027 root 1.18 default:
1028     {
1029 root 1.19 sv = decode_sv (dec);
1030    
1031 root 1.27 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 root 1.7
1064 root 1.27 PUTBACK;
1065    
1066     FREETMPS; LEAVE;
1067 root 1.18 }
1068 root 1.20 break;
1069 root 1.11 }
1070 root 1.9
1071 root 1.20 return sv;
1072    
1073 root 1.9 fail:
1074     SvREFCNT_dec (sv);
1075     return &PL_sv_undef;
1076 root 1.3 }
1077    
1078     static SV *
1079 root 1.1 decode_sv (dec_t *dec)
1080     {
1081     WANT (1);
1082    
1083 root 1.35 switch (*dec->cur >> MAJOR_SHIFT)
1084 root 1.1 {
1085 root 1.35 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 root 1.1 {
1096 root 1.35 case SIMPLE_FALSE:
1097 root 1.1 #if CBOR_SLOW
1098 root 1.10 types_false = get_bool ("Types::Serialiser::false");
1099 root 1.1 #endif
1100 root 1.10 return newSVsv (types_false);
1101 root 1.35 case SIMPLE_TRUE:
1102 root 1.1 #if CBOR_SLOW
1103 root 1.10 types_true = get_bool ("Types::Serialiser::true");
1104 root 1.1 #endif
1105 root 1.10 return newSVsv (types_true);
1106 root 1.35 case SIMPLE_NULL:
1107 root 1.1 return newSVsv (&PL_sv_undef);
1108 root 1.35 case SIMPLE_UNDEF:
1109 root 1.10 #if CBOR_SLOW
1110     types_error = get_bool ("Types::Serialiser::error");
1111     #endif
1112     return newSVsv (types_error);
1113 root 1.1
1114 root 1.35 case MISC_FLOAT16:
1115 root 1.2 {
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 root 1.1
1124 root 1.35 case MISC_FLOAT32:
1125 root 1.1 {
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 root 1.35 case MISC_FLOAT64:
1138 root 1.1 {
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 root 1.35 // 0..19 unassigned simple
1151 root 1.40 // 24 reserved + unassigned simple (reserved values are not encodable)
1152     // 28-30 unassigned misc
1153     // 31 break code
1154 root 1.1 default:
1155 root 1.40 ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1156 root 1.1 }
1157    
1158     break;
1159     }
1160    
1161     fail:
1162     return &PL_sv_undef;
1163     }
1164    
1165     static SV *
1166     decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1167     {
1168 root 1.18 dec_t dec = { };
1169 root 1.1 SV *sv;
1170 root 1.16 STRLEN len;
1171     char *data = SvPVbyte (string, len);
1172 root 1.1
1173 root 1.16 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 root 1.1
1177     dec.cbor = *cbor;
1178 root 1.16 dec.cur = (U8 *)data;
1179     dec.end = (U8 *)data + len;
1180 root 1.1
1181     sv = decode_sv (&dec);
1182    
1183     if (offset_return)
1184     *offset_return = dec.cur;
1185    
1186     if (!(offset_return || !sv))
1187 root 1.2 if (dec.cur != dec.end && !dec.err)
1188     dec.err = "garbage after CBOR object";
1189    
1190     if (dec.err)
1191 root 1.1 {
1192 root 1.39 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 root 1.2 SvREFCNT_dec (sv);
1204 root 1.16 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1205 root 1.1 }
1206    
1207     sv = sv_2mortal (sv);
1208    
1209     return sv;
1210     }
1211    
1212     /////////////////////////////////////////////////////////////////////////////
1213 root 1.40 // 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
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_BYTES >> MAJOR_SHIFT:
1270     case MAJOR_TEXT >> MAJOR_SHIFT:
1271     case MAJOR_ARRAY >> MAJOR_SHIFT:
1272     case MAJOR_MAP >> MAJOR_SHIFT:
1273     {
1274     UV len;
1275    
1276     if (ecb_expect_false (ilen))
1277     {
1278     len = 0;
1279    
1280     do {
1281     len = (len << 8) | *++p;
1282     } while (--ilen);
1283     }
1284     else
1285     len = m;
1286    
1287     switch (major)
1288     {
1289     case MAJOR_BYTES >> MAJOR_SHIFT:
1290     case MAJOR_TEXT >> MAJOR_SHIFT:
1291     self->incr_need += len;
1292     if (ecb_expect_false (self->incr_need > cur))
1293     return 0;
1294    
1295     break;
1296    
1297     case MAJOR_MAP >> MAJOR_SHIFT:
1298     len <<= 1;
1299     case MAJOR_ARRAY >> MAJOR_SHIFT:
1300     if (len)
1301     {
1302     av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1303     count = len + 1;
1304     }
1305     break;
1306     }
1307     }
1308     }
1309     }
1310    
1311     self->incr_pos = self->incr_need;
1312    
1313     if (count > 0)
1314     {
1315     while (!--count)
1316     {
1317     if (!AvFILLp (self->incr_count))
1318     return 1; // done
1319    
1320     SvREFCNT_dec_NN (av_pop (self->incr_count));
1321     count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1322     }
1323    
1324     SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1325     }
1326     }
1327    
1328     return 0;
1329     }
1330    
1331    
1332     /////////////////////////////////////////////////////////////////////////////
1333 root 1.1 // XS interface functions
1334    
1335     MODULE = CBOR::XS PACKAGE = CBOR::XS
1336    
1337     BOOT:
1338     {
1339     cbor_stash = gv_stashpv ("CBOR::XS" , 1);
1340 root 1.6 cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1);
1341 root 1.1
1342 root 1.10 types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
1343     types_error_stash = gv_stashpv ("Types::Serialiser::Error" , 1);
1344    
1345     types_true = get_bool ("Types::Serialiser::true" );
1346     types_false = get_bool ("Types::Serialiser::false");
1347     types_error = get_bool ("Types::Serialiser::error");
1348 root 1.11
1349 root 1.27 default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1350    
1351 root 1.11 sv_cbor = newSVpv ("CBOR", 0);
1352     SvREADONLY_on (sv_cbor);
1353 root 1.1 }
1354    
1355     PROTOTYPES: DISABLE
1356    
1357     void CLONE (...)
1358     CODE:
1359 root 1.10 cbor_stash = 0;
1360     cbor_tagged_stash = 0;
1361     types_error_stash = 0;
1362     types_boolean_stash = 0;
1363 root 1.1
1364     void new (char *klass)
1365     PPCODE:
1366     {
1367     SV *pv = NEWSV (0, sizeof (CBOR));
1368     SvPOK_only (pv);
1369     cbor_init ((CBOR *)SvPVX (pv));
1370     XPUSHs (sv_2mortal (sv_bless (
1371     newRV_noinc (pv),
1372     strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
1373     )));
1374     }
1375    
1376     void shrink (CBOR *self, int enable = 1)
1377     ALIAS:
1378     shrink = F_SHRINK
1379     allow_unknown = F_ALLOW_UNKNOWN
1380 root 1.18 allow_sharing = F_ALLOW_SHARING
1381 root 1.37 allow_cycles = F_ALLOW_CYCLES
1382 root 1.32 pack_strings = F_PACK_STRINGS
1383 root 1.38 validate_utf8 = F_VALIDATE_UTF8
1384 root 1.1 PPCODE:
1385     {
1386     if (enable)
1387     self->flags |= ix;
1388     else
1389     self->flags &= ~ix;
1390    
1391     XPUSHs (ST (0));
1392     }
1393    
1394     void get_shrink (CBOR *self)
1395     ALIAS:
1396     get_shrink = F_SHRINK
1397     get_allow_unknown = F_ALLOW_UNKNOWN
1398 root 1.18 get_allow_sharing = F_ALLOW_SHARING
1399 root 1.37 get_allow_cycles = F_ALLOW_CYCLES
1400 root 1.32 get_pack_strings = F_PACK_STRINGS
1401 root 1.38 get_validate_utf8 = F_VALIDATE_UTF8
1402 root 1.1 PPCODE:
1403     XPUSHs (boolSV (self->flags & ix));
1404    
1405     void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1406     PPCODE:
1407     self->max_depth = max_depth;
1408     XPUSHs (ST (0));
1409    
1410     U32 get_max_depth (CBOR *self)
1411     CODE:
1412     RETVAL = self->max_depth;
1413     OUTPUT:
1414     RETVAL
1415    
1416     void max_size (CBOR *self, U32 max_size = 0)
1417     PPCODE:
1418     self->max_size = max_size;
1419     XPUSHs (ST (0));
1420    
1421     int get_max_size (CBOR *self)
1422     CODE:
1423     RETVAL = self->max_size;
1424     OUTPUT:
1425     RETVAL
1426    
1427 root 1.27 void filter (CBOR *self, SV *filter = 0)
1428     PPCODE:
1429     SvREFCNT_dec (self->filter);
1430     self->filter = filter ? newSVsv (filter) : filter;
1431     XPUSHs (ST (0));
1432    
1433     SV *get_filter (CBOR *self)
1434     CODE:
1435     RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1436     OUTPUT:
1437     RETVAL
1438    
1439 root 1.1 void encode (CBOR *self, SV *scalar)
1440     PPCODE:
1441     PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
1442     XPUSHs (scalar);
1443    
1444     void decode (CBOR *self, SV *cborstr)
1445     PPCODE:
1446     PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
1447     XPUSHs (cborstr);
1448    
1449     void decode_prefix (CBOR *self, SV *cborstr)
1450     PPCODE:
1451     {
1452     SV *sv;
1453     char *offset;
1454     PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1455     EXTEND (SP, 2);
1456     PUSHs (sv);
1457     PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1458     }
1459    
1460 root 1.41 void incr_parse (CBOR *self, SV *cborstr)
1461 root 1.42 ALIAS:
1462     incr_parse_multiple = 1
1463 root 1.40 PPCODE:
1464     {
1465     if (SvUTF8 (cborstr))
1466     sv_utf8_downgrade (cborstr, 0);
1467    
1468     if (!self->incr_count)
1469     {
1470     self->incr_count = newAV ();
1471     self->incr_pos = 0;
1472     self->incr_need = 1;
1473    
1474     av_push (self->incr_count, newSViv (1));
1475     }
1476    
1477 root 1.41 do
1478 root 1.40 {
1479     if (!incr_parse (self, cborstr))
1480     {
1481     if (self->incr_need > self->max_size && self->max_size)
1482     croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1483     (unsigned long)self->incr_need, (unsigned long)self->max_size);
1484    
1485     break;
1486     }
1487    
1488 root 1.41 SV *sv;
1489     char *offset;
1490 root 1.40
1491 root 1.41 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1492     XPUSHs (sv);
1493 root 1.40
1494 root 1.41 sv_chop (cborstr, offset);
1495 root 1.40
1496 root 1.41 av_clear (self->incr_count);
1497     av_push (self->incr_count, newSViv (1));
1498 root 1.40
1499 root 1.41 self->incr_pos = 0;
1500     self->incr_need = self->incr_pos + 1;
1501 root 1.40 }
1502 root 1.42 while (ix);
1503 root 1.40 }
1504    
1505     void incr_reset (CBOR *self)
1506     CODE:
1507     {
1508     SvREFCNT_dec (self->incr_count);
1509     self->incr_count = 0;
1510     }
1511    
1512 root 1.27 void DESTROY (CBOR *self)
1513     PPCODE:
1514     cbor_free (self);
1515    
1516 root 1.1 PROTOTYPES: ENABLE
1517    
1518     void encode_cbor (SV *scalar)
1519 root 1.36 ALIAS:
1520     encode_cbor = 0
1521     encode_cbor_sharing = F_ALLOW_SHARING
1522 root 1.1 PPCODE:
1523     {
1524     CBOR cbor;
1525     cbor_init (&cbor);
1526 root 1.36 cbor.flags |= ix;
1527 root 1.1 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1528     XPUSHs (scalar);
1529     }
1530    
1531     void decode_cbor (SV *cborstr)
1532     PPCODE:
1533     {
1534     CBOR cbor;
1535     cbor_init (&cbor);
1536     PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
1537     XPUSHs (cborstr);
1538     }
1539