webmcp
changeset 172:a83164390355
Allow json.object and json.array functions to convert any Lua value using __pairs and __ipairs metamethods
author | jbe |
---|---|
date | Fri Aug 01 17:11:59 2014 +0200 (2014-08-01) |
parents | ce208edffcc9 |
children | f417c4b607ed |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Fri Aug 01 16:40:10 2014 +0200 1.2 +++ b/libraries/json/json.c Fri Aug 01 17:11:59 2014 +0200 1.3 @@ -45,6 +45,8 @@ 1.4 #define json_convert_iterator_idx 2 1.5 #define json_convert_output_idx 3 1.6 #define json_convert_shadow_idx 4 1.7 +#define json_convert_iterfun_idx 5 1.8 +#define json_convert_itertbl_idx 6 1.9 1.10 // converts a Lua table to a JSON object or JSON array: 1.11 // (does never modify the argument, returns an empty object or array if argument is nil) 1.12 @@ -112,8 +114,26 @@ 1.13 } 1.14 } 1.15 } else { 1.16 - // TODO: implement conversion using iterator metamethods 1.17 - return luaL_error(L, "Using %s metamethod not implemented yet", array ? "__ipairs" : "__pairs"); 1.18 + // if there is an iterator function, 1.19 + // call iterator function with source value (first argument) 1.20 + // and store 3 result values on stack positions 5 through 7: 1.21 + lua_pushvalue(L, json_convert_iterator_idx); 1.22 + lua_pushvalue(L, 1); 1.23 + lua_call(L, 1, 3); 1.24 + while (1) { 1.25 + lua_pushvalue(L, json_convert_iterfun_idx); 1.26 + lua_pushvalue(L, json_convert_itertbl_idx); 1.27 + lua_pushvalue(L, -3); 1.28 + lua_remove(L, -4); 1.29 + lua_call(L, 2, 2); 1.30 + if (lua_isnil(L, -2)) break; 1.31 + if (lua_type(L, -2) == (array ? LUA_TNUMBER : LUA_TSTRING)) { 1.32 + lua_pushvalue(L, -2); 1.33 + lua_pushvalue(L, -2); 1.34 + lua_rawset(L, json_convert_shadow_idx); 1.35 + } 1.36 + lua_pop(L, 1); 1.37 + } 1.38 } 1.39 // let result table be on top of stack: 1.40 lua_settop(L, json_convert_output_idx); 1.41 @@ -740,6 +760,8 @@ 1.42 // returns a triple such that 'for key, value in pairs(obj) do ... end' 1.43 // iterates through all key value pairs (including JSON null keys represented as Lua nil): 1.44 static int json_pairs(lua_State *L) { 1.45 + // require one argument to function 1.46 + luaL_checkany(L, 1); 1.47 // return triple of function json_pairs_iterfunc, first argument, and nil: 1.48 lua_pushcfunction(L, json_pairs_iterfunc); 1.49 lua_pushvalue(L, 1); 1.50 @@ -775,6 +797,8 @@ 1.51 // returns a triple such that 'for idx, value in ipairs(ary) do ... end' 1.52 // iterates through all values (including JSON null represented as Lua nil): 1.53 static int json_ipairs(lua_State *L) { 1.54 + // require one argument to function 1.55 + luaL_checkany(L, 1); 1.56 // return triple of function json_ipairs_iterfunc, first argument, and zero: 1.57 lua_pushcfunction(L, json_ipairs_iterfunc); 1.58 lua_pushvalue(L, 1);