webmcp
changeset 169:681367a16657
json.array and json.object functions create a new container rather than marking a table
author | jbe |
---|---|
date | Fri Aug 01 05:12:21 2014 +0200 (2014-08-01) |
parents | e618ccd017a3 |
children | c055d6d64586 |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Fri Aug 01 02:48:18 2014 +0200 1.2 +++ b/libraries/json/json.c Fri Aug 01 05:12:21 2014 +0200 1.3 @@ -41,63 +41,67 @@ 1.4 return 1; 1.5 } 1.6 1.7 -// marks a Lua table as JSON object or JSON array: 1.8 -// (returns its modified argument or a new table if argument is nil) 1.9 -static int json_mark(lua_State *L, JSON_REGPOINTER mt) { 1.10 - // check if argument is nil 1.11 - if (lua_isnoneornil(L, 1)) { 1.12 - // create new table at stack position 1: 1.13 - lua_settop(L, 0); 1.14 - lua_newtable(L); 1.15 - // create shadow table (leaving previously created table on stack position 1): 1.16 - json_regfetch(L, shadowtbl); 1.17 - lua_pushvalue(L, 1); 1.18 - lua_newtable(L); 1.19 - lua_rawset(L, -3); 1.20 - } else { 1.21 - // require argument to be a table: 1.22 - luaL_checktype(L, 1, LUA_TTABLE); 1.23 - // push shadow table on top of stack: 1.24 +#define json_convert_source_idx 1 1.25 +#define json_convert_iterator_idx 2 1.26 +#define json_convert_output_idx 3 1.27 +#define json_convert_shadow_idx 4 1.28 + 1.29 +// converts a Lua table to a JSON object or JSON array: 1.30 +// (does never modify the argument, returns an empty object or array if argument is nil) 1.31 +static int json_convert(lua_State *L, int array) { 1.32 + lua_settop(L, 1); 1.33 + if (lua_isnoneornil(L, json_convert_source_idx)) { 1.34 json_regfetch(L, shadowtbl); 1.35 - lua_pushvalue(L, 1); 1.36 - lua_rawget(L, -2); 1.37 - // if shadow table does not exist: 1.38 - if (lua_isnil(L, -1)) { 1.39 - // create shadow table and leave it on top of stack: 1.40 - lua_newtable(L); 1.41 - lua_pushvalue(L, 1); 1.42 - lua_pushvalue(L, -2); 1.43 - lua_rawset(L, -5); 1.44 + lua_newtable(L); 1.45 + lua_pushvalue(L, -1); 1.46 + lua_newtable(L); 1.47 + lua_rawset(L, -4); 1.48 + } else { 1.49 + // push iterator function on stack position 2 if existent, 1.50 + // else push null for normal tables: 1.51 + if (lua_getmetatable(L, json_convert_source_idx)) { 1.52 + lua_getfield(L, -1, array ? "__ipairs" : "__pairs"); 1.53 + if (lua_isnil(L, -1)) luaL_checktype(L, 1, LUA_TTABLE); 1.54 + else if (lua_type(L, -1) != LUA_TFUNCTION) 1.55 + return luaL_error(L, "%s metamethod is not a function", array ? "__ipairs" : "__pairs"); 1.56 + lua_replace(L, -2); 1.57 + } else { 1.58 + lua_pushnil(L); 1.59 } 1.60 - // move elements from original table to shadow table (that's expected on top of stack): 1.61 - for(lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { 1.62 - lua_pushvalue(L, -2); 1.63 - lua_pushnil(L); 1.64 - lua_rawset(L, 1); 1.65 - lua_pushvalue(L, -2); 1.66 - lua_pushvalue(L, -2); 1.67 - lua_rawset(L, -5); 1.68 + // create table on stack position 3: 1.69 + lua_newtable(L); 1.70 + // create shadow table on stack position 4: 1.71 + json_regfetch(L, shadowtbl); 1.72 + lua_newtable(L); 1.73 + lua_pushvalue(L, json_convert_output_idx); 1.74 + lua_pushvalue(L, -2); 1.75 + lua_rawset(L, -4); 1.76 + lua_replace(L, -2); 1.77 + if (lua_isnil(L, json_convert_iterator_idx)) { 1.78 + for (lua_pushnil(L); lua_next(L, json_convert_source_idx); lua_pop(L, 1)) { 1.79 + lua_pushvalue(L, -2); 1.80 + lua_pushvalue(L, -2); 1.81 + lua_rawset(L, json_convert_shadow_idx); 1.82 + } 1.83 + } else { 1.84 + return luaL_error(L, "Using %s metamethod not implemented yet", array ? "__ipairs" : "__pairs"); 1.85 } 1.86 + lua_settop(L, json_convert_output_idx); 1.87 } 1.88 - // discard everything but table to return: 1.89 - lua_settop(L, 1); 1.90 // set metatable: 1.91 - json_regfetchpointer(L, mt); 1.92 - lua_setmetatable(L, 1); 1.93 + if (array) json_regfetch(L, arraymt); 1.94 + else json_regfetch(L, objectmt); 1.95 + lua_setmetatable(L, -2); 1.96 // return table: 1.97 return 1; 1.98 } 1.99 1.100 -// marks a table as JSON object: 1.101 -// (returns its modified argument or a new table if argument is nil) 1.102 static int json_object(lua_State *L) { 1.103 - return json_mark(L, json_regpointer(objectmt)); 1.104 + return json_convert(L, 0); 1.105 } 1.106 1.107 -// marks a table as JSON array: 1.108 -// (returns its modified argument or a new table if argument is nil) 1.109 static int json_array(lua_State *L) { 1.110 - return json_mark(L, json_regpointer(arraymt)); 1.111 + return json_convert(L, 1); 1.112 } 1.113 1.114 // internal states of JSON parser: