# HG changeset patch # User jbe # Date 1406345262 -7200 # Node ID 402fce94f98c4837f686929b181352ac1abd3271 # Parent ff39d4a310b984e598a5c26338b5f75c922d5fc4 Added function json.isnull(...) to JSON library diff -r ff39d4a310b9 -r 402fce94f98c libraries/json/json.c --- a/libraries/json/json.c Fri Jul 25 22:50:12 2014 +0200 +++ b/libraries/json/json.c Sat Jul 26 05:27:42 2014 +0200 @@ -3,6 +3,9 @@ #include #include +#define JSON_UPVAL_ARYLEN lua_upvalueindex(1) +#define JSON_UPVAL_NULLS lua_upvalueindex(2) + #define JSON_VALUE 0 #define JSON_OBJECT_KEY 1 #define JSON_OBJECT_KEY_TERMINATOR 2 @@ -41,6 +44,10 @@ goto json_import_syntax_error; pos++; lua_newtable(L); + lua_newtable(L); // stores set of NULL values + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, JSON_UPVAL_NULLS); mode = JSON_OBJECT_KEY; level++; goto json_import_loop; @@ -49,6 +56,10 @@ goto json_import_syntax_error; pos++; lua_newtable(L); + lua_newtable(L); // stores set of NULL values + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, JSON_UPVAL_NULLS); lua_pushinteger(L, 0); // length of array (since it may contain nil's) mode = JSON_ARRAY_VALUE; level++; @@ -62,10 +73,11 @@ goto json_import_syntax_error; lua_pushvalue(L, -2); // use array table as key lua_insert(L, -2); // use length of array as value - lua_rawset(L, lua_upvalueindex(1)); // store length in ephemeron table + lua_rawset(L, JSON_UPVAL_ARYLEN); // store length in ephemeron table // leaves array table on top of stack json_import_close: pos++; + lua_pop(L, 1); // pop table that stores set of NULL values if (--level) { if (lua_type(L, -2) == LUA_TNUMBER) { mode = JSON_ARRAY_VALUE; @@ -172,12 +184,22 @@ mode = JSON_OBJECT_KEY_TERMINATOR; goto json_import_loop; case JSON_OBJECT_VALUE: - lua_rawset(L, -3); + if (lua_isnil(L, -1)) { + lua_pushvalue(L, -2); + lua_pushboolean(L, 1); + lua_rawset(L, -5); + } + lua_rawset(L, -4); mode = JSON_OBJECT_SEPARATOR; goto json_import_loop; case JSON_ARRAY_VALUE: aryidx = lua_tointeger(L, -2) + 1; - lua_rawseti(L, -3, aryidx); + if (lua_isnil(L, -1)) { + lua_pushinteger(L, aryidx); + lua_pushboolean(L, 1); + lua_rawset(L, -5); + } + lua_rawseti(L, -4, aryidx); lua_pop(L, 1); lua_pushinteger(L, aryidx); mode = JSON_ARRAY_SEPARATOR; @@ -194,24 +216,40 @@ static int json_arylen(lua_State *L) { lua_settop(L, 1); - lua_rawget(L, lua_upvalueindex(1)); + lua_rawget(L, JSON_UPVAL_ARYLEN); + return 1; +} + +static int json_isnull(lua_State *L) { + lua_pushvalue(L, 1); + lua_rawget(L, JSON_UPVAL_NULLS); + if (lua_isnil(L, -1)) goto json_isnull_false; + lua_pushvalue(L, 2); + lua_rawget(L, -2); + if (!lua_isnil(L, -1)) return 1; +json_isnull_false: + lua_pushboolean(L, 0); return 1; } static const struct luaL_Reg json_module_functions[] = { {"import", json_import}, {"arylen", json_arylen}, + {"isnull", json_isnull}, {NULL, NULL} }; int luaopen_json(lua_State *L) { lua_newtable(L); // library table lua_newtable(L); // ephemeron table to store the length of arrays (that may contain nil's) + lua_newtable(L); // ephemeron table to store a set of keys associated with JSON-null values lua_newtable(L); // meta table for ephemeron table lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); lua_setmetatable(L, -2); - luaL_setfuncs(L, json_module_functions, 1); + luaL_setfuncs(L, json_module_functions, 2); return 1; }