# HG changeset patch # User jbe # Date 1452788028 -3600 # Node ID f0303fca9218d21cd6cb4ca0883ba505bcf53ef8 # Parent 9d15451c340a5acde19fb82521711c4a0b221a87 Decode some JSON numbers (those without decimal point or exponential notation) as Lua integers diff -r 9d15451c340a -r f0303fca9218 libraries/json/json.c --- a/libraries/json/json.c Thu Jan 14 12:49:54 2016 +0100 +++ b/libraries/json/json.c Thu Jan 14 17:13:48 2016 +0100 @@ -544,17 +544,44 @@ } // process values whose type is is not deducible from a single character: if ((c >= '0' && c <= '9') || c == '-' || c == '+') { - // for numbers, - // use strtod() call to parse a (double precision) floating point number: + // try to parse number: double numval; char *endptr; + size_t endpos; + // use strtod() call to parse a (double precision) floating point number + // and to determine length of number: numval = strtod(str+pos, &endptr); // catch parsing errors: if (endptr == str+pos) goto json_import_syntax_error; + // calculate end position of number: + endpos = endptr - str; +#if LUA_VERSION_NUM >= 503 + // try alternative integer interpretation: + { + lua_Integer intval = 0; + size_t curpos; + if (c >= '0' && c <= '9') intval = c - '0'; + for (curpos=pos+1; curpos 9) break; + if (c == '-') { + // NOTE: rounding of negative integer division may be undefined + if ( + intval == LUA_MININTEGER || + -intval > (-(LUA_MININTEGER+10) - d) / 10 + 1 + ) break; + intval = 10 * intval - d; + } else { + if (intval > (LUA_MAXINTEGER - d) / 10) break; + intval = 10 * intval + d; + } + } + if (curpos == endpos) lua_pushinteger(L, intval); + else lua_pushnumber(L, numval); + } +#endif // consume characters that were parsed: - pos += endptr - (str+pos); - // push parsed (double precision) floating point number on Lua stack: - lua_pushnumber(L, numval); + pos = endpos; } else if (!strncmp(str+pos, "true", 4)) { // consume 4 input characters for "true": pos += 4; @@ -597,11 +624,11 @@ case JSON_STATE_ARRAY_VALUE: // get current array length: arraylen = lua_rawlen(L, -3); - // throw error if array would exceed INT_MAX elements: - // TODO: Lua 5.3 may support more elements - if (arraylen >= INT_MAX) { + // throw error if array would exceed INT_MAX-1 elements: + // NOTE: Lua 5.3 may support more elements, but C libraries may not + if (arraylen > INT_MAX-1) { lua_pushnil(L); - lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX); + lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX-1); } // store value in outer shadow table: lua_rawseti(L, -3, arraylen + 1);