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