--- JSON-XS/XS.xs 2008/03/19 15:17:53 1.74 +++ JSON-XS/XS.xs 2008/03/20 00:56:37 1.76 @@ -6,6 +6,7 @@ #include #include #include +#include #include #if defined(__BORLANDC__) || defined(_MSC_VER) @@ -18,6 +19,8 @@ # define UTF8_MAXBYTES 13 #endif +#define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 2) + #define F_ASCII 0x00000001UL #define F_LATIN1 0x00000002UL #define F_UTF8 0x00000004UL @@ -650,17 +653,8 @@ // we assume we can always read an IV as a UV and vice versa // we assume two's complement // we assume no aliasing issues in the union - if (SvIsUV (sv) ? SvUVX (sv) > 59000 - : SvIVX (sv) > 59000 || SvIVX (sv) < -59000) - { - // large integer, use the (rather slow) snprintf way. - need (enc, sizeof (UV) * 5 / 2 + 1); // CHAR_BIT is at least 8 - enc->cur += - SvIsUV(sv) - ? snprintf (enc->cur, sizeof (UV) * 3, "%"UVuf, (UV)SvUVX (sv)) - : snprintf (enc->cur, sizeof (UV) * 3, "%"IVdf, (IV)SvIVX (sv)); - } - else + if (SvIsUV (sv) ? SvUVX (sv) <= 59000 + : SvIVX (sv) <= 59000 && SvIVX (sv) >= -59000) { // optimise the "small number case" // code will likely be branchless and use only a single multiplication @@ -681,13 +675,22 @@ // and multiplying by 5 while moving the decimal point one to the right, // resulting in a net multiplication by 10. // we always write the digit to memory but conditionally increment - // the pointer, to ease the usage of conditional move instructions. - digit = u >> 28; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0xfffffff) * 5; - digit = u >> 27; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x7ffffff) * 5; - digit = u >> 26; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x3ffffff) * 5; - digit = u >> 25; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x1ffffff) * 5; + // the pointer, to enable the use of conditional move instructions. + digit = u >> 28; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0xfffffffUL) * 5; + digit = u >> 27; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x7ffffffUL) * 5; + digit = u >> 26; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x3ffffffUL) * 5; + digit = u >> 25; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x1ffffffUL) * 5; digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; // correctly generate '0' } + else + { + // large integer, use the (rather slow) snprintf way. + need (enc, IVUV_MAXCHARS); + enc->cur += + SvIsUV(sv) + ? snprintf (enc->cur, IVUV_MAXCHARS, "%"UVuf, (UV)SvUVX (sv)) + : snprintf (enc->cur, IVUV_MAXCHARS, "%"IVdf, (IV)SvIVX (sv)); + } } else if (SvROK (sv)) encode_rv (enc, SvRV (sv)); @@ -1641,16 +1644,22 @@ PROTOTYPES: ENABLE void encode_json (SV *scalar) + ALIAS: + to_json_ = 0 + encode_json = F_UTF8 PPCODE: { - JSON json = { F_DEFAULT | F_UTF8 }; + JSON json = { F_DEFAULT | ix }; XPUSHs (encode_json (scalar, &json)); } void decode_json (SV *jsonstr) + ALIAS: + from_json_ = 0 + decode_json = F_UTF8 PPCODE: { - JSON json = { F_DEFAULT | F_UTF8 }; + JSON json = { F_DEFAULT | ix }; XPUSHs (decode_json (jsonstr, &json, 0)); }