ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.49
Committed: Mon Feb 8 04:11:11 2016 UTC (8 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-1_4
Changes since 1.48: +3 -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.48 enc_t enc = { 0 };
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.49 WANT (len);
755 root 1.21 dec->cur += len;
756    
757 root 1.49 hv_store (hv, key, len, decode_sv (dec), 0);
758 root 1.16
759 root 1.21 return;
760     }
761 root 1.43 else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
762 root 1.21 {
763     I32 len = decode_uint (dec);
764     char *key = (char *)dec->cur;
765 root 1.16
766 root 1.49 WANT (len);
767 root 1.21 dec->cur += len;
768 root 1.20
769 root 1.38 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
770     if (!is_utf8_string (key, len))
771     ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
772 root 1.16
773 root 1.21 hv_store (hv, key, -len, decode_sv (dec), 0);
774 root 1.16
775 root 1.21 return;
776     }
777 root 1.20
778 root 1.21 SV *k = decode_sv (dec);
779     SV *v = decode_sv (dec);
780 root 1.16
781 root 1.21 hv_store_ent (hv, k, v, 0);
782     SvREFCNT_dec (k);
783 root 1.38
784     fail:
785     ;
786 root 1.16 }
787    
788 root 1.1 static SV *
789     decode_hv (dec_t *dec)
790     {
791     HV *hv = newHV ();
792    
793     DEC_INC_DEPTH;
794    
795 root 1.35 if (*dec->cur == (MAJOR_MAP | MINOR_INDEF))
796 root 1.1 {
797     ++dec->cur;
798    
799     for (;;)
800     {
801     WANT (1);
802    
803 root 1.35 if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
804 root 1.1 {
805     ++dec->cur;
806     break;
807     }
808    
809 root 1.16 decode_he (dec, hv);
810 root 1.1 }
811     }
812     else
813     {
814 root 1.16 int pairs = decode_uint (dec);
815 root 1.1
816 root 1.16 while (pairs--)
817     decode_he (dec, hv);
818 root 1.1 }
819    
820     DEC_DEC_DEPTH;
821     return newRV_noinc ((SV *)hv);
822    
823     fail:
824     SvREFCNT_dec (hv);
825     DEC_DEC_DEPTH;
826     return &PL_sv_undef;
827     }
828    
829     static SV *
830     decode_str (dec_t *dec, int utf8)
831     {
832 root 1.6 SV *sv = 0;
833 root 1.1
834 root 1.35 if ((*dec->cur & MINOR_MASK) == MINOR_INDEF)
835 root 1.1 {
836 root 1.33 // indefinite length strings
837 root 1.1 ++dec->cur;
838    
839 root 1.35 U8 major = *dec->cur & MAJOR_MISC;
840 root 1.33
841 root 1.1 sv = newSVpvn ("", 0);
842    
843     for (;;)
844     {
845     WANT (1);
846    
847 root 1.35 if ((*dec->cur - major) > LENGTH_EXT8)
848     if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
849 root 1.33 {
850     ++dec->cur;
851     break;
852     }
853     else
854     ERR ("corrupted CBOR data (invalid chunks in indefinite length string)");
855    
856     STRLEN len = decode_uint (dec);
857 root 1.1
858 root 1.33 WANT (len);
859     sv_catpvn (sv, dec->cur, len);
860     dec->cur += len;
861 root 1.1 }
862     }
863     else
864     {
865     STRLEN len = decode_uint (dec);
866    
867     WANT (len);
868     sv = newSVpvn (dec->cur, len);
869     dec->cur += len;
870 root 1.25
871     if (ecb_expect_false (dec->stringref)
872     && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
873     av_push (dec->stringref, SvREFCNT_inc_NN (sv));
874 root 1.1 }
875    
876     if (utf8)
877 root 1.38 {
878     if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
879     if (!is_utf8_string (SvPVX (sv), SvCUR (sv)))
880     ERR ("corrupted CBOR data (invalid UTF-8 in text string)");
881    
882     SvUTF8_on (sv);
883     }
884 root 1.1
885     return sv;
886    
887     fail:
888 root 1.6 SvREFCNT_dec (sv);
889 root 1.1 return &PL_sv_undef;
890     }
891    
892     static SV *
893 root 1.3 decode_tagged (dec_t *dec)
894     {
895 root 1.19 SV *sv = 0;
896 root 1.3 UV tag = decode_uint (dec);
897 root 1.19
898     WANT (1);
899 root 1.3
900 root 1.18 switch (tag)
901     {
902     case CBOR_TAG_MAGIC:
903 root 1.20 sv = decode_sv (dec);
904     break;
905 root 1.18
906     case CBOR_TAG_INDIRECTION:
907 root 1.20 sv = newRV_noinc (decode_sv (dec));
908     break;
909    
910     case CBOR_TAG_STRINGREF_NAMESPACE:
911     {
912     ENTER; SAVETMPS;
913    
914     SAVESPTR (dec->stringref);
915     dec->stringref = (AV *)sv_2mortal ((SV *)newAV ());
916    
917     sv = decode_sv (dec);
918    
919     FREETMPS; LEAVE;
920     }
921     break;
922    
923     case CBOR_TAG_STRINGREF:
924     {
925 root 1.35 if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
926 root 1.20 ERR ("corrupted CBOR data (stringref index not an unsigned integer)");
927    
928     UV idx = decode_uint (dec);
929    
930     if (!dec->stringref || (int)idx > AvFILLp (dec->stringref))
931     ERR ("corrupted CBOR data (stringref index out of bounds or outside namespace)");
932    
933     sv = newSVsv (AvARRAY (dec->stringref)[idx]);
934     }
935     break;
936 root 1.11
937 root 1.19 case CBOR_TAG_VALUE_SHAREABLE:
938     {
939     if (ecb_expect_false (!dec->shareable))
940     dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
941    
942 root 1.37 if (dec->cbor.flags & F_ALLOW_CYCLES)
943     {
944     sv = newSV (0);
945     av_push (dec->shareable, SvREFCNT_inc_NN (sv));
946 root 1.18
947 root 1.37 SV *osv = decode_sv (dec);
948     sv_setsv (sv, osv);
949     SvREFCNT_dec_NN (osv);
950     }
951     else
952     {
953     av_push (dec->shareable, &PL_sv_undef);
954     int idx = AvFILLp (dec->shareable);
955     sv = decode_sv (dec);
956     av_store (dec->shareable, idx, SvREFCNT_inc_NN (sv));
957     }
958 root 1.19 }
959 root 1.20 break;
960 root 1.18
961     case CBOR_TAG_VALUE_SHAREDREF:
962 root 1.17 {
963 root 1.35 if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
964 root 1.19 ERR ("corrupted CBOR data (sharedref index not an unsigned integer)");
965 root 1.18
966 root 1.19 UV idx = decode_uint (dec);
967    
968 root 1.20 if (!dec->shareable || (int)idx > AvFILLp (dec->shareable))
969 root 1.18 ERR ("corrupted CBOR data (sharedref index out of bounds)");
970    
971 root 1.20 sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
972 root 1.37
973     if (sv == &PL_sv_undef)
974     ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
975 root 1.17 }
976 root 1.20 break;
977 root 1.17
978 root 1.18 case CBOR_TAG_PERL_OBJECT:
979     {
980 root 1.19 sv = decode_sv (dec);
981    
982 root 1.18 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
983     ERR ("corrupted CBOR data (non-array perl object)");
984    
985     AV *av = (AV *)SvRV (sv);
986     int len = av_len (av) + 1;
987     HV *stash = gv_stashsv (*av_fetch (av, 0, 1), 0);
988    
989     if (!stash)
990     ERR ("cannot decode perl-object (package does not exist)");
991    
992     GV *method = gv_fetchmethod_autoload (stash, "THAW", 0);
993    
994     if (!method)
995     ERR ("cannot decode perl-object (package does not have a THAW method)");
996    
997     dSP;
998    
999     ENTER; SAVETMPS; PUSHMARK (SP);
1000     EXTEND (SP, len + 1);
1001     // we re-bless the reference to get overload and other niceties right
1002     PUSHs (*av_fetch (av, 0, 1));
1003     PUSHs (sv_cbor);
1004    
1005     int i;
1006    
1007     for (i = 1; i < len; ++i)
1008     PUSHs (*av_fetch (av, i, 1));
1009    
1010     PUTBACK;
1011     call_sv ((SV *)GvCV (method), G_SCALAR | G_EVAL);
1012     SPAGAIN;
1013    
1014     if (SvTRUE (ERRSV))
1015     {
1016     FREETMPS; LEAVE;
1017     ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV))));
1018     }
1019    
1020     SvREFCNT_dec (sv);
1021     sv = SvREFCNT_inc (POPs);
1022 root 1.11
1023 root 1.18 PUTBACK;
1024 root 1.11
1025 root 1.18 FREETMPS; LEAVE;
1026     }
1027 root 1.20 break;
1028 root 1.9
1029 root 1.18 default:
1030     {
1031 root 1.19 sv = decode_sv (dec);
1032    
1033 root 1.27 dSP;
1034     ENTER; SAVETMPS; PUSHMARK (SP);
1035     EXTEND (SP, 2);
1036     PUSHs (newSVuv (tag));
1037     PUSHs (sv);
1038    
1039     PUTBACK;
1040     int count = call_sv (dec->cbor.filter ? dec->cbor.filter : default_filter, G_ARRAY | G_EVAL);
1041     SPAGAIN;
1042    
1043     if (SvTRUE (ERRSV))
1044     {
1045     FREETMPS; LEAVE;
1046     ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV))));
1047     }
1048    
1049     if (count)
1050     {
1051     SvREFCNT_dec (sv);
1052     sv = SvREFCNT_inc (POPs);
1053     }
1054     else
1055     {
1056     AV *av = newAV ();
1057     av_push (av, newSVuv (tag));
1058     av_push (av, sv);
1059    
1060     HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
1061     ? cbor_tagged_stash
1062     : gv_stashpv ("CBOR::XS::Tagged" , 1);
1063     sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash);
1064     }
1065 root 1.7
1066 root 1.27 PUTBACK;
1067    
1068     FREETMPS; LEAVE;
1069 root 1.18 }
1070 root 1.20 break;
1071 root 1.11 }
1072 root 1.9
1073 root 1.20 return sv;
1074    
1075 root 1.9 fail:
1076     SvREFCNT_dec (sv);
1077     return &PL_sv_undef;
1078 root 1.3 }
1079    
1080     static SV *
1081 root 1.1 decode_sv (dec_t *dec)
1082     {
1083     WANT (1);
1084    
1085 root 1.35 switch (*dec->cur >> MAJOR_SHIFT)
1086 root 1.1 {
1087 root 1.35 case MAJOR_POS_INT >> MAJOR_SHIFT: return newSVuv (decode_uint (dec));
1088     case MAJOR_NEG_INT >> MAJOR_SHIFT: return newSViv (-1 - (IV)decode_uint (dec));
1089     case MAJOR_BYTES >> MAJOR_SHIFT: return decode_str (dec, 0);
1090     case MAJOR_TEXT >> MAJOR_SHIFT: return decode_str (dec, 1);
1091     case MAJOR_ARRAY >> MAJOR_SHIFT: return decode_av (dec);
1092     case MAJOR_MAP >> MAJOR_SHIFT: return decode_hv (dec);
1093     case MAJOR_TAG >> MAJOR_SHIFT: return decode_tagged (dec);
1094    
1095     case MAJOR_MISC >> MAJOR_SHIFT:
1096     switch (*dec->cur++ & MINOR_MASK)
1097 root 1.1 {
1098 root 1.35 case SIMPLE_FALSE:
1099 root 1.1 #if CBOR_SLOW
1100 root 1.10 types_false = get_bool ("Types::Serialiser::false");
1101 root 1.1 #endif
1102 root 1.10 return newSVsv (types_false);
1103 root 1.35 case SIMPLE_TRUE:
1104 root 1.1 #if CBOR_SLOW
1105 root 1.10 types_true = get_bool ("Types::Serialiser::true");
1106 root 1.1 #endif
1107 root 1.10 return newSVsv (types_true);
1108 root 1.35 case SIMPLE_NULL:
1109 root 1.1 return newSVsv (&PL_sv_undef);
1110 root 1.35 case SIMPLE_UNDEF:
1111 root 1.10 #if CBOR_SLOW
1112     types_error = get_bool ("Types::Serialiser::error");
1113     #endif
1114     return newSVsv (types_error);
1115 root 1.1
1116 root 1.35 case MISC_FLOAT16:
1117 root 1.2 {
1118     WANT (2);
1119    
1120     uint16_t fp = (dec->cur[0] << 8) | dec->cur[1];
1121     dec->cur += 2;
1122    
1123     return newSVnv (ecb_binary16_to_float (fp));
1124     }
1125 root 1.1
1126 root 1.35 case MISC_FLOAT32:
1127 root 1.1 {
1128     uint32_t fp;
1129     WANT (4);
1130     memcpy (&fp, dec->cur, 4);
1131     dec->cur += 4;
1132    
1133     if (!ecb_big_endian ())
1134     fp = ecb_bswap32 (fp);
1135    
1136     return newSVnv (ecb_binary32_to_float (fp));
1137     }
1138    
1139 root 1.35 case MISC_FLOAT64:
1140 root 1.1 {
1141     uint64_t fp;
1142     WANT (8);
1143     memcpy (&fp, dec->cur, 8);
1144     dec->cur += 8;
1145    
1146     if (!ecb_big_endian ())
1147     fp = ecb_bswap64 (fp);
1148    
1149     return newSVnv (ecb_binary64_to_double (fp));
1150     }
1151    
1152 root 1.35 // 0..19 unassigned simple
1153 root 1.40 // 24 reserved + unassigned simple (reserved values are not encodable)
1154     // 28-30 unassigned misc
1155     // 31 break code
1156 root 1.1 default:
1157 root 1.40 ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1158 root 1.1 }
1159    
1160     break;
1161     }
1162    
1163     fail:
1164     return &PL_sv_undef;
1165     }
1166    
1167     static SV *
1168     decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1169     {
1170 root 1.48 dec_t dec = { 0 };
1171 root 1.1 SV *sv;
1172 root 1.16 STRLEN len;
1173     char *data = SvPVbyte (string, len);
1174 root 1.1
1175 root 1.16 if (len > cbor->max_size && cbor->max_size)
1176     croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1177     (unsigned long)len, (unsigned long)cbor->max_size);
1178 root 1.1
1179     dec.cbor = *cbor;
1180 root 1.16 dec.cur = (U8 *)data;
1181     dec.end = (U8 *)data + len;
1182 root 1.1
1183     sv = decode_sv (&dec);
1184    
1185     if (offset_return)
1186     *offset_return = dec.cur;
1187    
1188     if (!(offset_return || !sv))
1189 root 1.2 if (dec.cur != dec.end && !dec.err)
1190     dec.err = "garbage after CBOR object";
1191    
1192     if (dec.err)
1193 root 1.1 {
1194 root 1.39 if (dec.shareable)
1195     {
1196     // need to break cyclic links, which whould all be in shareable
1197     int i;
1198     SV **svp;
1199    
1200     for (i = av_len (dec.shareable) + 1; i--; )
1201     if ((svp = av_fetch (dec.shareable, i, 0)))
1202     sv_setsv (*svp, &PL_sv_undef);
1203     }
1204    
1205 root 1.2 SvREFCNT_dec (sv);
1206 root 1.16 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1207 root 1.1 }
1208    
1209     sv = sv_2mortal (sv);
1210    
1211     return sv;
1212     }
1213    
1214     /////////////////////////////////////////////////////////////////////////////
1215 root 1.40 // incremental parser
1216    
1217     #define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1218    
1219     // returns 0 for notyet, 1 for success or error
1220     static int
1221     incr_parse (CBOR *self, SV *cborstr)
1222     {
1223     STRLEN cur;
1224     SvPV (cborstr, cur);
1225    
1226     while (ecb_expect_true (self->incr_need <= cur))
1227     {
1228     // table of integer count bytes
1229     static I8 incr_len[MINOR_MASK + 1] = {
1230     0, 0, 0, 0, 0, 0, 0, 0,
1231     0, 0, 0, 0, 0, 0, 0, 0,
1232     0, 0, 0, 0, 0, 0, 0, 0,
1233     1, 2, 4, 8,-1,-1,-1,-2
1234     };
1235    
1236     const U8 *p = SvPVX (cborstr) + self->incr_pos;
1237     U8 m = *p & MINOR_MASK;
1238     IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1239     I8 ilen = incr_len[m];
1240    
1241     self->incr_need = self->incr_pos + 1;
1242    
1243     if (ecb_expect_false (ilen < 0))
1244     {
1245     if (m != MINOR_INDEF)
1246     return 1; // error
1247    
1248     if (*p == (MAJOR_MISC | MINOR_INDEF))
1249     {
1250     if (count >= 0)
1251     return 1; // error
1252    
1253     count = 1;
1254     }
1255     else
1256     {
1257     av_push (self->incr_count, newSViv (-1)); //TODO: nest
1258     count = -1;
1259     }
1260     }
1261     else
1262     {
1263     self->incr_need += ilen;
1264     if (ecb_expect_false (self->incr_need > cur))
1265     return 0;
1266    
1267     int major = *p >> MAJOR_SHIFT;
1268    
1269     switch (major)
1270     {
1271 root 1.47 case MAJOR_TAG >> MAJOR_SHIFT:
1272     ++count; // tags merely prefix another value
1273     break;
1274    
1275 root 1.40 case MAJOR_BYTES >> MAJOR_SHIFT:
1276     case MAJOR_TEXT >> MAJOR_SHIFT:
1277     case MAJOR_ARRAY >> MAJOR_SHIFT:
1278     case MAJOR_MAP >> MAJOR_SHIFT:
1279     {
1280     UV len;
1281    
1282     if (ecb_expect_false (ilen))
1283     {
1284     len = 0;
1285    
1286     do {
1287     len = (len << 8) | *++p;
1288     } while (--ilen);
1289     }
1290     else
1291     len = m;
1292    
1293     switch (major)
1294     {
1295     case MAJOR_BYTES >> MAJOR_SHIFT:
1296     case MAJOR_TEXT >> MAJOR_SHIFT:
1297     self->incr_need += len;
1298     if (ecb_expect_false (self->incr_need > cur))
1299     return 0;
1300    
1301     break;
1302    
1303     case MAJOR_MAP >> MAJOR_SHIFT:
1304     len <<= 1;
1305     case MAJOR_ARRAY >> MAJOR_SHIFT:
1306     if (len)
1307     {
1308     av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1309     count = len + 1;
1310     }
1311     break;
1312     }
1313     }
1314     }
1315     }
1316    
1317     self->incr_pos = self->incr_need;
1318    
1319     if (count > 0)
1320     {
1321     while (!--count)
1322     {
1323     if (!AvFILLp (self->incr_count))
1324     return 1; // done
1325    
1326     SvREFCNT_dec_NN (av_pop (self->incr_count));
1327     count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1328     }
1329    
1330     SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1331     }
1332     }
1333    
1334     return 0;
1335     }
1336    
1337    
1338     /////////////////////////////////////////////////////////////////////////////
1339 root 1.1 // XS interface functions
1340    
1341     MODULE = CBOR::XS PACKAGE = CBOR::XS
1342    
1343     BOOT:
1344     {
1345     cbor_stash = gv_stashpv ("CBOR::XS" , 1);
1346 root 1.6 cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1);
1347 root 1.1
1348 root 1.10 types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
1349     types_error_stash = gv_stashpv ("Types::Serialiser::Error" , 1);
1350    
1351     types_true = get_bool ("Types::Serialiser::true" );
1352     types_false = get_bool ("Types::Serialiser::false");
1353     types_error = get_bool ("Types::Serialiser::error");
1354 root 1.11
1355 root 1.27 default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1356    
1357 root 1.11 sv_cbor = newSVpv ("CBOR", 0);
1358     SvREADONLY_on (sv_cbor);
1359 root 1.1 }
1360    
1361     PROTOTYPES: DISABLE
1362    
1363     void CLONE (...)
1364     CODE:
1365 root 1.10 cbor_stash = 0;
1366     cbor_tagged_stash = 0;
1367     types_error_stash = 0;
1368     types_boolean_stash = 0;
1369 root 1.1
1370     void new (char *klass)
1371     PPCODE:
1372     {
1373     SV *pv = NEWSV (0, sizeof (CBOR));
1374     SvPOK_only (pv);
1375     cbor_init ((CBOR *)SvPVX (pv));
1376     XPUSHs (sv_2mortal (sv_bless (
1377     newRV_noinc (pv),
1378     strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
1379     )));
1380     }
1381    
1382     void shrink (CBOR *self, int enable = 1)
1383     ALIAS:
1384     shrink = F_SHRINK
1385     allow_unknown = F_ALLOW_UNKNOWN
1386 root 1.18 allow_sharing = F_ALLOW_SHARING
1387 root 1.37 allow_cycles = F_ALLOW_CYCLES
1388 root 1.32 pack_strings = F_PACK_STRINGS
1389 root 1.38 validate_utf8 = F_VALIDATE_UTF8
1390 root 1.1 PPCODE:
1391     {
1392     if (enable)
1393     self->flags |= ix;
1394     else
1395     self->flags &= ~ix;
1396    
1397     XPUSHs (ST (0));
1398     }
1399    
1400     void get_shrink (CBOR *self)
1401     ALIAS:
1402     get_shrink = F_SHRINK
1403     get_allow_unknown = F_ALLOW_UNKNOWN
1404 root 1.18 get_allow_sharing = F_ALLOW_SHARING
1405 root 1.37 get_allow_cycles = F_ALLOW_CYCLES
1406 root 1.32 get_pack_strings = F_PACK_STRINGS
1407 root 1.38 get_validate_utf8 = F_VALIDATE_UTF8
1408 root 1.1 PPCODE:
1409     XPUSHs (boolSV (self->flags & ix));
1410    
1411     void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1412     PPCODE:
1413     self->max_depth = max_depth;
1414     XPUSHs (ST (0));
1415    
1416     U32 get_max_depth (CBOR *self)
1417     CODE:
1418     RETVAL = self->max_depth;
1419     OUTPUT:
1420     RETVAL
1421    
1422     void max_size (CBOR *self, U32 max_size = 0)
1423     PPCODE:
1424     self->max_size = max_size;
1425     XPUSHs (ST (0));
1426    
1427     int get_max_size (CBOR *self)
1428     CODE:
1429     RETVAL = self->max_size;
1430     OUTPUT:
1431     RETVAL
1432    
1433 root 1.27 void filter (CBOR *self, SV *filter = 0)
1434     PPCODE:
1435     SvREFCNT_dec (self->filter);
1436     self->filter = filter ? newSVsv (filter) : filter;
1437     XPUSHs (ST (0));
1438    
1439     SV *get_filter (CBOR *self)
1440     CODE:
1441     RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1442     OUTPUT:
1443     RETVAL
1444    
1445 root 1.1 void encode (CBOR *self, SV *scalar)
1446     PPCODE:
1447     PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
1448     XPUSHs (scalar);
1449    
1450     void decode (CBOR *self, SV *cborstr)
1451     PPCODE:
1452     PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
1453     XPUSHs (cborstr);
1454    
1455     void decode_prefix (CBOR *self, SV *cborstr)
1456     PPCODE:
1457     {
1458     SV *sv;
1459     char *offset;
1460     PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1461     EXTEND (SP, 2);
1462     PUSHs (sv);
1463     PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1464     }
1465    
1466 root 1.41 void incr_parse (CBOR *self, SV *cborstr)
1467 root 1.42 ALIAS:
1468     incr_parse_multiple = 1
1469 root 1.40 PPCODE:
1470     {
1471     if (SvUTF8 (cborstr))
1472     sv_utf8_downgrade (cborstr, 0);
1473    
1474     if (!self->incr_count)
1475     {
1476     self->incr_count = newAV ();
1477     self->incr_pos = 0;
1478     self->incr_need = 1;
1479    
1480     av_push (self->incr_count, newSViv (1));
1481     }
1482    
1483 root 1.41 do
1484 root 1.40 {
1485     if (!incr_parse (self, cborstr))
1486     {
1487     if (self->incr_need > self->max_size && self->max_size)
1488     croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1489     (unsigned long)self->incr_need, (unsigned long)self->max_size);
1490    
1491     break;
1492     }
1493    
1494 root 1.41 SV *sv;
1495     char *offset;
1496 root 1.40
1497 root 1.41 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1498     XPUSHs (sv);
1499 root 1.40
1500 root 1.41 sv_chop (cborstr, offset);
1501 root 1.40
1502 root 1.41 av_clear (self->incr_count);
1503     av_push (self->incr_count, newSViv (1));
1504 root 1.40
1505 root 1.41 self->incr_pos = 0;
1506     self->incr_need = self->incr_pos + 1;
1507 root 1.40 }
1508 root 1.42 while (ix);
1509 root 1.40 }
1510    
1511     void incr_reset (CBOR *self)
1512     CODE:
1513     {
1514     SvREFCNT_dec (self->incr_count);
1515     self->incr_count = 0;
1516     }
1517    
1518 root 1.27 void DESTROY (CBOR *self)
1519     PPCODE:
1520     cbor_free (self);
1521    
1522 root 1.1 PROTOTYPES: ENABLE
1523    
1524     void encode_cbor (SV *scalar)
1525 root 1.36 ALIAS:
1526     encode_cbor = 0
1527     encode_cbor_sharing = F_ALLOW_SHARING
1528 root 1.1 PPCODE:
1529     {
1530     CBOR cbor;
1531     cbor_init (&cbor);
1532 root 1.36 cbor.flags |= ix;
1533 root 1.1 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1534     XPUSHs (scalar);
1535     }
1536    
1537     void decode_cbor (SV *cborstr)
1538     PPCODE:
1539     {
1540     CBOR cbor;
1541     cbor_init (&cbor);
1542     PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
1543     XPUSHs (cborstr);
1544     }
1545