webmcp
changeset 123:402fce94f98c
Added function json.isnull(...) to JSON library
author | jbe |
---|---|
date | Sat Jul 26 05:27:42 2014 +0200 (2014-07-26) |
parents | ff39d4a310b9 |
children | ece4e6f683c9 |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Fri Jul 25 22:50:12 2014 +0200 1.2 +++ b/libraries/json/json.c Sat Jul 26 05:27:42 2014 +0200 1.3 @@ -3,6 +3,9 @@ 1.4 #include <stdlib.h> 1.5 #include <string.h> 1.6 1.7 +#define JSON_UPVAL_ARYLEN lua_upvalueindex(1) 1.8 +#define JSON_UPVAL_NULLS lua_upvalueindex(2) 1.9 + 1.10 #define JSON_VALUE 0 1.11 #define JSON_OBJECT_KEY 1 1.12 #define JSON_OBJECT_KEY_TERMINATOR 2 1.13 @@ -41,6 +44,10 @@ 1.14 goto json_import_syntax_error; 1.15 pos++; 1.16 lua_newtable(L); 1.17 + lua_newtable(L); // stores set of NULL values 1.18 + lua_pushvalue(L, -2); 1.19 + lua_pushvalue(L, -2); 1.20 + lua_rawset(L, JSON_UPVAL_NULLS); 1.21 mode = JSON_OBJECT_KEY; 1.22 level++; 1.23 goto json_import_loop; 1.24 @@ -49,6 +56,10 @@ 1.25 goto json_import_syntax_error; 1.26 pos++; 1.27 lua_newtable(L); 1.28 + lua_newtable(L); // stores set of NULL values 1.29 + lua_pushvalue(L, -2); 1.30 + lua_pushvalue(L, -2); 1.31 + lua_rawset(L, JSON_UPVAL_NULLS); 1.32 lua_pushinteger(L, 0); // length of array (since it may contain nil's) 1.33 mode = JSON_ARRAY_VALUE; 1.34 level++; 1.35 @@ -62,10 +73,11 @@ 1.36 goto json_import_syntax_error; 1.37 lua_pushvalue(L, -2); // use array table as key 1.38 lua_insert(L, -2); // use length of array as value 1.39 - lua_rawset(L, lua_upvalueindex(1)); // store length in ephemeron table 1.40 + lua_rawset(L, JSON_UPVAL_ARYLEN); // store length in ephemeron table 1.41 // leaves array table on top of stack 1.42 json_import_close: 1.43 pos++; 1.44 + lua_pop(L, 1); // pop table that stores set of NULL values 1.45 if (--level) { 1.46 if (lua_type(L, -2) == LUA_TNUMBER) { 1.47 mode = JSON_ARRAY_VALUE; 1.48 @@ -172,12 +184,22 @@ 1.49 mode = JSON_OBJECT_KEY_TERMINATOR; 1.50 goto json_import_loop; 1.51 case JSON_OBJECT_VALUE: 1.52 - lua_rawset(L, -3); 1.53 + if (lua_isnil(L, -1)) { 1.54 + lua_pushvalue(L, -2); 1.55 + lua_pushboolean(L, 1); 1.56 + lua_rawset(L, -5); 1.57 + } 1.58 + lua_rawset(L, -4); 1.59 mode = JSON_OBJECT_SEPARATOR; 1.60 goto json_import_loop; 1.61 case JSON_ARRAY_VALUE: 1.62 aryidx = lua_tointeger(L, -2) + 1; 1.63 - lua_rawseti(L, -3, aryidx); 1.64 + if (lua_isnil(L, -1)) { 1.65 + lua_pushinteger(L, aryidx); 1.66 + lua_pushboolean(L, 1); 1.67 + lua_rawset(L, -5); 1.68 + } 1.69 + lua_rawseti(L, -4, aryidx); 1.70 lua_pop(L, 1); 1.71 lua_pushinteger(L, aryidx); 1.72 mode = JSON_ARRAY_SEPARATOR; 1.73 @@ -194,24 +216,40 @@ 1.74 1.75 static int json_arylen(lua_State *L) { 1.76 lua_settop(L, 1); 1.77 - lua_rawget(L, lua_upvalueindex(1)); 1.78 + lua_rawget(L, JSON_UPVAL_ARYLEN); 1.79 + return 1; 1.80 +} 1.81 + 1.82 +static int json_isnull(lua_State *L) { 1.83 + lua_pushvalue(L, 1); 1.84 + lua_rawget(L, JSON_UPVAL_NULLS); 1.85 + if (lua_isnil(L, -1)) goto json_isnull_false; 1.86 + lua_pushvalue(L, 2); 1.87 + lua_rawget(L, -2); 1.88 + if (!lua_isnil(L, -1)) return 1; 1.89 +json_isnull_false: 1.90 + lua_pushboolean(L, 0); 1.91 return 1; 1.92 } 1.93 1.94 static const struct luaL_Reg json_module_functions[] = { 1.95 {"import", json_import}, 1.96 {"arylen", json_arylen}, 1.97 + {"isnull", json_isnull}, 1.98 {NULL, NULL} 1.99 }; 1.100 1.101 int luaopen_json(lua_State *L) { 1.102 lua_newtable(L); // library table 1.103 lua_newtable(L); // ephemeron table to store the length of arrays (that may contain nil's) 1.104 + lua_newtable(L); // ephemeron table to store a set of keys associated with JSON-null values 1.105 lua_newtable(L); // meta table for ephemeron table 1.106 lua_pushliteral(L, "__mode"); 1.107 lua_pushliteral(L, "k"); 1.108 lua_rawset(L, -3); 1.109 + lua_pushvalue(L, -1); 1.110 + lua_setmetatable(L, -3); 1.111 lua_setmetatable(L, -2); 1.112 - luaL_setfuncs(L, json_module_functions, 1); 1.113 + luaL_setfuncs(L, json_module_functions, 2); 1.114 return 1; 1.115 }