--- CBOR-XS/XS.xs 2013/11/28 11:43:26 1.31 +++ CBOR-XS/XS.xs 2013/11/30 16:19:59 1.34 @@ -61,8 +61,8 @@ #define F_SHRINK 0x00000001UL #define F_ALLOW_UNKNOWN 0x00000002UL -#define F_ALLOW_SHARING 0x00000004UL //TODO -#define F_ALLOW_STRINGREF 0x00000008UL //TODO +#define F_ALLOW_SHARING 0x00000004UL +#define F_PACK_STRINGS 0x00000008UL #define INIT_SIZE 32 // initial scalar size to be allocated @@ -244,7 +244,7 @@ static void encode_strref (enc_t *enc, int utf8, char *str, STRLEN len) { - if (ecb_expect_false (enc->cbor.flags & F_ALLOW_STRINGREF)) + if (ecb_expect_false (enc->cbor.flags & F_PACK_STRINGS)) { SV **svp = hv_fetch (enc->stringref[!!utf8], str, len, 1); @@ -329,28 +329,6 @@ { SvGETMAGIC (sv); - if (ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING) - && ecb_expect_false (SvREFCNT (sv) > 1)) - { - if (!enc->shareable) - enc->shareable = (HV *)sv_2mortal ((SV *)newHV ()); - - SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1); - - if (SvOK (*svp)) - { - encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF); - encode_uint (enc, 0x00, SvUV (*svp)); - return; - } - else - { - sv_setuv (*svp, enc->shareable_idx); - ++enc->shareable_idx; - encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE); - } - } - svtype svt = SvTYPE (sv); if (ecb_expect_false (SvOBJECT (sv))) @@ -366,12 +344,17 @@ : gv_stashpv ("CBOR::XS::Tagged" , 1); HV *stash = SvSTASH (sv); - GV *method; if (stash == boolean_stash) - encode_ch (enc, SvIV (sv) ? 0xe0 | 21 : 0xe0 | 20); + { + encode_ch (enc, SvIV (sv) ? 0xe0 | 21 : 0xe0 | 20); + return; + } else if (stash == error_stash) - encode_ch (enc, 0xe0 | 23); + { + encode_ch (enc, 0xe0 | 23); + return; + } else if (stash == tagged_stash) { if (svt != SVt_PVAV) @@ -379,8 +362,39 @@ encode_uint (enc, 0xc0, SvUV (*av_fetch ((AV *)sv, 0, 1))); encode_sv (enc, *av_fetch ((AV *)sv, 1, 1)); + + return; + } + } + + if (ecb_expect_false (SvREFCNT (sv) > 1) + && ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING)) + { + if (!enc->shareable) + enc->shareable = (HV *)sv_2mortal ((SV *)newHV ()); + + SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1); + + if (SvOK (*svp)) + { + encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF); + encode_uint (enc, 0x00, SvUV (*svp)); + return; } - else if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0))) + else + { + sv_setuv (*svp, enc->shareable_idx); + ++enc->shareable_idx; + encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE); + } + } + + if (ecb_expect_false (SvOBJECT (sv))) + { + HV *stash = SvSTASH (sv); + GV *method; + + if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0))) { dSP; @@ -528,7 +542,7 @@ SvPOK_only (enc.sv); - if (cbor->flags & F_ALLOW_STRINGREF) + if (cbor->flags & F_PACK_STRINGS) { encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE); enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ()); @@ -602,10 +616,16 @@ case 27: WANT (9); dec->cur += 9; - return (((UV)dec->cur[-8]) << 56) + + return +#if UVSIZE < 8 + 0 +#else + (((UV)dec->cur[-8]) << 56) | (((UV)dec->cur[-7]) << 48) | (((UV)dec->cur[-6]) << 40) | (((UV)dec->cur[-5]) << 32) +#endif | (((UV)dec->cur[-4]) << 24) | (((UV)dec->cur[-3]) << 16) | (((UV)dec->cur[-2]) << 8) @@ -755,22 +775,31 @@ if ((*dec->cur & 31) == 31) { + // indefinite length strings ++dec->cur; + unsigned char major = *dec->cur & 0xe0; + sv = newSVpvn ("", 0); - // not very fast, and certainly not robust against illegal input for (;;) { WANT (1); - if (*dec->cur == (0xe0 | 31)) - { - ++dec->cur; - break; - } + if ((*dec->cur ^ major) >= 31) + if (*dec->cur == (0xe0 | 31)) + { + ++dec->cur; + break; + } + else + ERR ("corrupted CBOR data (invalid chunks in indefinite length string)"); + + STRLEN len = decode_uint (dec); - sv_catsv (sv, decode_sv (dec)); + WANT (len); + sv_catpvn (sv, dec->cur, len); + dec->cur += len; } } else @@ -1147,7 +1176,7 @@ shrink = F_SHRINK allow_unknown = F_ALLOW_UNKNOWN allow_sharing = F_ALLOW_SHARING - allow_stringref = F_ALLOW_STRINGREF + pack_strings = F_PACK_STRINGS PPCODE: { if (enable) @@ -1163,7 +1192,7 @@ get_shrink = F_SHRINK get_allow_unknown = F_ALLOW_UNKNOWN get_allow_sharing = F_ALLOW_SHARING - get_allow_stringref = F_ALLOW_STRINGREF + get_pack_strings = F_PACK_STRINGS PPCODE: XPUSHs (boolSV (self->flags & ix));