# HG changeset patch # User jbe # Date 1406904010 -7200 # Node ID ce208edffcc9b12e3cadfb46bfa3ce59b2dbe091 # Parent c055d6d6458656139e572827bdf3166d679de37a Code cleanup in json.object and json.array functions diff -r c055d6d64586 -r ce208edffcc9 libraries/json/json.c --- a/libraries/json/json.c Fri Aug 01 13:09:15 2014 +0200 +++ b/libraries/json/json.c Fri Aug 01 16:40:10 2014 +0200 @@ -49,16 +49,21 @@ // converts a Lua table to a JSON object or JSON array: // (does never modify the argument, returns an empty object or array if argument is nil) static int json_convert(lua_State *L, int array) { - lua_settop(L, 1); + int arrayidx = 0; + // determine is argument is given: if (lua_isnoneornil(L, json_convert_source_idx)) { + // if no argument is given (or if argument is nil), + // create table with shadow table, and leave first table on top of stack: json_regfetch(L, shadowtbl); lua_newtable(L); lua_pushvalue(L, -1); lua_newtable(L); lua_rawset(L, -4); } else { - // push iterator function on stack position 2 if existent, + // if an argument was given, + // push its iterator function on stack position 2 if existent, // else push null for normal tables: + lua_settop(L, 1); if (lua_getmetatable(L, json_convert_source_idx)) { lua_getfield(L, -1, array ? "__ipairs" : "__pairs"); if (lua_isnil(L, -1)) luaL_checktype(L, 1, LUA_TTABLE); @@ -68,7 +73,7 @@ } else { lua_pushnil(L); } - // create table on stack position 3: + // create result table on stack position 3: lua_newtable(L); // create shadow table on stack position 4: json_regfetch(L, shadowtbl); @@ -77,22 +82,47 @@ lua_pushvalue(L, -2); lua_rawset(L, -4); lua_replace(L, -2); + // check if iterator function exists: if (lua_isnil(L, json_convert_iterator_idx)) { - for (lua_pushnil(L); lua_next(L, json_convert_source_idx); lua_pop(L, 1)) { - lua_pushvalue(L, -2); - lua_pushvalue(L, -2); - lua_rawset(L, json_convert_shadow_idx); + // if there is no iterator function, + // distinguish between objects and arrays: + if (array == 0) { + // for an object, copy all string key value pairs to shadow table: + for (lua_pushnil(L); lua_next(L, json_convert_source_idx); lua_pop(L, 1)) { + if (lua_type(L, -2) == LUA_TSTRING) { + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, json_convert_shadow_idx); + } + } + } else { + // for an array, copy consecutive integer value pairs to shadow table: + while (1) { + // TODO: Lua 5.3 may support more elements + if (arrayidx == INT_MAX) { + lua_pushnumber(L, (size_t)INT_MAX+1); + lua_rawget(L, json_convert_source_idx); + if (lua_isnil(L, -1)) break; + return luaL_error(L, "Array exceeded length of %d elements", INT_MAX); + } + arrayidx++; + lua_rawgeti(L, json_convert_source_idx, arrayidx); + if (lua_isnil(L, -1)) break; + lua_rawseti(L, json_convert_shadow_idx, arrayidx); + } } } else { + // TODO: implement conversion using iterator metamethods return luaL_error(L, "Using %s metamethod not implemented yet", array ? "__ipairs" : "__pairs"); } + // let result table be on top of stack: lua_settop(L, json_convert_output_idx); } - // set metatable: - if (array) json_regfetch(L, arraymt); - else json_regfetch(L, objectmt); + // set metatable (for result table on top of stack): + if (array == 0) json_regfetch(L, objectmt); + else json_regfetch(L, arraymt); lua_setmetatable(L, -2); - // return table: + // return table on top of stack: return 1; }