--- CBOR-XS/XS.xs 2013/10/29 18:37:31 1.15 +++ CBOR-XS/XS.xs 2013/10/29 20:59:16 1.16 @@ -586,6 +586,40 @@ return &PL_sv_undef; } +static void +decode_he (dec_t *dec, HV *hv) +{ + // for speed reasons, we specialcase single-string + // byte or utf-8 strings as keys. + + if (*dec->cur >= 0x40 && *dec->cur <= 0x40 + 27) + { + I32 len = decode_uint (dec); + char *key = (char *)dec->cur; + + dec->cur += len; + + hv_store (hv, key, len, decode_sv (dec), 0); + } + else if (*dec->cur >= 0x60 && *dec->cur <= 0x60 + 27) + { + I32 len = decode_uint (dec); + char *key = (char *)dec->cur; + + dec->cur += len; + + hv_store (hv, key, -len, decode_sv (dec), 0); + } + else + { + SV *k = decode_sv (dec); + SV *v = decode_sv (dec); + + hv_store_ent (hv, k, v, 0); + SvREFCNT_dec (k); + } +} + static SV * decode_hv (dec_t *dec) { @@ -607,25 +641,15 @@ break; } - SV *k = decode_sv (dec); - SV *v = decode_sv (dec); - - hv_store_ent (hv, k, v, 0); - SvREFCNT_dec (k); + decode_he (dec, hv); } } else { - int len = decode_uint (dec); + int pairs = decode_uint (dec); - while (len--) - { - SV *k = decode_sv (dec); - SV *v = decode_sv (dec); - - hv_store_ent (hv, k, v, 0); - SvREFCNT_dec (k); - } + while (pairs--) + decode_he (dec, hv); } DEC_DEC_DEPTH; @@ -846,45 +870,16 @@ { dec_t dec; SV *sv; + STRLEN len; + char *data = SvPVbyte (string, len); - /* work around bugs in 5.10 where manipulating magic values - * makes perl ignore the magic in subsequent accesses. - * also make a copy of non-PV values, to get them into a clean - * state (SvPV should do that, but it's buggy, see below). - */ - /*SvGETMAGIC (string);*/ - if (SvMAGICAL (string) || !SvPOK (string)) - string = sv_2mortal (newSVsv (string)); - - SvUPGRADE (string, SVt_PV); - - /* work around a bug in perl 5.10, which causes SvCUR to fail an - * assertion with -DDEBUGGING, although SvCUR is documented to - * return the xpv_cur field which certainly exists after upgrading. - * according to nicholas clark, calling SvPOK fixes this. - * But it doesn't fix it, so try another workaround, call SvPV_nolen - * and hope for the best. - * Damnit, SvPV_nolen still trips over yet another assertion. This - * assertion business is seriously broken, try yet another workaround - * for the broken -DDEBUGGING. - */ - { -#ifdef DEBUGGING - STRLEN offset = SvOK (string) ? sv_len (string) : 0; -#else - STRLEN offset = SvCUR (string); -#endif - - if (offset > cbor->max_size && cbor->max_size) - croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu", - (unsigned long)SvCUR (string), (unsigned long)cbor->max_size); - } - - sv_utf8_downgrade (string, 0); + if (len > cbor->max_size && cbor->max_size) + croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu", + (unsigned long)len, (unsigned long)cbor->max_size); dec.cbor = *cbor; - dec.cur = (U8 *)SvPVX (string); - dec.end = (U8 *)SvEND (string); + dec.cur = (U8 *)data; + dec.end = (U8 *)data + len; dec.err = 0; dec.depth = 0; @@ -900,7 +895,7 @@ if (dec.err) { SvREFCNT_dec (sv); - croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)SvPVX (string), (int)(uint8_t)*dec.cur); + croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); } sv = sv_2mortal (sv);