# HG changeset patch # User jbe # Date 1452789649 -3600 # Node ID 52ebde158c92091b5d376fa50c7bfc957ff7a3cc # Parent f0303fca9218d21cd6cb4ca0883ba505bcf53ef8 Fixed minor glitch regarding floating point numbers (e.g. 0.009) in JSON encoder; Distinguish between integers and floats in JSON encoder if Lua version >= 5.3 diff -r f0303fca9218 -r 52ebde158c92 libraries/json/json.c --- a/libraries/json/json.c Thu Jan 14 17:13:48 2016 +0100 +++ b/libraries/json/json.c Thu Jan 14 17:40:49 2016 +0100 @@ -1037,7 +1037,11 @@ int pretty; // pretty printing on? (i.e. printing with indentation) luaL_Buffer buf; // Lua buffer containing result string lua_Number num; // number to encode - char numstr[21]; // encoded number (sign, zero, point, 17 significant digits, and terminating NULL byte) + char numstr[80]; // encoded number + // (21 chars needed for sign, zero, point, 17 significant digits, and NULL byte) + // (21 chars needed for sign, 19 digits INT64, and NULL byte) + // (80 chars needed for sign, 78 digits INT256, and NULL byte) + // (NOTE: we don't know the size of intmax_t and thus use 80) const char *str; // string to encode size_t strlen; // length of string to encode size_t strpos ; // position in string or position of current key @@ -1101,6 +1105,14 @@ break; // value to encode is of type number: case LUA_TNUMBER: +#if LUA_VERSION_NUM >= 503 + // handle integers: + if (lua_isinteger(L, json_export_value_idx)) { + sprintf(numstr, "%ji", (intmax_t)lua_tointeger(L, json_export_value_idx)); + luaL_addstring(&buf, numstr); + break; + } +#endif // convert value to double precision number: num = lua_tonumber(L, json_export_value_idx); // throw error if number is not-a-number: @@ -1108,10 +1120,21 @@ // throw error if number is positive or negative infinity: if (isinf(num)) return luaL_error(L, "JSON export not possible for infinite numbers"); // determine necessary precision to represent double precision floating point number: - sprintf(numstr, "%.16g", num); + sprintf(numstr, "%.15g", num); // NOTE: e.g. 0.009 should not be 0.008999999999999999 + if (strtod(numstr, NULL) != num) sprintf(numstr, "%.16g", num); if (strtod(numstr, NULL) != num) sprintf(numstr, "%.17g", num); // add string encoding of the number to the output buffer: luaL_addstring(&buf, numstr); +#if LUA_VERSION_NUM >= 503 + // enforce trailing ".0" for floats unless exponential notation was chosen: + { + char *p; + if (numstr[0] == '-' || numstr[0] == '+') p = numstr+1; + else p = numstr; + for (; *p; p++) if (*p < '0' || *p > '9') break; + if (!*p) luaL_addstring(&buf, ".0"); + } +#endif break; // value to encode is of type boolean: case LUA_TBOOLEAN: