webmcp
changeset 137:f490b78827d6
More documentation in JSON library; Implement json.isnull(...) through json.type(...) == "null"
author | jbe |
---|---|
date | Mon Jul 28 19:04:32 2014 +0200 (2014-07-28) |
parents | 3cf5fcf2bd5f |
children | 8a533f370038 |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Mon Jul 28 17:16:34 2014 +0200 1.2 +++ b/libraries/json/json.c Mon Jul 28 19:04:32 2014 +0200 1.3 @@ -3,12 +3,13 @@ 1.4 #include <stdlib.h> 1.5 #include <string.h> 1.6 1.7 -#define JSON_UPVAL_NULLMARK lua_upvalueindex(1) 1.8 -#define JSON_UPVAL_SHADOWTBL lua_upvalueindex(2) 1.9 -#define JSON_UPVAL_TYPES lua_upvalueindex(3) 1.10 -#define JSON_UPVAL_METATABLE lua_upvalueindex(4) 1.11 -#define JSON_UPVAL_PAIRS_ITERFUNC lua_upvalueindex(5) 1.12 -#define JSON_UPVAL_IPAIRS_ITERFUNC lua_upvalueindex(6) 1.13 +#define JSON_UPVAL_LIBRARY lua_upvalueindex(1) 1.14 +#define JSON_UPVAL_NULLMARK lua_upvalueindex(2) 1.15 +#define JSON_UPVAL_SHADOWTBL lua_upvalueindex(3) 1.16 +#define JSON_UPVAL_TYPES lua_upvalueindex(4) 1.17 +#define JSON_UPVAL_METATABLE lua_upvalueindex(5) 1.18 +#define JSON_UPVAL_PAIRS_ITERFUNC lua_upvalueindex(6) 1.19 +#define JSON_UPVAL_IPAIRS_ITERFUNC lua_upvalueindex(7) 1.20 1.21 // marks a table as JSON object or JSON array: 1.22 // (returns its modified argument or a new table if argument is nil) 1.23 @@ -347,68 +348,93 @@ 1.24 return 2; 1.25 } 1.26 1.27 -#define JSON_PATH_GET 1 1.28 -#define JSON_PATH_TYPE 2 1.29 -#define JSON_PATH_ISNULL 3 1.30 - 1.31 -// gets a value, its type, or information 1.32 -static int json_path(lua_State *L, int mode) { 1.33 +// gets a value or its type from a JSON document (first argument) 1.34 +// optionally using a path (variable number of keys after first argument): 1.35 +static int json_path(lua_State *L, int type_mode) { 1.36 int argc; 1.37 int idx = 2; 1.38 + // store number of arguments: 1.39 argc = lua_gettop(L); 1.40 + // follow path, starting with first argument as "current value": 1.41 lua_pushvalue(L, 1); 1.42 + // process each "path key": 1.43 while (idx <= argc) { 1.44 - if (lua_isnil(L, -1)) { 1.45 - if (mode == JSON_PATH_ISNULL) lua_pushboolean(L, 0); 1.46 - return 1; 1.47 - } 1.48 + // if "current value" is nil, then the path cannot be walked and nil is returned: 1.49 + if (lua_isnil(L, -1)) return 1; 1.50 + // try to get shadow table of "current value": 1.51 lua_pushvalue(L, -1); 1.52 lua_rawget(L, JSON_UPVAL_SHADOWTBL); 1.53 if (lua_isnil(L, -1)) { 1.54 + // if no shadow table is found, 1.55 + // drop nil from stack: 1.56 lua_pop(L, 1); 1.57 if (lua_type(L, -1) == LUA_TTABLE) { 1.58 + // if "current value" is a table, 1.59 + // get "next value" using the "path key": 1.60 lua_pushvalue(L, idx++); 1.61 lua_gettable(L, -2); 1.62 } else { 1.63 + // if "current value" is not a table, 1.64 + // then the path cannot be walked and nil is returned: 1.65 lua_pushnil(L); 1.66 + return 1; 1.67 } 1.68 } else { 1.69 + // if a shadow table is found, 1.70 + // set "current value" to its shadow table: 1.71 lua_replace(L, -2); 1.72 + // get "next value" using the "path key": 1.73 lua_pushvalue(L, idx++); 1.74 lua_rawget(L, -2); 1.75 } 1.76 + // the "next value" replaces the "current value": 1.77 lua_replace(L, -2); 1.78 } 1.79 - switch (mode) { 1.80 - case JSON_PATH_GET: 1.81 + if (!type_mode) { 1.82 + // if a value (and not its type) was requested, 1.83 + // check if value is the null-marker, and store nil on top of Lua stack in that case: 1.84 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) lua_pushnil(L); 1.85 - return 1; 1.86 - case JSON_PATH_TYPE: 1.87 + } else { 1.88 + // if the type was requested, 1.89 + // check if value is the null-marker: 1.90 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) { 1.91 + // if yes, store string "null" on top of Lua stack: 1.92 lua_pushliteral(L, "null"); 1.93 - return 1; 1.94 + } else { 1.95 + // otherwise, 1.96 + // try to read type ("object" or "array") from internal type table: 1.97 + lua_pushvalue(L, -1); 1.98 + lua_rawget(L, JSON_UPVAL_TYPES); 1.99 + // if no entry is found in the internal type table, get the Lua type: 1.100 + if (lua_isnil(L, -1)) lua_pushstring(L, lua_typename(L, lua_type(L, -2))); 1.101 } 1.102 - lua_pushvalue(L, -1); 1.103 - lua_rawget(L, JSON_UPVAL_TYPES); 1.104 - if (lua_isnil(L, -1)) lua_pushstring(L, lua_typename(L, lua_type(L, -2))); 1.105 - return 1; 1.106 - case JSON_PATH_ISNULL: 1.107 - lua_pushboolean(L, lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)); 1.108 - return 1; 1.109 } 1.110 - return 0; 1.111 + // return the top most value on the Lua stack: 1.112 + return 1; 1.113 } 1.114 1.115 +// gets a value from a JSON document (first argument) 1.116 +// optionally using a path (variable number of keys after first argument): 1.117 static int json_get(lua_State *L) { 1.118 - return json_path(L, JSON_PATH_GET); 1.119 + return json_path(L, 0); 1.120 } 1.121 1.122 +// gets a value's type from a JSON document (first argument) 1.123 +// optionally using a path (variable number of keys after first argument): 1.124 static int json_type(lua_State *L) { 1.125 - return json_path(L, JSON_PATH_TYPE); 1.126 + return json_path(L, 1); 1.127 } 1.128 1.129 +// checks if a value in a JSON document (first argument) is null: 1.130 static int json_isnull(lua_State *L) { 1.131 - return json_path(L, JSON_PATH_ISNULL); 1.132 + const char *jsontype; 1.133 + lua_getfield(L, JSON_UPVAL_LIBRARY, "type"); 1.134 + lua_insert(L, 1); 1.135 + lua_call(L, lua_gettop(L) - 1, 1); 1.136 + jsontype = lua_tostring(L, -1); 1.137 + if (jsontype && !strcmp(jsontype, "null")) lua_pushboolean(L, 1); 1.138 + else lua_pushboolean(L, 0); 1.139 + return 1; 1.140 } 1.141 1.142 static int json_setnull(lua_State *L) { 1.143 @@ -524,37 +550,41 @@ 1.144 1.145 int luaopen_json(lua_State *L) { 1.146 lua_settop(L, 0); 1.147 - lua_newtable(L); // 1: library table on stack position 1.148 - lua_newtable(L); // 2: table used as JSON NULL value in internal shadow tables 1.149 - lua_newtable(L); // 3: ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil 1.150 - lua_newtable(L); // 4: ephemeron table to store the type of the JSON object/array 1.151 - lua_newtable(L); // 5: metatable for ephemeron tables 1.152 + lua_newtable(L); // 1: library table on stack position 1.153 + lua_pushvalue(L, 1); // 2: copy of library table 1.154 + lua_newtable(L); // 3: table used as JSON NULL value in internal shadow tables 1.155 + lua_newtable(L); // 4: ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil 1.156 + lua_newtable(L); // 5: ephemeron table to store the type of the JSON object/array 1.157 + lua_newtable(L); // 6: metatable for ephemeron tables 1.158 lua_pushliteral(L, "__mode"); 1.159 lua_pushliteral(L, "k"); 1.160 - lua_rawset(L, 5); 1.161 - lua_pushvalue(L, 5); // 6: cloned metatable reference 1.162 - lua_setmetatable(L, 3); 1.163 + lua_rawset(L, 6); 1.164 + lua_pushvalue(L, 6); // 7: cloned metatable reference 1.165 lua_setmetatable(L, 4); 1.166 - lua_newtable(L); // 5: metatable for JSON objects and JSON arrays 1.167 + lua_setmetatable(L, 5); 1.168 + lua_newtable(L); // 6: metatable for JSON objects and JSON arrays 1.169 lua_pushvalue(L, 2); 1.170 lua_pushvalue(L, 3); 1.171 lua_pushvalue(L, 4); 1.172 lua_pushvalue(L, 5); 1.173 - lua_pushcclosure(L, json_pairs_iterfunc, 4); // 6: iteration function for pairs 1.174 + lua_pushvalue(L, 6); 1.175 + lua_pushcclosure(L, json_pairs_iterfunc, 5); // 7: iteration function for pairs 1.176 lua_pushvalue(L, 2); 1.177 lua_pushvalue(L, 3); 1.178 lua_pushvalue(L, 4); 1.179 lua_pushvalue(L, 5); 1.180 - lua_pushcclosure(L, json_ipairs_iterfunc, 4); // 7: iteration function for ipairs 1.181 - lua_pushvalue(L, 5); 1.182 + lua_pushvalue(L, 6); 1.183 + lua_pushcclosure(L, json_ipairs_iterfunc, 5); // 8: iteration function for ipairs 1.184 + lua_pushvalue(L, 6); 1.185 lua_pushvalue(L, 2); 1.186 lua_pushvalue(L, 3); 1.187 lua_pushvalue(L, 4); 1.188 lua_pushvalue(L, 5); 1.189 lua_pushvalue(L, 6); 1.190 lua_pushvalue(L, 7); 1.191 - luaL_setfuncs(L, json_metatable_functions, 6); 1.192 + lua_pushvalue(L, 8); 1.193 + luaL_setfuncs(L, json_metatable_functions, 7); 1.194 lua_setfield(L, 1, "metatable"); 1.195 - luaL_setfuncs(L, json_module_functions, 6); 1.196 + luaL_setfuncs(L, json_module_functions, 7); 1.197 return 1; 1.198 }