ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
(Generate patch)

Comparing CBOR-XS/XS.xs (file contents):
Revision 1.1 by root, Fri Oct 25 23:09:45 2013 UTC vs.
Revision 1.5 by root, Sat Oct 26 21:14:20 2013 UTC

9#include <limits.h> 9#include <limits.h>
10#include <float.h> 10#include <float.h>
11 11
12#include "ecb.h" 12#include "ecb.h"
13 13
14#if defined(__BORLANDC__) || defined(_MSC_VER)
15# define snprintf _snprintf // C compilers have this in stdio.h
16#endif
17
18#define F_SHRINK 0x00000200UL 14#define F_SHRINK 0x00000200UL
19#define F_ALLOW_UNKNOWN 0x00002000UL 15#define F_ALLOW_UNKNOWN 0x00002000UL
20 16
21#define INIT_SIZE 32 // initial scalar size to be allocated 17#define INIT_SIZE 32 // initial scalar size to be allocated
22 18
23#define SB do { 19#define SB do {
24#define SE } while (0) 20#define SE } while (0)
25
26#if __GNUC__ >= 3
27# define expect(expr,value) __builtin_expect ((expr), (value))
28# define INLINE static inline
29#else
30# define expect(expr,value) (expr)
31# define INLINE static
32#endif
33
34#define expect_false(expr) expect ((expr) != 0, 0)
35#define expect_true(expr) expect ((expr) != 0, 1)
36 21
37#define IN_RANGE_INC(type,val,beg,end) \ 22#define IN_RANGE_INC(type,val,beg,end) \
38 ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \ 23 ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \
39 <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg))) 24 <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg)))
40 25
58 43
59 SV *cb_object; 44 SV *cb_object;
60 HV *cb_sk_object; 45 HV *cb_sk_object;
61} CBOR; 46} CBOR;
62 47
63INLINE void 48ecb_inline void
64cbor_init (CBOR *cbor) 49cbor_init (CBOR *cbor)
65{ 50{
66 Zero (cbor, 1, CBOR); 51 Zero (cbor, 1, CBOR);
67 cbor->max_depth = 512; 52 cbor->max_depth = 512;
68} 53}
69 54
70///////////////////////////////////////////////////////////////////////////// 55/////////////////////////////////////////////////////////////////////////////
71// utility functions 56// utility functions
72 57
73INLINE SV * 58ecb_inline SV *
74get_bool (const char *name) 59get_bool (const char *name)
75{ 60{
76 SV *sv = get_sv (name, 1); 61 SV *sv = get_sv (name, 1);
77 62
78 SvREADONLY_on (sv); 63 SvREADONLY_on (sv);
79 SvREADONLY_on (SvRV (sv)); 64 SvREADONLY_on (SvRV (sv));
80 65
81 return sv; 66 return sv;
82} 67}
83 68
84INLINE void 69ecb_inline void
85shrink (SV *sv) 70shrink (SV *sv)
86{ 71{
87 sv_utf8_downgrade (sv, 1); 72 sv_utf8_downgrade (sv, 1);
88 73
89 if (SvLEN (sv) > SvCUR (sv) + 1) 74 if (SvLEN (sv) > SvCUR (sv) + 1)
112 SV *sv; // result scalar 97 SV *sv; // result scalar
113 CBOR cbor; 98 CBOR cbor;
114 U32 depth; // recursion level 99 U32 depth; // recursion level
115} enc_t; 100} enc_t;
116 101
117INLINE void 102ecb_inline void
118need (enc_t *enc, STRLEN len) 103need (enc_t *enc, STRLEN len)
119{ 104{
120 if (expect_false (enc->cur + len >= enc->end)) 105 if (ecb_expect_false (enc->cur + len >= enc->end))
121 { 106 {
122 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); 107 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
123 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 108 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
124 enc->cur = SvPVX (enc->sv) + cur; 109 enc->cur = SvPVX (enc->sv) + cur;
125 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; 110 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1;
126 } 111 }
127} 112}
128 113
129INLINE void 114ecb_inline void
130encode_ch (enc_t *enc, char ch) 115encode_ch (enc_t *enc, char ch)
131{ 116{
132 need (enc, 1); 117 need (enc, 1);
133 *enc->cur++ = ch; 118 *enc->cur++ = ch;
134} 119}
138{ 123{
139 need (enc, 9); 124 need (enc, 9);
140 125
141 if (len < 24) 126 if (len < 24)
142 *enc->cur++ = major | len; 127 *enc->cur++ = major | len;
143 else if (len < 0x100) 128 else if (len <= 0xff)
144 { 129 {
145 *enc->cur++ = major | 24; 130 *enc->cur++ = major | 24;
146 *enc->cur++ = len; 131 *enc->cur++ = len;
147 } 132 }
148 else if (len < 0x10000) 133 else if (len <= 0xffff)
149 { 134 {
150 *enc->cur++ = major | 25; 135 *enc->cur++ = major | 25;
151 *enc->cur++ = len >> 8; 136 *enc->cur++ = len >> 8;
152 *enc->cur++ = len; 137 *enc->cur++ = len;
153 } 138 }
154 else if (len < 0x100000000) 139 else if (len <= 0xffffffff)
155 { 140 {
156 *enc->cur++ = major | 26; 141 *enc->cur++ = major | 26;
157 *enc->cur++ = len >> 24; 142 *enc->cur++ = len >> 24;
158 *enc->cur++ = len >> 16; 143 *enc->cur++ = len >> 16;
159 *enc->cur++ = len >> 8; 144 *enc->cur++ = len >> 8;
160 *enc->cur++ = len; 145 *enc->cur++ = len;
161 } 146 }
162 else if (len) 147 else
163 { 148 {
164 *enc->cur++ = major | 27; 149 *enc->cur++ = major | 27;
165 *enc->cur++ = len >> 56; 150 *enc->cur++ = len >> 56;
166 *enc->cur++ = len >> 48; 151 *enc->cur++ = len >> 48;
167 *enc->cur++ = len >> 40; 152 *enc->cur++ = len >> 40;
228 if (HeKLEN (he) == HEf_SVKEY) 213 if (HeKLEN (he) == HEf_SVKEY)
229 encode_sv (enc, HeSVKEY (he)); 214 encode_sv (enc, HeSVKEY (he));
230 else 215 else
231 encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he)); 216 encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he));
232 217
233 encode_sv (enc, expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he)); 218 encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he));
234 } 219 }
235 220
236 if (mg) 221 if (mg)
237 encode_ch (enc, 0xe0 | 31); 222 encode_ch (enc, 0xe0 | 31);
238 223
246 svtype svt; 231 svtype svt;
247 232
248 SvGETMAGIC (sv); 233 SvGETMAGIC (sv);
249 svt = SvTYPE (sv); 234 svt = SvTYPE (sv);
250 235
251 if (expect_false (SvOBJECT (sv))) 236 if (ecb_expect_false (SvOBJECT (sv)))
252 { 237 {
253 HV *stash = !CBOR_SLOW || cbor_boolean_stash 238 HV *stash = !CBOR_SLOW || cbor_boolean_stash
254 ? cbor_boolean_stash 239 ? cbor_boolean_stash
255 : gv_stashpv ("CBOR::XS::Boolean", 1); 240 : gv_stashpv ("CBOR::XS::Boolean", 1);
256 241
332{ 317{
333 double nv = SvNVX (sv); 318 double nv = SvNVX (sv);
334 319
335 need (enc, 9); 320 need (enc, 9);
336 321
337 if (expect_false (nv == (U32)nv)) 322 if (ecb_expect_false (nv == (U32)nv))
338 encode_uint (enc, 0x00, (U32)nv); 323 encode_uint (enc, 0x00, (U32)nv);
339 //TODO: maybe I32? 324 //TODO: maybe I32?
340 else if (expect_false (nv == (float)nv)) 325 else if (ecb_expect_false (nv == (float)nv))
341 { 326 {
342 uint32_t fp = ecb_float_to_binary32 (nv); 327 uint32_t fp = ecb_float_to_binary32 (nv);
343 328
344 *enc->cur++ = 0xe0 | 26; 329 *enc->cur++ = 0xe0 | 26;
345 330
433 U32 maxdepth; // recursion depth limit 418 U32 maxdepth; // recursion depth limit
434} dec_t; 419} dec_t;
435 420
436#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE 421#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
437 422
438#define WANT(len) if (expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data"); 423#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
439 424
440#define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED) 425#define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED)
441#define DEC_DEC_DEPTH --dec->depth 426#define DEC_DEC_DEPTH --dec->depth
442 427
443static UV 428static UV
504 489
505 for (;;) 490 for (;;)
506 { 491 {
507 WANT (1); 492 WANT (1);
508 493
509 if (*dec->cur == 0xe0 | 31) 494 if (*dec->cur == (0xe0 | 31))
510 { 495 {
511 ++dec->cur; 496 ++dec->cur;
512 break; 497 break;
513 } 498 }
514 499
547 532
548 for (;;) 533 for (;;)
549 { 534 {
550 WANT (1); 535 WANT (1);
551 536
552 if (*dec->cur == 0xe0 | 31) 537 if (*dec->cur == (0xe0 | 31))
553 { 538 {
554 ++dec->cur; 539 ++dec->cur;
555 break; 540 break;
556 } 541 }
557 542
752 // not very fast, and certainly not robust against illegal input 737 // not very fast, and certainly not robust against illegal input
753 for (;;) 738 for (;;)
754 { 739 {
755 WANT (1); 740 WANT (1);
756 741
757 if (*dec->cur == 0xe0 | 31) 742 if (*dec->cur == (0xe0 | 31))
758 { 743 {
759 ++dec->cur; 744 ++dec->cur;
760 break; 745 break;
761 } 746 }
762 747
778 763
779 return sv; 764 return sv;
780 765
781fail: 766fail:
782 return &PL_sv_undef; 767 return &PL_sv_undef;
768}
769
770static SV *
771decode_tagged (dec_t *dec)
772{
773 UV tag = decode_uint (dec);
774 SV *sv = decode_sv (dec);
775
776 if (tag == 55799) // 2.4.5 Self-Describe CBOR
777 return sv;
778
779 AV *av = newAV ();
780 av_push (av, newSVuv (tag));
781 av_push (av, sv);
782 return newRV_noinc ((SV *)av);
783} 783}
784 784
785static SV * 785static SV *
786decode_sv (dec_t *dec) 786decode_sv (dec_t *dec)
787{ 787{
801 case 4: // array 801 case 4: // array
802 return decode_av (dec); 802 return decode_av (dec);
803 case 5: // map 803 case 5: // map
804 return decode_hv (dec); 804 return decode_hv (dec);
805 case 6: // tag 805 case 6: // tag
806 abort (); 806 return decode_tagged (dec);
807 break;
808 case 7: // misc 807 case 7: // misc
809 switch (*dec->cur++ & 31) 808 switch (*dec->cur++ & 31)
810 { 809 {
811 case 20: 810 case 20:
812#if CBOR_SLOW 811#if CBOR_SLOW
820 return newSVsv (cbor_true); 819 return newSVsv (cbor_true);
821 case 22: 820 case 22:
822 return newSVsv (&PL_sv_undef); 821 return newSVsv (&PL_sv_undef);
823 822
824 case 25: 823 case 25:
825 // half float
826 abort ();
827 break; 824 {
825 WANT (2);
826
827 uint16_t fp = (dec->cur[0] << 8) | dec->cur[1];
828 dec->cur += 2;
829
830 return newSVnv (ecb_binary16_to_float (fp));
831 }
828 832
829 case 26: 833 case 26:
830 { 834 {
831 uint32_t fp; 835 uint32_t fp;
832 WANT (4); 836 WANT (4);
975 979
976 if (offset_return) 980 if (offset_return)
977 *offset_return = dec.cur; 981 *offset_return = dec.cur;
978 982
979 if (!(offset_return || !sv)) 983 if (!(offset_return || !sv))
980 {
981 if (*dec.cur && !dec.err) 984 if (dec.cur != dec.end && !dec.err)
982 {
983 dec.err = "garbage after CBOR object"; 985 dec.err = "garbage after CBOR object";
986
987 if (dec.err)
988 {
984 SvREFCNT_dec (sv); 989 SvREFCNT_dec (sv);
985 sv = 0;
986 }
987 }
988
989 if (!sv)
990 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur); 990 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur);
991 }
991 992
992 sv = sv_2mortal (sv); 993 sv = sv_2mortal (sv);
993 994
994 return sv; 995 return sv;
995} 996}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines