ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.48
Committed: Sun Sep 20 23:25:53 2015 UTC (8 years, 7 months ago) by root
Branch: MAIN
Changes since 1.47: +2 -2 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.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.48 dec_t dec = { 0 };
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 root 1.47 case MAJOR_TAG >> MAJOR_SHIFT:
1270     ++count; // tags merely prefix another value
1271     break;
1272    
1273 root 1.40 case MAJOR_BYTES >> MAJOR_SHIFT:
1274     case MAJOR_TEXT >> MAJOR_SHIFT:
1275     case MAJOR_ARRAY >> MAJOR_SHIFT:
1276     case MAJOR_MAP >> MAJOR_SHIFT:
1277     {
1278     UV len;
1279    
1280     if (ecb_expect_false (ilen))
1281     {
1282     len = 0;
1283    
1284     do {
1285     len = (len << 8) | *++p;
1286     } while (--ilen);
1287     }
1288     else
1289     len = m;
1290    
1291     switch (major)
1292     {
1293     case MAJOR_BYTES >> MAJOR_SHIFT:
1294     case MAJOR_TEXT >> MAJOR_SHIFT:
1295     self->incr_need += len;
1296     if (ecb_expect_false (self->incr_need > cur))
1297     return 0;
1298    
1299     break;
1300    
1301     case MAJOR_MAP >> MAJOR_SHIFT:
1302     len <<= 1;
1303     case MAJOR_ARRAY >> MAJOR_SHIFT:
1304     if (len)
1305     {
1306     av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1307     count = len + 1;
1308     }
1309     break;
1310     }
1311     }
1312     }
1313     }
1314    
1315     self->incr_pos = self->incr_need;
1316    
1317     if (count > 0)
1318     {
1319     while (!--count)
1320     {
1321     if (!AvFILLp (self->incr_count))
1322     return 1; // done
1323    
1324     SvREFCNT_dec_NN (av_pop (self->incr_count));
1325     count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1326     }
1327    
1328     SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1329     }
1330     }
1331    
1332     return 0;
1333     }
1334    
1335    
1336     /////////////////////////////////////////////////////////////////////////////
1337 root 1.1 // XS interface functions
1338    
1339     MODULE = CBOR::XS PACKAGE = CBOR::XS
1340    
1341     BOOT:
1342     {
1343     cbor_stash = gv_stashpv ("CBOR::XS" , 1);
1344 root 1.6 cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1);
1345 root 1.1
1346 root 1.10 types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
1347     types_error_stash = gv_stashpv ("Types::Serialiser::Error" , 1);
1348    
1349     types_true = get_bool ("Types::Serialiser::true" );
1350     types_false = get_bool ("Types::Serialiser::false");
1351     types_error = get_bool ("Types::Serialiser::error");
1352 root 1.11
1353 root 1.27 default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1354    
1355 root 1.11 sv_cbor = newSVpv ("CBOR", 0);
1356     SvREADONLY_on (sv_cbor);
1357 root 1.1 }
1358    
1359     PROTOTYPES: DISABLE
1360    
1361     void CLONE (...)
1362     CODE:
1363 root 1.10 cbor_stash = 0;
1364     cbor_tagged_stash = 0;
1365     types_error_stash = 0;
1366     types_boolean_stash = 0;
1367 root 1.1
1368     void new (char *klass)
1369     PPCODE:
1370     {
1371     SV *pv = NEWSV (0, sizeof (CBOR));
1372     SvPOK_only (pv);
1373     cbor_init ((CBOR *)SvPVX (pv));
1374     XPUSHs (sv_2mortal (sv_bless (
1375     newRV_noinc (pv),
1376     strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
1377     )));
1378     }
1379    
1380     void shrink (CBOR *self, int enable = 1)
1381     ALIAS:
1382     shrink = F_SHRINK
1383     allow_unknown = F_ALLOW_UNKNOWN
1384 root 1.18 allow_sharing = F_ALLOW_SHARING
1385 root 1.37 allow_cycles = F_ALLOW_CYCLES
1386 root 1.32 pack_strings = F_PACK_STRINGS
1387 root 1.38 validate_utf8 = F_VALIDATE_UTF8
1388 root 1.1 PPCODE:
1389     {
1390     if (enable)
1391     self->flags |= ix;
1392     else
1393     self->flags &= ~ix;
1394    
1395     XPUSHs (ST (0));
1396     }
1397    
1398     void get_shrink (CBOR *self)
1399     ALIAS:
1400     get_shrink = F_SHRINK
1401     get_allow_unknown = F_ALLOW_UNKNOWN
1402 root 1.18 get_allow_sharing = F_ALLOW_SHARING
1403 root 1.37 get_allow_cycles = F_ALLOW_CYCLES
1404 root 1.32 get_pack_strings = F_PACK_STRINGS
1405 root 1.38 get_validate_utf8 = F_VALIDATE_UTF8
1406 root 1.1 PPCODE:
1407     XPUSHs (boolSV (self->flags & ix));
1408    
1409     void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1410     PPCODE:
1411     self->max_depth = max_depth;
1412     XPUSHs (ST (0));
1413    
1414     U32 get_max_depth (CBOR *self)
1415     CODE:
1416     RETVAL = self->max_depth;
1417     OUTPUT:
1418     RETVAL
1419    
1420     void max_size (CBOR *self, U32 max_size = 0)
1421     PPCODE:
1422     self->max_size = max_size;
1423     XPUSHs (ST (0));
1424    
1425     int get_max_size (CBOR *self)
1426     CODE:
1427     RETVAL = self->max_size;
1428     OUTPUT:
1429     RETVAL
1430    
1431 root 1.27 void filter (CBOR *self, SV *filter = 0)
1432     PPCODE:
1433     SvREFCNT_dec (self->filter);
1434     self->filter = filter ? newSVsv (filter) : filter;
1435     XPUSHs (ST (0));
1436    
1437     SV *get_filter (CBOR *self)
1438     CODE:
1439     RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1440     OUTPUT:
1441     RETVAL
1442    
1443 root 1.1 void encode (CBOR *self, SV *scalar)
1444     PPCODE:
1445     PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
1446     XPUSHs (scalar);
1447    
1448     void decode (CBOR *self, SV *cborstr)
1449     PPCODE:
1450     PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
1451     XPUSHs (cborstr);
1452    
1453     void decode_prefix (CBOR *self, SV *cborstr)
1454     PPCODE:
1455     {
1456     SV *sv;
1457     char *offset;
1458     PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1459     EXTEND (SP, 2);
1460     PUSHs (sv);
1461     PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1462     }
1463    
1464 root 1.41 void incr_parse (CBOR *self, SV *cborstr)
1465 root 1.42 ALIAS:
1466     incr_parse_multiple = 1
1467 root 1.40 PPCODE:
1468     {
1469     if (SvUTF8 (cborstr))
1470     sv_utf8_downgrade (cborstr, 0);
1471    
1472     if (!self->incr_count)
1473     {
1474     self->incr_count = newAV ();
1475     self->incr_pos = 0;
1476     self->incr_need = 1;
1477    
1478     av_push (self->incr_count, newSViv (1));
1479     }
1480    
1481 root 1.41 do
1482 root 1.40 {
1483     if (!incr_parse (self, cborstr))
1484     {
1485     if (self->incr_need > self->max_size && self->max_size)
1486     croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1487     (unsigned long)self->incr_need, (unsigned long)self->max_size);
1488    
1489     break;
1490     }
1491    
1492 root 1.41 SV *sv;
1493     char *offset;
1494 root 1.40
1495 root 1.41 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1496     XPUSHs (sv);
1497 root 1.40
1498 root 1.41 sv_chop (cborstr, offset);
1499 root 1.40
1500 root 1.41 av_clear (self->incr_count);
1501     av_push (self->incr_count, newSViv (1));
1502 root 1.40
1503 root 1.41 self->incr_pos = 0;
1504     self->incr_need = self->incr_pos + 1;
1505 root 1.40 }
1506 root 1.42 while (ix);
1507 root 1.40 }
1508    
1509     void incr_reset (CBOR *self)
1510     CODE:
1511     {
1512     SvREFCNT_dec (self->incr_count);
1513     self->incr_count = 0;
1514     }
1515    
1516 root 1.27 void DESTROY (CBOR *self)
1517     PPCODE:
1518     cbor_free (self);
1519    
1520 root 1.1 PROTOTYPES: ENABLE
1521    
1522     void encode_cbor (SV *scalar)
1523 root 1.36 ALIAS:
1524     encode_cbor = 0
1525     encode_cbor_sharing = F_ALLOW_SHARING
1526 root 1.1 PPCODE:
1527     {
1528     CBOR cbor;
1529     cbor_init (&cbor);
1530 root 1.36 cbor.flags |= ix;
1531 root 1.1 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1532     XPUSHs (scalar);
1533     }
1534    
1535     void decode_cbor (SV *cborstr)
1536     PPCODE:
1537     {
1538     CBOR cbor;
1539     cbor_init (&cbor);
1540     PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
1541     XPUSHs (cborstr);
1542     }
1543