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);

Impressum / About Us