--- JSON-XS/XS.xs 2007/06/11 03:18:07 1.38 +++ JSON-XS/XS.xs 2007/06/11 03:42:57 1.39 @@ -499,6 +499,7 @@ } else if (SvNOKp (sv)) { + // trust that perl will do the right thing w.r.t. JSON syntax. need (enc, NV_DIG + 32); Gconvert (SvNVX (sv), NV_DIG, 0, enc->cur); enc->cur += strlen (enc->cur); @@ -508,6 +509,7 @@ // we assume we can always read an IV as a UV if (SvUV (sv) & ~(UV)0x7fff) { + // large integer, use the (rather slow) snprintf way. need (enc, sizeof (UV) * 3); enc->cur += SvIsUV(sv) @@ -520,6 +522,7 @@ // code will likely be branchless and use only a single multiplication I32 i = SvIV (sv); U32 u; + char digit, nz = 0; need (enc, 6); @@ -529,13 +532,16 @@ // convert to 4.28 fixed-point representation u = u * ((0xfffffff + 10000) / 10000); // 10**5, 5 fractional digits - char digit, nz = 0; - + // now output digit by digit, each time masking out the integer part + // 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; - digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; + digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; // correctly generate '0' } } else if (SvROK (sv))