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:

Impressum / About Us