ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
Revision: 1.50
Committed: Thu Feb 25 02:29:22 2016 UTC (8 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-1_41
Changes since 1.49: +10 -4 lines
Log Message:
*** empty log message ***

File Contents

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