webmcp

changeset 145:0edc2f05c66a

Use lightuserdata directly to store JSON null values in JSON library
author jbe
date Wed Jul 30 19:59:11 2014 +0200 (2014-07-30)
parents 0690fe79b673
children 7912a05ebc3f
files libraries/json/json.c
line diff
     1.1 --- a/libraries/json/json.c	Wed Jul 30 19:24:06 2014 +0200
     1.2 +++ b/libraries/json/json.c	Wed Jul 30 19:59:11 2014 +0200
     1.3 @@ -8,46 +8,56 @@
     1.4  
     1.5  // macros for usage of Lua registry:
     1.6  #define JSON_REGENT char
     1.7 -#define JSON_REGREF void *
     1.8 -#define json_regref(x) (&json_registry.x)
     1.9 -#define json_regfetchref(L, x) (lua_pushlightuserdata((L), (x)), lua_rawget((L), LUA_REGISTRYINDEX))
    1.10 -#define json_regfetch(L, x) (json_regfetchref(L, json_regref(x)))
    1.11 -#define json_regstore(L, x) (lua_pushlightuserdata(L, json_regref(x)), lua_pushvalue(L, -2), lua_rawset(L, LUA_REGISTRYINDEX));
    1.12 +#define JSON_REGPOINTER void *
    1.13 +#define json_pushlightref(L, x) (lua_pushlightuserdata((L), &json_reference.x))
    1.14 +#define json_regpointer(x) (&json_registry.x)
    1.15 +#define json_regfetchpointer(L, x) (lua_pushlightuserdata((L), (x)), lua_rawget((L), LUA_REGISTRYINDEX))
    1.16 +#define json_regfetch(L, x) (json_regfetchpointer(L, json_regpointer(x)))
    1.17 +#define json_regstore(L, x) (lua_pushlightuserdata(L, json_regpointer(x)), lua_pushvalue(L, -2), lua_rawset(L, LUA_REGISTRYINDEX));
    1.18 +
    1.19 +// generate dummy memory addresses that represent Lua objects
    1.20 +// directly via lightuserdata values (not using the Lua registry):
    1.21 +static struct {
    1.22 +  JSON_REGENT nullmark;  // magic value to indicate JSON null value
    1.23 +} json_reference;
    1.24 +
    1.25  
    1.26  // generate dummy memory addresses that represent Lua objects
    1.27 -// (via lightuserdata keys and LUA_REGISTRYINDEX):
    1.28 +// via lightuserdata keys and LUA_REGISTRYINDEX:
    1.29  static struct {
    1.30 -  JSON_REGENT nullmark;
    1.31 -  JSON_REGENT shadowtbl;
    1.32 -  JSON_REGENT unknownmt;
    1.33 -  JSON_REGENT objectmt;
    1.34 -  JSON_REGENT arraymt;
    1.35 +  JSON_REGENT shadowtbl;  // ephemeron table that maps tables to their corresponding shadow table
    1.36 +  JSON_REGENT unknownmt;  // metatable for tables that may be either JSON objects or JSON arrays
    1.37 +  JSON_REGENT objectmt;   // metatable for JSON objects
    1.38 +  JSON_REGENT arraymt;    // metatable for JSON arrays
    1.39  } json_registry;
    1.40  
    1.41 -// marks a table as JSON object or JSON array:
    1.42 +// marks a Lua table as JSON object or JSON array:
    1.43  // (returns its modified argument or a new table if argument is nil)
    1.44 -static int json_mark(lua_State *L, JSON_REGREF mt) {
    1.45 -  // if argument is nil, then create new table:
    1.46 +static int json_mark(lua_State *L, JSON_REGPOINTER mt) {
    1.47 +  // check if argument is nil
    1.48    if (lua_isnoneornil(L, 1)) {
    1.49 +    // create new table at stack position 1:
    1.50      lua_settop(L, 0);
    1.51      lua_newtable(L);
    1.52 -    // set shadow table:
    1.53 +    // create shadow table (leaving previously created table on stack position 1):
    1.54      json_regfetch(L, shadowtbl);
    1.55      lua_pushvalue(L, 1);
    1.56      lua_newtable(L);
    1.57      lua_rawset(L, -3);
    1.58    } else {
    1.59 -    // check if shadow table already exists:
    1.60 +    // push shadow table on top of stack:
    1.61      json_regfetch(L, shadowtbl);
    1.62      lua_pushvalue(L, 1);
    1.63      lua_rawget(L, -2);
    1.64 +    // if shadow table does not exist:
    1.65      if (lua_isnil(L, -1)) {
    1.66 -      // set shadow table and leave it on top of stack:
    1.67 +      // create shadow table and leave it on top of stack:
    1.68        lua_newtable(L);
    1.69        lua_pushvalue(L, 1);
    1.70        lua_pushvalue(L, -2);
    1.71        lua_rawset(L, -5);
    1.72      }
    1.73 +    // move elements from original table to shadow table (that's expected on top of stack):
    1.74      for(lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
    1.75        lua_pushvalue(L, -2);
    1.76        lua_pushnil(L);
    1.77 @@ -60,7 +70,7 @@
    1.78    // discard everything but table to return:
    1.79    lua_settop(L, 1);
    1.80    // set metatable:
    1.81 -  json_regfetchref(L, mt);
    1.82 +  json_regfetchpointer(L, mt);
    1.83    lua_setmetatable(L, 1);
    1.84    // return table:
    1.85    return 1;
    1.86 @@ -69,15 +79,16 @@
    1.87  // marks a table as JSON object:
    1.88  // (returns its modified argument or a new table if argument is nil)
    1.89  static int json_object(lua_State *L) {
    1.90 -  return json_mark(L, json_regref(objectmt));
    1.91 +  return json_mark(L, json_regpointer(objectmt));
    1.92  }
    1.93  
    1.94  // marks a table as JSON array:
    1.95  // (returns its modified argument or a new table if argument is nil)
    1.96  static int json_array(lua_State *L) {
    1.97 -  return json_mark(L, json_regref(arraymt));
    1.98 +  return json_mark(L, json_regpointer(arraymt));
    1.99  }
   1.100  
   1.101 +// internal states of JSON parser:
   1.102  #define JSON_STATE_VALUE 0
   1.103  #define JSON_STATE_OBJECT_KEY 1
   1.104  #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
   1.105 @@ -87,6 +98,7 @@
   1.106  #define JSON_STATE_ARRAY_SEPARATOR 6
   1.107  #define JSON_STATE_END 7
   1.108  
   1.109 +// special Lua stack indicies for json_import function:
   1.110  #define json_import_objectmt_idx 2
   1.111  #define json_import_arraymt_idx 3
   1.112  #define json_import_shadowtbl_idx 4
   1.113 @@ -98,21 +110,21 @@
   1.114    size_t total;      // total length of string to parse
   1.115    size_t pos = 0;    // current position in string to parse
   1.116    size_t level = 0;  // nested levels of objects/arrays currently being processed
   1.117 -  int mode = JSON_STATE_VALUE;  // state of parser
   1.118 +  int mode = JSON_STATE_VALUE;  // state of parser (i.e. "what's expected next?")
   1.119    char c;              // variable to store a single character to be processed
   1.120 -  luaL_Buffer luabuf;  // Lua buffer to decode (possibly escaped) strings
   1.121 -  char *cbuf;          // C buffer to decode (possibly escaped) strings
   1.122 +  luaL_Buffer luabuf;  // Lua buffer to decode JSON string values
   1.123 +  char *cbuf;          // C buffer to decode JSON string values
   1.124    size_t writepos;     // write position of decoded strings in C buffer
   1.125 -  // limit stack to 1 element:
   1.126 +  // stack shall only contain one function argument:
   1.127    lua_settop(L, 1);
   1.128 -  // push json_objectmt on stack position 2:
   1.129 +  // push objectmt on stack position 2:
   1.130    json_regfetch(L, objectmt);
   1.131 -  // push json_arraymt on stack position 3:
   1.132 +  // push arraymt on stack position 3:
   1.133    json_regfetch(L, arraymt);
   1.134 -  // push json_shadowtbl on stack position 4:
   1.135 +  // push shadowtbl on stack position 4:
   1.136    json_regfetch(L, shadowtbl);
   1.137 -  // push json_nullmark on stack position 5:
   1.138 -  json_regfetch(L, nullmark);
   1.139 +  // push nullmark on stack position 5:
   1.140 +  json_pushlightref(L, nullmark);
   1.141    // require string as first argument:
   1.142    str = luaL_checklstring(L, 1, &total);
   1.143    // if string contains a NULL byte, this is a syntax error
   1.144 @@ -402,7 +414,7 @@
   1.145    json_regfetch(L, shadowtbl);
   1.146    lua_insert(L, 1);
   1.147    // insert json_nullmark on stack at position 2:
   1.148 -  json_regfetch(L, nullmark);
   1.149 +  json_pushlightref(L, nullmark);
   1.150    lua_insert(L, 2);
   1.151    // store number of arguments:
   1.152    stacktop = lua_gettop(L);
   1.153 @@ -536,7 +548,7 @@
   1.154      lua_rawset(L, json_setnull_shadowtbl_idx);
   1.155    }
   1.156    lua_pushvalue(L, 2);
   1.157 -  json_regfetch(L, nullmark);
   1.158 +  json_pushlightref(L, nullmark);
   1.159    lua_rawset(L, -3);
   1.160    return 0;
   1.161  }
   1.162 @@ -555,7 +567,7 @@
   1.163  
   1.164  static int json_index(lua_State *L) {
   1.165    lua_settop(L, 2);
   1.166 -  json_regfetch(L, nullmark);  // on stack position 3
   1.167 +  json_pushlightref(L, nullmark);  // on stack position 3
   1.168    json_regfetch(L, shadowtbl);
   1.169    lua_pushvalue(L, 1);
   1.170    lua_rawget(L, json_index_shadowtbl_idx);
   1.171 @@ -583,7 +595,7 @@
   1.172  
   1.173  static int json_pairs_iterfunc(lua_State *L) {
   1.174    lua_settop(L, 2);
   1.175 -  json_regfetch(L, nullmark);  // on stack position 3
   1.176 +  json_pushlightref(L, nullmark);  // on stack position 3
   1.177    json_regfetch(L, shadowtbl);
   1.178    lua_pushvalue(L, 1);
   1.179    lua_rawget(L, json_pairs_iterfunc_shadowtbl_idx);
   1.180 @@ -610,7 +622,7 @@
   1.181  static int json_ipairs_iterfunc(lua_State *L) {
   1.182    int idx;
   1.183    lua_settop(L, 2);
   1.184 -  json_regfetch(L, nullmark);  // on stack position 3
   1.185 +  json_pushlightref(L, nullmark);  // on stack position 3
   1.186    json_regfetch(L, shadowtbl);
   1.187    idx = lua_tointeger(L, 2) + 1;
   1.188    lua_pushvalue(L, 1);
   1.189 @@ -673,8 +685,6 @@
   1.190    lua_rawset(L, -3);
   1.191    lua_setmetatable(L, -2);
   1.192    json_regstore(L, shadowtbl);
   1.193 -  lua_newtable(L);
   1.194 -  json_regstore(L, nullmark);
   1.195    lua_settop(L, 1);
   1.196    luaL_setfuncs(L, json_module_functions, 0);
   1.197    return 1;

Impressum / About Us