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