ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.47
Committed: Mon Apr 27 20:21:53 2015 UTC (9 years ago) by root
Branch: MAIN
CVS Tags: rel-1_3
Changes since 1.46: +4 -0 lines
Log Message:
1.3

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