--- CBOR-XS/XS.xs 2013/10/25 23:09:45 1.1 +++ CBOR-XS/XS.xs 2013/10/26 21:14:20 1.5 @@ -11,10 +11,6 @@ #include "ecb.h" -#if defined(__BORLANDC__) || defined(_MSC_VER) -# define snprintf _snprintf // C compilers have this in stdio.h -#endif - #define F_SHRINK 0x00000200UL #define F_ALLOW_UNKNOWN 0x00002000UL @@ -23,17 +19,6 @@ #define SB do { #define SE } while (0) -#if __GNUC__ >= 3 -# define expect(expr,value) __builtin_expect ((expr), (value)) -# define INLINE static inline -#else -# define expect(expr,value) (expr) -# define INLINE static -#endif - -#define expect_false(expr) expect ((expr) != 0, 0) -#define expect_true(expr) expect ((expr) != 0, 1) - #define IN_RANGE_INC(type,val,beg,end) \ ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \ <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg))) @@ -60,7 +45,7 @@ HV *cb_sk_object; } CBOR; -INLINE void +ecb_inline void cbor_init (CBOR *cbor) { Zero (cbor, 1, CBOR); @@ -70,7 +55,7 @@ ///////////////////////////////////////////////////////////////////////////// // utility functions -INLINE SV * +ecb_inline SV * get_bool (const char *name) { SV *sv = get_sv (name, 1); @@ -81,7 +66,7 @@ return sv; } -INLINE void +ecb_inline void shrink (SV *sv) { sv_utf8_downgrade (sv, 1); @@ -114,10 +99,10 @@ U32 depth; // recursion level } enc_t; -INLINE void +ecb_inline void need (enc_t *enc, STRLEN len) { - if (expect_false (enc->cur + len >= enc->end)) + if (ecb_expect_false (enc->cur + len >= enc->end)) { STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); @@ -126,7 +111,7 @@ } } -INLINE void +ecb_inline void encode_ch (enc_t *enc, char ch) { need (enc, 1); @@ -140,18 +125,18 @@ if (len < 24) *enc->cur++ = major | len; - else if (len < 0x100) + else if (len <= 0xff) { *enc->cur++ = major | 24; *enc->cur++ = len; } - else if (len < 0x10000) + else if (len <= 0xffff) { *enc->cur++ = major | 25; *enc->cur++ = len >> 8; *enc->cur++ = len; } - else if (len < 0x100000000) + else if (len <= 0xffffffff) { *enc->cur++ = major | 26; *enc->cur++ = len >> 24; @@ -159,7 +144,7 @@ *enc->cur++ = len >> 8; *enc->cur++ = len; } - else if (len) + else { *enc->cur++ = major | 27; *enc->cur++ = len >> 56; @@ -230,7 +215,7 @@ else encode_str (enc, HeKUTF8 (he), HeKEY (he), HeKLEN (he)); - encode_sv (enc, expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he)); + encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he)); } if (mg) @@ -248,7 +233,7 @@ SvGETMAGIC (sv); svt = SvTYPE (sv); - if (expect_false (SvOBJECT (sv))) + if (ecb_expect_false (SvOBJECT (sv))) { HV *stash = !CBOR_SLOW || cbor_boolean_stash ? cbor_boolean_stash @@ -334,10 +319,10 @@ need (enc, 9); - if (expect_false (nv == (U32)nv)) + if (ecb_expect_false (nv == (U32)nv)) encode_uint (enc, 0x00, (U32)nv); //TODO: maybe I32? - else if (expect_false (nv == (float)nv)) + else if (ecb_expect_false (nv == (float)nv)) { uint32_t fp = ecb_float_to_binary32 (nv); @@ -435,7 +420,7 @@ #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE -#define WANT(len) if (expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data"); +#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") #define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED) #define DEC_DEC_DEPTH --dec->depth @@ -506,7 +491,7 @@ { WANT (1); - if (*dec->cur == 0xe0 | 31) + if (*dec->cur == (0xe0 | 31)) { ++dec->cur; break; @@ -549,7 +534,7 @@ { WANT (1); - if (*dec->cur == 0xe0 | 31) + if (*dec->cur == (0xe0 | 31)) { ++dec->cur; break; @@ -754,7 +739,7 @@ { WANT (1); - if (*dec->cur == 0xe0 | 31) + if (*dec->cur == (0xe0 | 31)) { ++dec->cur; break; @@ -783,6 +768,21 @@ } static SV * +decode_tagged (dec_t *dec) +{ + UV tag = decode_uint (dec); + SV *sv = decode_sv (dec); + + if (tag == 55799) // 2.4.5 Self-Describe CBOR + return sv; + + AV *av = newAV (); + av_push (av, newSVuv (tag)); + av_push (av, sv); + return newRV_noinc ((SV *)av); +} + +static SV * decode_sv (dec_t *dec) { WANT (1); @@ -803,8 +803,7 @@ case 5: // map return decode_hv (dec); case 6: // tag - abort (); - break; + return decode_tagged (dec); case 7: // misc switch (*dec->cur++ & 31) { @@ -822,9 +821,14 @@ return newSVsv (&PL_sv_undef); case 25: - // half float - abort (); - break; + { + WANT (2); + + uint16_t fp = (dec->cur[0] << 8) | dec->cur[1]; + dec->cur += 2; + + return newSVnv (ecb_binary16_to_float (fp)); + } case 26: { @@ -977,18 +981,15 @@ *offset_return = dec.cur; if (!(offset_return || !sv)) + if (dec.cur != dec.end && !dec.err) + dec.err = "garbage after CBOR object"; + + if (dec.err) { - if (*dec.cur && !dec.err) - { - dec.err = "garbage after CBOR object"; - SvREFCNT_dec (sv); - sv = 0; - } + SvREFCNT_dec (sv); + croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur); } - if (!sv) - croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur); - sv = sv_2mortal (sv); return sv;