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