ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.6
Committed: Sat Oct 26 22:25:47 2013 UTC (10 years, 6 months ago) by root
Branch: MAIN
Changes since 1.5: +49 -262 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 #define F_SHRINK 0x00000200UL
15 #define F_ALLOW_UNKNOWN 0x00002000UL
16
17 #define INIT_SIZE 32 // initial scalar size to be allocated
18
19 #define SB do {
20 #define SE } while (0)
21
22 #define IN_RANGE_INC(type,val,beg,end) \
23 ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \
24 <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg)))
25
26 #define ERR_NESTING_EXCEEDED "cbor text or perl structure exceeds maximum nesting level (max_depth set too low?)"
27
28 #ifdef USE_ITHREADS
29 # define CBOR_SLOW 1
30 # define CBOR_STASH (cbor_stash ? cbor_stash : gv_stashpv ("CBOR::XS", 1))
31 #else
32 # define CBOR_SLOW 0
33 # define CBOR_STASH cbor_stash
34 #endif
35
36 static HV *cbor_stash, *cbor_boolean_stash, *cbor_tagged_stash; // CBOR::XS::
37 static SV *cbor_true, *cbor_false;
38
39 typedef struct {
40 U32 flags;
41 U32 max_depth;
42 STRLEN max_size;
43 } CBOR;
44
45 ecb_inline void
46 cbor_init (CBOR *cbor)
47 {
48 Zero (cbor, 1, CBOR);
49 cbor->max_depth = 512;
50 }
51
52 /////////////////////////////////////////////////////////////////////////////
53 // utility functions
54
55 ecb_inline SV *
56 get_bool (const char *name)
57 {
58 SV *sv = get_sv (name, 1);
59
60 SvREADONLY_on (sv);
61 SvREADONLY_on (SvRV (sv));
62
63 return sv;
64 }
65
66 ecb_inline void
67 shrink (SV *sv)
68 {
69 sv_utf8_downgrade (sv, 1);
70
71 if (SvLEN (sv) > SvCUR (sv) + 1)
72 {
73 #ifdef SvPV_shrink_to_cur
74 SvPV_shrink_to_cur (sv);
75 #elif defined (SvPV_renew)
76 SvPV_renew (sv, SvCUR (sv) + 1);
77 #endif
78 }
79 }
80
81 /////////////////////////////////////////////////////////////////////////////
82 // fp hell
83
84 //TODO
85
86 /////////////////////////////////////////////////////////////////////////////
87 // encoder
88
89 // structure used for encoding CBOR
90 typedef struct
91 {
92 char *cur; // SvPVX (sv) + current output position
93 char *end; // SvEND (sv)
94 SV *sv; // result scalar
95 CBOR cbor;
96 U32 depth; // recursion level
97 } enc_t;
98
99 ecb_inline void
100 need (enc_t *enc, STRLEN len)
101 {
102 if (ecb_expect_false (enc->cur + len >= enc->end))
103 {
104 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
105 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
106 enc->cur = SvPVX (enc->sv) + cur;
107 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1;
108 }
109 }
110
111 ecb_inline void
112 encode_ch (enc_t *enc, char ch)
113 {
114 need (enc, 1);
115 *enc->cur++ = ch;
116 }
117
118 static void
119 encode_uint (enc_t *enc, int major, UV len)
120 {
121 need (enc, 9);
122
123 if (len < 24)
124 *enc->cur++ = major | len;
125 else if (len <= 0xff)
126 {
127 *enc->cur++ = major | 24;
128 *enc->cur++ = len;
129 }
130 else if (len <= 0xffff)
131 {
132 *enc->cur++ = major | 25;
133 *enc->cur++ = len >> 8;
134 *enc->cur++ = len;
135 }
136 else if (len <= 0xffffffff)
137 {
138 *enc->cur++ = major | 26;
139 *enc->cur++ = len >> 24;
140 *enc->cur++ = len >> 16;
141 *enc->cur++ = len >> 8;
142 *enc->cur++ = len;
143 }
144 else
145 {
146 *enc->cur++ = major | 27;
147 *enc->cur++ = len >> 56;
148 *enc->cur++ = len >> 48;
149 *enc->cur++ = len >> 40;
150 *enc->cur++ = len >> 32;
151 *enc->cur++ = len >> 24;
152 *enc->cur++ = len >> 16;
153 *enc->cur++ = len >> 8;
154 *enc->cur++ = len;
155 }
156 }
157
158 static void
159 encode_str (enc_t *enc, int utf8, char *str, STRLEN len)
160 {
161 encode_uint (enc, utf8 ? 0x60 : 0x40, len);
162 need (enc, len);
163 memcpy (enc->cur, str, len);
164 enc->cur += len;
165 }
166
167 static void encode_sv (enc_t *enc, SV *sv);
168
169 static void
170 encode_av (enc_t *enc, AV *av)
171 {
172 int i, len = av_len (av);
173
174 if (enc->depth >= enc->cbor.max_depth)
175 croak (ERR_NESTING_EXCEEDED);
176
177 ++enc->depth;
178
179 encode_uint (enc, 0x80, len + 1);
180
181 for (i = 0; i <= len; ++i)
182 {
183 SV **svp = av_fetch (av, i, 0);
184 encode_sv (enc, svp ? *svp : &PL_sv_undef);
185 }
186
187 --enc->depth;
188 }
189
190 static void
191 encode_hv (enc_t *enc, HV *hv)
192 {
193 HE *he;
194
195 if (enc->depth >= enc->cbor.max_depth)
196 croak (ERR_NESTING_EXCEEDED);
197
198 ++enc->depth;
199
200 int pairs = hv_iterinit (hv);
201 int mg = SvMAGICAL (hv);
202
203 if (mg)
204 encode_ch (enc, 0xa0 | 31);
205 else
206 encode_uint (enc, 0xa0, pairs);
207
208 while ((he = hv_iternext (hv)))
209 {
210 if (HeKLEN (he) == HEf_SVKEY)
211 encode_sv (enc, HeSVKEY (he));
212 else
213 encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he));
214
215 encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he));
216 }
217
218 if (mg)
219 encode_ch (enc, 0xe0 | 31);
220
221 --enc->depth;
222 }
223
224 // encode objects, arrays and special \0=false and \1=true values.
225 static void
226 encode_rv (enc_t *enc, SV *sv)
227 {
228 svtype svt;
229
230 SvGETMAGIC (sv);
231 svt = SvTYPE (sv);
232
233 if (ecb_expect_false (SvOBJECT (sv)))
234 {
235 HV *boolean_stash = !CBOR_SLOW || cbor_boolean_stash
236 ? cbor_boolean_stash
237 : gv_stashpv ("CBOR::XS::Boolean", 1);
238 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
239 ? cbor_tagged_stash
240 : gv_stashpv ("CBOR::XS::Tagged" , 1);
241
242 if (SvSTASH (sv) == boolean_stash)
243 encode_ch (enc, SvIV (sv) ? 0xe0 | 21 : 0xe0 | 20);
244 else if (SvSTASH (sv) == tagged_stash)
245 {
246 if (svt != SVt_PVAV)
247 croak ("encountered CBOR::XS::Tagged object that isn't an array");
248
249 encode_uint (enc, 0xc0, SvUV (*av_fetch ((AV *)sv, 0, 1)));
250 encode_sv (enc, *av_fetch ((AV *)sv, 1, 1));
251 }
252 else
253 {
254 // we re-bless the reference to get overload and other niceties right
255 GV *to_cbor = gv_fetchmethod_autoload (SvSTASH (sv), "TO_CBOR", 0);
256
257 if (to_cbor)
258 {
259 dSP;
260
261 ENTER; SAVETMPS; PUSHMARK (SP);
262 XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), SvSTASH (sv)));
263
264 // calling with G_SCALAR ensures that we always get a 1 return value
265 PUTBACK;
266 call_sv ((SV *)GvCV (to_cbor), G_SCALAR);
267 SPAGAIN;
268
269 // catch this surprisingly common error
270 if (SvROK (TOPs) && SvRV (TOPs) == sv)
271 croak ("%s::TO_CBOR method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv)));
272
273 sv = POPs;
274 PUTBACK;
275
276 encode_sv (enc, sv);
277
278 FREETMPS; LEAVE;
279 }
280 else
281 croak ("encountered object '%s', but no TO_CBOR method available on it",
282 SvPV_nolen (sv_2mortal (newRV_inc (sv))));
283 }
284 }
285 else if (svt == SVt_PVHV)
286 encode_hv (enc, (HV *)sv);
287 else if (svt == SVt_PVAV)
288 encode_av (enc, (AV *)sv);
289 else if (svt < SVt_PVAV)
290 {
291 STRLEN len = 0;
292 char *pv = svt ? SvPV (sv, len) : 0;
293
294 if (len == 1 && *pv == '1')
295 encode_ch (enc, 0xe0 | 21);
296 else if (len == 1 && *pv == '0')
297 encode_ch (enc, 0xe0 | 20);
298 else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
299 encode_ch (enc, 0xe0 | 23);
300 else
301 croak ("cannot encode reference to scalar '%s' unless the scalar is 0 or 1",
302 SvPV_nolen (sv_2mortal (newRV_inc (sv))));
303 }
304 else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
305 encode_ch (enc, 0xe0 | 23);
306 else
307 croak ("encountered %s, but CBOR can only represent references to arrays or hashes",
308 SvPV_nolen (sv_2mortal (newRV_inc (sv))));
309 }
310
311 static void
312 encode_nv (enc_t *enc, SV *sv)
313 {
314 double nv = SvNVX (sv);
315
316 need (enc, 9);
317
318 if (ecb_expect_false (nv == (U32)nv))
319 encode_uint (enc, 0x00, (U32)nv);
320 //TODO: maybe I32?
321 else if (ecb_expect_false (nv == (float)nv))
322 {
323 uint32_t fp = ecb_float_to_binary32 (nv);
324
325 *enc->cur++ = 0xe0 | 26;
326
327 if (!ecb_big_endian ())
328 fp = ecb_bswap32 (fp);
329
330 memcpy (enc->cur, &fp, 4);
331 enc->cur += 4;
332 }
333 else
334 {
335 uint64_t fp = ecb_double_to_binary64 (nv);
336
337 *enc->cur++ = 0xe0 | 27;
338
339 if (!ecb_big_endian ())
340 fp = ecb_bswap64 (fp);
341
342 memcpy (enc->cur, &fp, 8);
343 enc->cur += 8;
344 }
345 }
346
347 static void
348 encode_sv (enc_t *enc, SV *sv)
349 {
350 SvGETMAGIC (sv);
351
352 if (SvPOKp (sv))
353 {
354 STRLEN len;
355 char *str = SvPV (sv, len);
356 encode_str (enc, SvUTF8 (sv), str, len);
357 }
358 else if (SvNOKp (sv))
359 encode_nv (enc, sv);
360 else if (SvIOKp (sv))
361 {
362 if (SvIsUV (sv))
363 encode_uint (enc, 0x00, SvUVX (sv));
364 else if (SvIVX (sv) >= 0)
365 encode_uint (enc, 0x00, SvIVX (sv));
366 else
367 encode_uint (enc, 0x20, -(SvIVX (sv) + 1));
368 }
369 else if (SvROK (sv))
370 encode_rv (enc, SvRV (sv));
371 else if (!SvOK (sv))
372 encode_ch (enc, 0xe0 | 22);
373 else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
374 encode_ch (enc, 0xe0 | 23);
375 else
376 croak ("encountered perl type (%s,0x%x) that CBOR cannot handle, check your input data",
377 SvPV_nolen (sv), (unsigned int)SvFLAGS (sv));
378 }
379
380 static SV *
381 encode_cbor (SV *scalar, CBOR *cbor)
382 {
383 enc_t enc;
384
385 enc.cbor = *cbor;
386 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
387 enc.cur = SvPVX (enc.sv);
388 enc.end = SvEND (enc.sv);
389 enc.depth = 0;
390
391 SvPOK_only (enc.sv);
392 encode_sv (&enc, scalar);
393
394 SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
395 *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings
396
397 if (enc.cbor.flags & F_SHRINK)
398 shrink (enc.sv);
399
400 return enc.sv;
401 }
402
403 /////////////////////////////////////////////////////////////////////////////
404 // decoder
405
406 // structure used for decoding CBOR
407 typedef struct
408 {
409 U8 *cur; // current parser pointer
410 U8 *end; // end of input string
411 const char *err; // parse error, if != 0
412 CBOR cbor;
413 U32 depth; // recursion depth
414 U32 maxdepth; // recursion depth limit
415 } dec_t;
416
417 #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
418
419 #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
420
421 #define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED)
422 #define DEC_DEC_DEPTH --dec->depth
423
424 static UV
425 decode_uint (dec_t *dec)
426 {
427 switch (*dec->cur & 31)
428 {
429 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
430 case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
431 case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
432 return *dec->cur++ & 31;
433
434 case 24:
435 WANT (2);
436 dec->cur += 2;
437 return dec->cur[-1];
438
439 case 25:
440 WANT (3);
441 dec->cur += 3;
442 return (((UV)dec->cur[-2]) << 8)
443 | ((UV)dec->cur[-1]);
444
445 case 26:
446 WANT (5);
447 dec->cur += 5;
448 return (((UV)dec->cur[-4]) << 24)
449 | (((UV)dec->cur[-3]) << 16)
450 | (((UV)dec->cur[-2]) << 8)
451 | ((UV)dec->cur[-1]);
452
453 case 27:
454 WANT (9);
455 dec->cur += 9;
456 return (((UV)dec->cur[-8]) << 56)
457 | (((UV)dec->cur[-7]) << 48)
458 | (((UV)dec->cur[-6]) << 40)
459 | (((UV)dec->cur[-5]) << 32)
460 | (((UV)dec->cur[-4]) << 24)
461 | (((UV)dec->cur[-3]) << 16)
462 | (((UV)dec->cur[-2]) << 8)
463 | ((UV)dec->cur[-1]);
464
465 default:
466 ERR ("corrupted CBOR data (unsupported integer minor encoding)");
467 }
468
469 fail:
470 return 0;
471 }
472
473 static SV *decode_sv (dec_t *dec);
474
475 static SV *
476 decode_av (dec_t *dec)
477 {
478 AV *av = newAV ();
479
480 DEC_INC_DEPTH;
481
482 if ((*dec->cur & 31) == 31)
483 {
484 ++dec->cur;
485
486 for (;;)
487 {
488 WANT (1);
489
490 if (*dec->cur == (0xe0 | 31))
491 {
492 ++dec->cur;
493 break;
494 }
495
496 av_push (av, decode_sv (dec));
497 }
498 }
499 else
500 {
501 int i, len = decode_uint (dec);
502
503 av_fill (av, len - 1);
504
505 for (i = 0; i < len; ++i)
506 AvARRAY (av)[i] = decode_sv (dec);
507 }
508
509 DEC_DEC_DEPTH;
510 return newRV_noinc ((SV *)av);
511
512 fail:
513 SvREFCNT_dec (av);
514 DEC_DEC_DEPTH;
515 return &PL_sv_undef;
516 }
517
518 static SV *
519 decode_hv (dec_t *dec)
520 {
521 HV *hv = newHV ();
522
523 DEC_INC_DEPTH;
524
525 if ((*dec->cur & 31) == 31)
526 {
527 ++dec->cur;
528
529 for (;;)
530 {
531 WANT (1);
532
533 if (*dec->cur == (0xe0 | 31))
534 {
535 ++dec->cur;
536 break;
537 }
538
539 SV *k = decode_sv (dec);
540 SV *v = decode_sv (dec);
541
542 hv_store_ent (hv, k, v, 0);
543 }
544 }
545 else
546 {
547 int len = decode_uint (dec);
548
549 while (len--)
550 {
551 SV *k = decode_sv (dec);
552 SV *v = decode_sv (dec);
553
554 hv_store_ent (hv, k, v, 0);
555 }
556 }
557
558 DEC_DEC_DEPTH;
559 return newRV_noinc ((SV *)hv);
560
561 fail:
562 SvREFCNT_dec (hv);
563 DEC_DEC_DEPTH;
564 return &PL_sv_undef;
565 }
566
567 static SV *
568 decode_str (dec_t *dec, int utf8)
569 {
570 SV *sv = 0;
571
572 if ((*dec->cur & 31) == 31)
573 {
574 ++dec->cur;
575
576 sv = newSVpvn ("", 0);
577
578 // not very fast, and certainly not robust against illegal input
579 for (;;)
580 {
581 WANT (1);
582
583 if (*dec->cur == (0xe0 | 31))
584 {
585 ++dec->cur;
586 break;
587 }
588
589 sv_catsv (sv, decode_sv (dec));
590 }
591 }
592 else
593 {
594 STRLEN len = decode_uint (dec);
595
596 WANT (len);
597 sv = newSVpvn (dec->cur, len);
598 dec->cur += len;
599 }
600
601 if (utf8)
602 SvUTF8_on (sv);
603
604 return sv;
605
606 fail:
607 SvREFCNT_dec (sv);
608 return &PL_sv_undef;
609 }
610
611 static SV *
612 decode_tagged (dec_t *dec)
613 {
614 UV tag = decode_uint (dec);
615 SV *sv = decode_sv (dec);
616
617 if (tag == 55799) // 2.4.5 Self-Describe CBOR
618 return sv;
619
620 AV *av = newAV ();
621 av_push (av, newSVuv (tag));
622 av_push (av, sv);
623 return newRV_noinc ((SV *)av);
624 }
625
626 static SV *
627 decode_sv (dec_t *dec)
628 {
629 WANT (1);
630
631 switch (*dec->cur >> 5)
632 {
633 case 0: // unsigned int
634 return newSVuv (decode_uint (dec));
635 case 1: // negative int
636 return newSViv (-1 - (IV)decode_uint (dec));
637 case 2: // octet string
638 return decode_str (dec, 0);
639 case 3: // utf-8 string
640 return decode_str (dec, 1);
641 case 4: // array
642 return decode_av (dec);
643 case 5: // map
644 return decode_hv (dec);
645 case 6: // tag
646 return decode_tagged (dec);
647 case 7: // misc
648 switch (*dec->cur++ & 31)
649 {
650 case 20:
651 #if CBOR_SLOW
652 cbor_false = get_bool ("CBOR::XS::false");
653 #endif
654 return newSVsv (cbor_false);
655 case 21:
656 #if CBOR_SLOW
657 cbor_true = get_bool ("CBOR::XS::true");
658 #endif
659 return newSVsv (cbor_true);
660 case 22:
661 return newSVsv (&PL_sv_undef);
662
663 case 25:
664 {
665 WANT (2);
666
667 uint16_t fp = (dec->cur[0] << 8) | dec->cur[1];
668 dec->cur += 2;
669
670 return newSVnv (ecb_binary16_to_float (fp));
671 }
672
673 case 26:
674 {
675 uint32_t fp;
676 WANT (4);
677 memcpy (&fp, dec->cur, 4);
678 dec->cur += 4;
679
680 if (!ecb_big_endian ())
681 fp = ecb_bswap32 (fp);
682
683 return newSVnv (ecb_binary32_to_float (fp));
684 }
685
686 case 27:
687 {
688 uint64_t fp;
689 WANT (8);
690 memcpy (&fp, dec->cur, 8);
691 dec->cur += 8;
692
693 if (!ecb_big_endian ())
694 fp = ecb_bswap64 (fp);
695
696 return newSVnv (ecb_binary64_to_double (fp));
697 }
698
699 // 0..19 unassigned
700 // 24 reserved + unassigned (reserved values are not encodable)
701 default:
702 ERR ("corrupted CBOR data (reserved/unassigned major 7 value)");
703 }
704
705 break;
706 }
707
708 fail:
709 return &PL_sv_undef;
710 }
711
712 static SV *
713 decode_cbor (SV *string, CBOR *cbor, char **offset_return)
714 {
715 dec_t dec;
716 SV *sv;
717
718 /* work around bugs in 5.10 where manipulating magic values
719 * makes perl ignore the magic in subsequent accesses.
720 * also make a copy of non-PV values, to get them into a clean
721 * state (SvPV should do that, but it's buggy, see below).
722 */
723 /*SvGETMAGIC (string);*/
724 if (SvMAGICAL (string) || !SvPOK (string))
725 string = sv_2mortal (newSVsv (string));
726
727 SvUPGRADE (string, SVt_PV);
728
729 /* work around a bug in perl 5.10, which causes SvCUR to fail an
730 * assertion with -DDEBUGGING, although SvCUR is documented to
731 * return the xpv_cur field which certainly exists after upgrading.
732 * according to nicholas clark, calling SvPOK fixes this.
733 * But it doesn't fix it, so try another workaround, call SvPV_nolen
734 * and hope for the best.
735 * Damnit, SvPV_nolen still trips over yet another assertion. This
736 * assertion business is seriously broken, try yet another workaround
737 * for the broken -DDEBUGGING.
738 */
739 {
740 #ifdef DEBUGGING
741 STRLEN offset = SvOK (string) ? sv_len (string) : 0;
742 #else
743 STRLEN offset = SvCUR (string);
744 #endif
745
746 if (offset > cbor->max_size && cbor->max_size)
747 croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
748 (unsigned long)SvCUR (string), (unsigned long)cbor->max_size);
749 }
750
751 sv_utf8_downgrade (string, 0);
752
753 dec.cbor = *cbor;
754 dec.cur = (U8 *)SvPVX (string);
755 dec.end = (U8 *)SvEND (string);
756 dec.err = 0;
757 dec.depth = 0;
758
759 sv = decode_sv (&dec);
760
761 if (offset_return)
762 *offset_return = dec.cur;
763
764 if (!(offset_return || !sv))
765 if (dec.cur != dec.end && !dec.err)
766 dec.err = "garbage after CBOR object";
767
768 if (dec.err)
769 {
770 SvREFCNT_dec (sv);
771 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur);
772 }
773
774 sv = sv_2mortal (sv);
775
776 return sv;
777 }
778
779 /////////////////////////////////////////////////////////////////////////////
780 // XS interface functions
781
782 MODULE = CBOR::XS PACKAGE = CBOR::XS
783
784 BOOT:
785 {
786 cbor_stash = gv_stashpv ("CBOR::XS" , 1);
787 cbor_boolean_stash = gv_stashpv ("CBOR::XS::Boolean", 1);
788 cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1);
789
790 cbor_true = get_bool ("CBOR::XS::true");
791 cbor_false = get_bool ("CBOR::XS::false");
792 }
793
794 PROTOTYPES: DISABLE
795
796 void CLONE (...)
797 CODE:
798 cbor_stash = 0;
799 cbor_boolean_stash = 0;
800 cbor_tagged_stash = 0;
801
802 void new (char *klass)
803 PPCODE:
804 {
805 SV *pv = NEWSV (0, sizeof (CBOR));
806 SvPOK_only (pv);
807 cbor_init ((CBOR *)SvPVX (pv));
808 XPUSHs (sv_2mortal (sv_bless (
809 newRV_noinc (pv),
810 strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
811 )));
812 }
813
814 void shrink (CBOR *self, int enable = 1)
815 ALIAS:
816 shrink = F_SHRINK
817 allow_unknown = F_ALLOW_UNKNOWN
818 PPCODE:
819 {
820 if (enable)
821 self->flags |= ix;
822 else
823 self->flags &= ~ix;
824
825 XPUSHs (ST (0));
826 }
827
828 void get_shrink (CBOR *self)
829 ALIAS:
830 get_shrink = F_SHRINK
831 get_allow_unknown = F_ALLOW_UNKNOWN
832 PPCODE:
833 XPUSHs (boolSV (self->flags & ix));
834
835 void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
836 PPCODE:
837 self->max_depth = max_depth;
838 XPUSHs (ST (0));
839
840 U32 get_max_depth (CBOR *self)
841 CODE:
842 RETVAL = self->max_depth;
843 OUTPUT:
844 RETVAL
845
846 void max_size (CBOR *self, U32 max_size = 0)
847 PPCODE:
848 self->max_size = max_size;
849 XPUSHs (ST (0));
850
851 int get_max_size (CBOR *self)
852 CODE:
853 RETVAL = self->max_size;
854 OUTPUT:
855 RETVAL
856
857 #if 0 //TODO
858
859 void filter_cbor_object (CBOR *self, SV *cb = &PL_sv_undef)
860 PPCODE:
861 {
862 SvREFCNT_dec (self->cb_object);
863 self->cb_object = SvOK (cb) ? newSVsv (cb) : 0;
864
865 XPUSHs (ST (0));
866 }
867
868 void filter_cbor_single_key_object (CBOR *self, SV *key, SV *cb = &PL_sv_undef)
869 PPCODE:
870 {
871 if (!self->cb_sk_object)
872 self->cb_sk_object = newHV ();
873
874 if (SvOK (cb))
875 hv_store_ent (self->cb_sk_object, key, newSVsv (cb), 0);
876 else
877 {
878 hv_delete_ent (self->cb_sk_object, key, G_DISCARD, 0);
879
880 if (!HvKEYS (self->cb_sk_object))
881 {
882 SvREFCNT_dec (self->cb_sk_object);
883 self->cb_sk_object = 0;
884 }
885 }
886
887 XPUSHs (ST (0));
888 }
889
890 #endif
891
892 void encode (CBOR *self, SV *scalar)
893 PPCODE:
894 PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
895 XPUSHs (scalar);
896
897 void decode (CBOR *self, SV *cborstr)
898 PPCODE:
899 PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
900 XPUSHs (cborstr);
901
902 void decode_prefix (CBOR *self, SV *cborstr)
903 PPCODE:
904 {
905 SV *sv;
906 char *offset;
907 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
908 EXTEND (SP, 2);
909 PUSHs (sv);
910 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
911 }
912
913 #if 0
914
915 void DESTROY (CBOR *self)
916 CODE:
917 SvREFCNT_dec (self->cb_sk_object);
918 SvREFCNT_dec (self->cb_object);
919
920 #endif
921
922 PROTOTYPES: ENABLE
923
924 void encode_cbor (SV *scalar)
925 PPCODE:
926 {
927 CBOR cbor;
928 cbor_init (&cbor);
929 PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
930 XPUSHs (scalar);
931 }
932
933 void decode_cbor (SV *cborstr)
934 PPCODE:
935 {
936 CBOR cbor;
937 cbor_init (&cbor);
938 PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
939 XPUSHs (cborstr);
940 }
941