ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.51
Committed: Sun Apr 24 13:15:19 2016 UTC (8 years ago) by root
Branch: MAIN
Changes since 1.50: +16 -1 lines
Log Message:
*** empty log message ***

File Contents

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