# HG changeset patch # User jbe # Date 1406741046 -7200 # Node ID 0690fe79b673129cc4b567a59c8bc0091b4df646 # Parent 6f723e60acdccc0e2bcc308ae3fc8138531c4222 Improved macros for handling Lua registry in JSON library diff -r 6f723e60acdc -r 0690fe79b673 libraries/json/json.c --- a/libraries/json/json.c Wed Jul 30 02:36:37 2014 +0200 +++ b/libraries/json/json.c Wed Jul 30 19:24:06 2014 +0200 @@ -3,20 +3,26 @@ #include #include +// maximum number of nested JSON values (objects and arrays): #define JSON_MAXDEPTH 100 -#define JSON_REGENT static char +// macros for usage of Lua registry: +#define JSON_REGENT char #define JSON_REGREF void * +#define json_regref(x) (&json_registry.x) +#define json_regfetchref(L, x) (lua_pushlightuserdata((L), (x)), lua_rawget((L), LUA_REGISTRYINDEX)) +#define json_regfetch(L, x) (json_regfetchref(L, json_regref(x))) +#define json_regstore(L, x) (lua_pushlightuserdata(L, json_regref(x)), lua_pushvalue(L, -2), lua_rawset(L, LUA_REGISTRYINDEX)); -JSON_REGENT json_nullmark; -JSON_REGENT json_shadowtbl; -JSON_REGENT json_unknownmt; -JSON_REGENT json_objectmt; -JSON_REGENT json_arraymt; - -#define json_regfetch(L, x) (lua_pushlightuserdata((L), &(x)), lua_rawget((L), LUA_REGISTRYINDEX)) - -#define json_regstore(L, x) (lua_pushlightuserdata(L, &(x)), lua_pushvalue(L, -2), lua_rawset(L, LUA_REGISTRYINDEX)); +// generate dummy memory addresses that represent Lua objects +// (via lightuserdata keys and LUA_REGISTRYINDEX): +static struct { + JSON_REGENT nullmark; + JSON_REGENT shadowtbl; + JSON_REGENT unknownmt; + JSON_REGENT objectmt; + JSON_REGENT arraymt; +} json_registry; // marks a table as JSON object or JSON array: // (returns its modified argument or a new table if argument is nil) @@ -26,13 +32,13 @@ lua_settop(L, 0); lua_newtable(L); // set shadow table: - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_newtable(L); lua_rawset(L, -3); } else { // check if shadow table already exists: - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, -2); if (lua_isnil(L, -1)) { @@ -54,7 +60,7 @@ // discard everything but table to return: lua_settop(L, 1); // set metatable: - json_regfetch(L, *mt); + json_regfetchref(L, mt); lua_setmetatable(L, 1); // return table: return 1; @@ -63,13 +69,13 @@ // marks a table as JSON object: // (returns its modified argument or a new table if argument is nil) static int json_object(lua_State *L) { - return json_mark(L, &json_objectmt); + return json_mark(L, json_regref(objectmt)); } // marks a table as JSON array: // (returns its modified argument or a new table if argument is nil) static int json_array(lua_State *L) { - return json_mark(L, &json_arraymt); + return json_mark(L, json_regref(arraymt)); } #define JSON_STATE_VALUE 0 @@ -100,13 +106,13 @@ // limit stack to 1 element: lua_settop(L, 1); // push json_objectmt on stack position 2: - json_regfetch(L, json_objectmt); + json_regfetch(L, objectmt); // push json_arraymt on stack position 3: - json_regfetch(L, json_arraymt); + json_regfetch(L, arraymt); // push json_shadowtbl on stack position 4: - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); // push json_nullmark on stack position 5: - json_regfetch(L, json_nullmark); + json_regfetch(L, nullmark); // require string as first argument: str = luaL_checklstring(L, 1, &total); // if string contains a NULL byte, this is a syntax error @@ -393,10 +399,10 @@ int stacktop; int idx = 2 + json_path_idxshift; // insert json_shadowtbl on stack at position 1: - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); lua_insert(L, 1); // insert json_nullmark on stack at position 2: - json_regfetch(L, json_nullmark); + json_regfetch(L, nullmark); lua_insert(L, 2); // store number of arguments: stacktop = lua_gettop(L); @@ -449,13 +455,13 @@ // otherwise, // check if metatable indicates "object" or "array": if (lua_getmetatable(L, -1)) { - json_regfetch(L, json_objectmt); + json_regfetch(L, objectmt); if (lua_rawequal(L, -2, -1)) { // return string "object": lua_pushliteral(L, "object"); return 1; } - json_regfetch(L, json_arraymt); + json_regfetch(L, arraymt); if (lua_rawequal(L, -3, -1)) { // return string "array": lua_pushliteral(L, "array"); @@ -504,13 +510,13 @@ // truncate stack to two elements: lua_settop(L, 2); // push json_unknownmt to stack position 3: - json_regfetch(L, json_unknownmt); + json_regfetch(L, unknownmt); // push json_objectmt to stack position 4: - json_regfetch(L, json_objectmt); + json_regfetch(L, objectmt); // push json_arraymt to stack position 5: - json_regfetch(L, json_arraymt); + json_regfetch(L, arraymt); // push json_shadowtbl to stack position 6: - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); // lua_getmetatable(L, 1); if ( @@ -530,14 +536,14 @@ lua_rawset(L, json_setnull_shadowtbl_idx); } lua_pushvalue(L, 2); - json_regfetch(L, json_nullmark); + json_regfetch(L, nullmark); lua_rawset(L, -3); return 0; } static int json_len(lua_State *L) { lua_settop(L, 1); - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, -2); lua_pushinteger(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1)); @@ -549,8 +555,8 @@ static int json_index(lua_State *L) { lua_settop(L, 2); - json_regfetch(L, json_nullmark); // on stack position 3 - json_regfetch(L, json_shadowtbl); + json_regfetch(L, nullmark); // on stack position 3 + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, json_index_shadowtbl_idx); if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); @@ -562,7 +568,7 @@ static int json_newindex(lua_State *L) { lua_settop(L, 3); - json_regfetch(L, json_shadowtbl); + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, -2); if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); @@ -577,8 +583,8 @@ static int json_pairs_iterfunc(lua_State *L) { lua_settop(L, 2); - json_regfetch(L, json_nullmark); // on stack position 3 - json_regfetch(L, json_shadowtbl); + json_regfetch(L, nullmark); // on stack position 3 + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, json_pairs_iterfunc_shadowtbl_idx); if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); @@ -604,8 +610,8 @@ static int json_ipairs_iterfunc(lua_State *L) { int idx; lua_settop(L, 2); - json_regfetch(L, json_nullmark); // on stack position 3 - json_regfetch(L, json_shadowtbl); + json_regfetch(L, nullmark); // on stack position 3 + json_regfetch(L, shadowtbl); idx = lua_tointeger(L, 2) + 1; lua_pushvalue(L, 1); lua_rawget(L, json_ipairs_iterfunc_shadowtbl_idx); @@ -650,15 +656,15 @@ lua_newtable(L); // library lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); - json_regstore(L, json_unknownmt); + json_regstore(L, unknownmt); lua_setfield(L, 1, "ambiguous_mt"); lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); - json_regstore(L, json_objectmt); + json_regstore(L, objectmt); lua_setfield(L, 1, "object_mt"); lua_newtable(L); luaL_setfuncs(L, json_metatable_functions, 0); - json_regstore(L, json_arraymt); + json_regstore(L, arraymt); lua_setfield(L, 1, "array_mt"); lua_newtable(L); // ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil lua_newtable(L); // metatable for ephemeron table @@ -666,9 +672,9 @@ lua_pushliteral(L, "k"); lua_rawset(L, -3); lua_setmetatable(L, -2); - json_regstore(L, json_shadowtbl); + json_regstore(L, shadowtbl); lua_newtable(L); - json_regstore(L, json_nullmark); + json_regstore(L, nullmark); lua_settop(L, 1); luaL_setfuncs(L, json_module_functions, 0); return 1;