# HG changeset patch # User jbe # Date 1406753781 -7200 # Node ID 5229687c7601f2aae328758a3fd3ab2da1f5d07b # Parent 5354d836e6fb8d48eccb9c0b027abb4593e30d03 Removed metatable entries in JSON library module (since they should not be set directly); Added documentation to JSON library diff -r 5354d836e6fb -r 5229687c7601 libraries/json/json.c --- a/libraries/json/json.c Wed Jul 30 22:32:33 2014 +0200 +++ b/libraries/json/json.c Wed Jul 30 22:56:21 2014 +0200 @@ -651,22 +651,34 @@ #define json_pairs_iterfunc_shadowtbl_idx 4 static int json_pairs_iterfunc(lua_State *L) { + // stack shall contain two function arguments: lua_settop(L, 2); - json_pushlightref(L, nullmark); // on stack position 3 + // push nullmark onto stack position 3: + json_pushlightref(L, nullmark); + // push shadowtbl onto stack position 4: json_regfetch(L, shadowtbl); + // get corresponding shadow table for first argument: lua_pushvalue(L, 1); lua_rawget(L, json_pairs_iterfunc_shadowtbl_idx); + // throw error if no shadow table was found: if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); + // get next key value pair from shadow table (using previous key from argument 2) + // and return nothing if there is no next pair: lua_pushvalue(L, 2); if (!lua_next(L, -2)) return 0; + // replace null-marker with nil: if (lua_rawequal(L, -1, json_pairs_iterfunc_nullmark_idx)) { lua_pop(L, 1); lua_pushnil(L); } + // return key and value (or key and nil, if null-marker was found): return 2; } +// returns a triple such that 'for key, value in pairs(obj) do ... end' +// iterates through all key value pairs (including JSON null keys represented as Lua nil): static int json_pairs(lua_State *L) { + // return triple of function json_pairs_iterfunc, first argument, and nil: lua_pushcfunction(L, json_pairs_iterfunc); lua_pushvalue(L, 1); lua_pushnil(L); @@ -679,28 +691,43 @@ static int json_ipairs_iterfunc(lua_State *L) { int idx; + // stack shall contain two function arguments: lua_settop(L, 2); - json_pushlightref(L, nullmark); // on stack position 3 + // push nullmark onto stack position 3: + json_pushlightref(L, nullmark); + // push shadowtbl onto stack position 4: json_regfetch(L, shadowtbl); + // calculate new index by incrementing second argument: idx = lua_tointeger(L, 2) + 1; + // get corresponding shadow table for first argument: lua_pushvalue(L, 1); lua_rawget(L, json_ipairs_iterfunc_shadowtbl_idx); + // throw error if no shadow table was found: if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); + // do integer lookup in shadow table: lua_rawgeti(L, -1, idx); + // return nothing if there was no value: if (lua_isnil(L, -1)) return 0; + // return new index and + // either the looked up value if it is not equal to the null-marker + // or nil instead of null-marker: lua_pushinteger(L, idx); if (lua_rawequal(L, -2, json_ipairs_iterfunc_nullmark_idx)) lua_pushnil(L); else lua_pushvalue(L, -2); return 2; } +// returns a triple such that 'for idx, value in ipairs(ary) do ... end' +// iterates through all values (including JSON null represented as Lua nil): static int json_ipairs(lua_State *L) { + // return triple of function json_ipairs_iterfunc, first argument, and zero: lua_pushcfunction(L, json_ipairs_iterfunc); lua_pushvalue(L, 1); lua_pushinteger(L, 0); return 3; } +// functions in library module: static const struct luaL_Reg json_module_functions[] = { {"object", json_object}, {"array", json_array}, @@ -712,6 +739,7 @@ {NULL, NULL} }; +// metamethods for JSON objects, JSON arrays, and unknown JSON collections (object or array): static const struct luaL_Reg json_metatable_functions[] = { {"__len", json_len}, {"__index", json_index}, @@ -721,29 +749,36 @@ {NULL, NULL} }; +// initializes json library: int luaopen_json(lua_State *L) { + // empty stack: lua_settop(L, 0); - lua_newtable(L); // library + // push library module onto stack position 1: + lua_newtable(L); + // register library functions: + luaL_setfuncs(L, json_module_functions, 0); + // create and store unknownmt: lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); json_regstore(L, unknownmt); - lua_setfield(L, 1, "ambiguous_mt"); + // create and store objectmt: lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); json_regstore(L, objectmt); - lua_setfield(L, 1, "object_mt"); + // create and store arraymt: lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); json_regstore(L, arraymt); - lua_setfield(L, 1, "array_mt"); - lua_newtable(L); // ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil + // create and store ephemeron table to store shadow tables for each JSON object/array + // to allow NULL values returned as nil + lua_newtable(L); lua_newtable(L); // metatable for ephemeron table lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3); lua_setmetatable(L, -2); json_regstore(L, shadowtbl); + // return library module stored on lowest stack position: lua_settop(L, 1); - luaL_setfuncs(L, json_module_functions, 0); return 1; }