--- JSON-XS/XS.xs 2008/03/19 13:44:43 1.73 +++ JSON-XS/XS.xs 2008/03/19 15:17:53 1.74 @@ -125,13 +125,20 @@ INLINE unsigned char * encode_utf8 (unsigned char *s, UV ch) { - if (ch <= 0x7FF) - { - *s++ = (ch >> 6) | 0xc0; - *s++ = (ch & 0x3f) | 0x80; - } - else - s = uvuni_to_utf8_flags (s, ch, 0); + if (expect_false (ch < 0x000080)) + *s++ = ch; + else if (expect_true (ch < 0x000800)) + *s++ = 0xc0 | ( ch >> 6), + *s++ = 0x80 | ( ch & 0x3f); + else if ( ch < 0x010000) + *s++ = 0xe0 | ( ch >> 12), + *s++ = 0x80 | ((ch >> 6) & 0x3f), + *s++ = 0x80 | ( ch & 0x3f); + else if ( ch < 0x110000) + *s++ = 0xf0 | ( ch >> 18), + *s++ = 0x80 | ((ch >> 12) & 0x3f), + *s++ = 0x80 | ((ch >> 6) & 0x3f), + *s++ = 0x80 | ( ch & 0x3f); return s; } @@ -229,9 +236,9 @@ if (uch < 0x80/*0x20*/ || uch >= enc->limit) { - if (uch > 0xFFFFUL) + if (uch >= 0x10000UL) { - if (uch > 0x10FFFFUL) + if (uch >= 0x110000UL) croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch); need (enc, len += 11); @@ -640,11 +647,14 @@ } else if (SvIOKp (sv)) { - // we assume we can always read an IV as a UV - if (SvUV (sv) & ~(UV)0x7fff) + // 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) * 3); + 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)) @@ -654,7 +664,8 @@ { // optimise the "small number case" // code will likely be branchless and use only a single multiplication - I32 i = SvIV (sv); + // works for numbers up to 59074 + I32 i = SvIVX (sv); U32 u; char digit, nz = 0; @@ -703,7 +714,7 @@ enc.maxdepth = DEC_DEPTH (enc.json.flags); enc.limit = enc.json.flags & F_ASCII ? 0x000080UL : enc.json.flags & F_LATIN1 ? 0x000100UL - : 0x10FFFFUL; + : 0x110000UL; SvPOK_only (enc.sv); encode_sv (&enc, scalar); @@ -891,7 +902,7 @@ ERR ("illegal backslash escape sequence in string"); } } - else if (expect_true (ch >= 0x20 && ch <= 0x7f)) + else if (expect_true (ch >= 0x20 && ch < 0x80)) *cur++ = ch; else if (ch >= 0x80) {