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