webmcp

changeset 427:f0303fca9218

Decode some JSON numbers (those without decimal point or exponential notation) as Lua integers
author jbe
date Thu Jan 14 17:13:48 2016 +0100 (2016-01-14)
parents 9d15451c340a
children 52ebde158c92
files libraries/json/json.c
line diff
     1.1 --- a/libraries/json/json.c	Thu Jan 14 12:49:54 2016 +0100
     1.2 +++ b/libraries/json/json.c	Thu Jan 14 17:13:48 2016 +0100
     1.3 @@ -544,17 +544,44 @@
     1.4    }
     1.5    // process values whose type is is not deducible from a single character:
     1.6    if ((c >= '0' && c <= '9') || c == '-' || c == '+') {
     1.7 -    // for numbers,
     1.8 -    // use strtod() call to parse a (double precision) floating point number:
     1.9 +    // try to parse number:
    1.10      double numval;
    1.11      char *endptr;
    1.12 +    size_t endpos;
    1.13 +    // use strtod() call to parse a (double precision) floating point number
    1.14 +    // and to determine length of number:
    1.15      numval = strtod(str+pos, &endptr);
    1.16      // catch parsing errors:
    1.17      if (endptr == str+pos) goto json_import_syntax_error;
    1.18 +    // calculate end position of number:
    1.19 +    endpos = endptr - str;
    1.20 +#if LUA_VERSION_NUM >= 503
    1.21 +    // try alternative integer interpretation:
    1.22 +    {
    1.23 +      lua_Integer intval = 0;
    1.24 +      size_t curpos;
    1.25 +      if (c >= '0' && c <= '9') intval = c - '0';
    1.26 +      for (curpos=pos+1; curpos<endpos; curpos++) {
    1.27 +        lua_Integer d = str[curpos] - '0';
    1.28 +        if (d < 0 || d > 9) break;
    1.29 +        if (c == '-') {
    1.30 +          // NOTE: rounding of negative integer division may be undefined
    1.31 +          if (
    1.32 +            intval == LUA_MININTEGER ||
    1.33 +            -intval > (-(LUA_MININTEGER+10) - d) / 10 + 1
    1.34 +          ) break;
    1.35 +          intval = 10 * intval - d;
    1.36 +        } else {
    1.37 +          if (intval > (LUA_MAXINTEGER - d) / 10) break;
    1.38 +          intval = 10 * intval + d;
    1.39 +        }
    1.40 +      }
    1.41 +      if (curpos == endpos) lua_pushinteger(L, intval);
    1.42 +      else lua_pushnumber(L, numval);
    1.43 +    }
    1.44 +#endif
    1.45      // consume characters that were parsed:
    1.46 -    pos += endptr - (str+pos);
    1.47 -    // push parsed (double precision) floating point number on Lua stack:
    1.48 -    lua_pushnumber(L, numval);
    1.49 +    pos = endpos;
    1.50    } else if (!strncmp(str+pos, "true", 4)) {
    1.51      // consume 4 input characters for "true":
    1.52      pos += 4;
    1.53 @@ -597,11 +624,11 @@
    1.54    case JSON_STATE_ARRAY_VALUE:
    1.55      // get current array length:
    1.56      arraylen = lua_rawlen(L, -3);
    1.57 -    // throw error if array would exceed INT_MAX elements:
    1.58 -    // TODO: Lua 5.3 may support more elements
    1.59 -    if (arraylen >= INT_MAX) {
    1.60 +    // throw error if array would exceed INT_MAX-1 elements:
    1.61 +    // NOTE: Lua 5.3 may support more elements, but C libraries may not
    1.62 +    if (arraylen > INT_MAX-1) {
    1.63        lua_pushnil(L);
    1.64 -      lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX);
    1.65 +      lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX-1);
    1.66      }
    1.67      // store value in outer shadow table:
    1.68      lua_rawseti(L, -3, arraylen + 1);

Impressum / About Us