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