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