# HG changeset patch # User jbe # Date 1406769484 -7200 # Node ID 185e944182cb488c9e482b4f08bb08af2f9d1d47 # Parent c8669dde9ce200c7b890083b6463c290dfebec53 Better C macros for null-marker in JSON library diff -r c8669dde9ce2 -r 185e944182cb libraries/json/json.c --- a/libraries/json/json.c Thu Jul 31 03:01:53 2014 +0200 +++ b/libraries/json/json.c Thu Jul 31 03:18:04 2014 +0200 @@ -14,21 +14,19 @@ // returning nil and an error string). #define JSON_MAXDEPTH 500 +// generate dummy memory addresses that represents null values: +char json_nullmark; +#define json_isnullmark(L, i) (lua_touserdata((L), (i)) == &json_nullmark) +#define json_pushnullmark(L) lua_pushlightuserdata((L), &json_nullmark) + // macros for usage of Lua registry: #define JSON_REGENT char #define JSON_REGPOINTER void * -#define json_pushlightref(L, x) lua_pushlightuserdata((L), &json_reference.x) -#define json_islightref(L, i, x) (lua_touserdata((L), (i)) == &json_reference.x) #define json_regpointer(x) (&json_registry.x) #define json_regfetchpointer(L, x) lua_rawgetp((L), LUA_REGISTRYINDEX, (x)) #define json_regfetch(L, x) json_regfetchpointer(L, json_regpointer(x)) #define json_regstore(L, x) lua_rawsetp(L, LUA_REGISTRYINDEX, json_regpointer(x)) -// generate dummy memory addresses that represent non-modifiable lightuserdata (dummy) objects: -static struct { - JSON_REGENT nullmark; // magic value to indicate JSON null value in shadow table -} json_reference; - // generate dummy memory addresses that represent Lua objects // via lightuserdata keys and LUA_REGISTRYINDEX: static struct { @@ -109,7 +107,6 @@ #define json_import_objectmt_idx 2 #define json_import_arraymt_idx 3 #define json_import_shadowtbl_idx 4 -#define json_import_nullmark_idx 5 // decodes a JSON document: static int json_import(lua_State *L) { @@ -131,8 +128,6 @@ json_regfetch(L, arraymt); // push shadowtbl onto stack position 4: json_regfetch(L, shadowtbl); - // push nullmark onto stack position 5: - json_pushlightref(L, nullmark); // require string as first argument: str = luaL_checklstring(L, 1, &total); // if string contains a NULL byte, this is a syntax error @@ -386,7 +381,7 @@ if (level) { // if sub-level, // push special null-marker onto stack: - lua_pushvalue(L, json_import_nullmark_idx); + json_pushnullmark(L); } else { // if top-level, // push nil onto stack: @@ -446,10 +441,9 @@ // special Lua stack indicies for json_path function: #define json_path_shadowtbl_idx 1 -#define json_path_nullmark_idx 2 // stack offset of arguments to json_path function: -#define json_path_idxshift 2 +#define json_path_idxshift 1 // gets a value or its type from a JSON document (passed as first argument) // using a path (passed as variable number of keys after first argument): @@ -459,9 +453,6 @@ // insert shadowtbl into stack at position 1 (shifting the arguments): json_regfetch(L, shadowtbl); lua_insert(L, 1); - // insert nullmark into stack at position 2 (shifting the arguments): - json_pushlightref(L, nullmark); - lua_insert(L, 2); // store stack index of top of stack: stacktop = lua_gettop(L); // use first argument as "current value" (stored on top of stack): @@ -501,11 +492,11 @@ if (!type_mode) { // if a value (and not its type) was requested, // check if value is the null-marker, and store nil on top of Lua stack in that case: - if (lua_rawequal(L, -1, json_path_nullmark_idx)) lua_pushnil(L); + if (json_isnullmark(L, -1)) lua_pushnil(L); } else { // if the type was requested, // check if value is the null-marker: - if (lua_rawequal(L, -1, json_path_nullmark_idx)) { + if (json_isnullmark(L, -1)) { // if yes, store string "null" on top of Lua stack: lua_pushliteral(L, "null"); } else { @@ -608,7 +599,7 @@ } // push key (second argument) and null-marker after shadow table onto stack: lua_pushvalue(L, 2); - json_pushlightref(L, nullmark); + json_pushnullmark(L); // store key and null-marker in shadow table: lua_rawset(L, -3); // return nothing: @@ -628,27 +619,20 @@ return 1; } -// special Lua stack indicies for json_index function: -#define json_index_nullmark_idx 3 -#define json_index_shadowtbl_idx 4 - static int json_index(lua_State *L) { // stack shall contain two function arguments: lua_settop(L, 2); - // push nullmark onto stack position 3: - json_pushlightref(L, nullmark); - // push shadowtbl onto stack position 4: + // get corresponding shadow table for first argument: json_regfetch(L, shadowtbl); - // get corresponding shadow table for first argument: lua_pushvalue(L, 1); - lua_rawget(L, json_index_shadowtbl_idx); + lua_rawget(L, -2); // throw error if no shadow table was found: if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); // use key passed as second argument to lookup value in shadow table: lua_pushvalue(L, 2); lua_rawget(L, -2); // if value is null-marker, then push nil onto stack: - if (lua_rawequal(L, -1, json_index_nullmark_idx)) lua_pushnil(L); + if (json_isnullmark(L, -1)) lua_pushnil(L); // return either looked up value, or nil return 1; } @@ -671,20 +655,13 @@ return 0; } -// special Lua stack indicies for json_pairs_iterfunc function: -#define json_pairs_iterfunc_nullmark_idx 3 -#define json_pairs_iterfunc_shadowtbl_idx 4 - static int json_pairs_iterfunc(lua_State *L) { // stack shall contain two function arguments: lua_settop(L, 2); - // push nullmark onto stack position 3: - json_pushlightref(L, nullmark); - // push shadowtbl onto stack position 4: + // get corresponding shadow table for first argument: json_regfetch(L, shadowtbl); - // get corresponding shadow table for first argument: lua_pushvalue(L, 1); - lua_rawget(L, json_pairs_iterfunc_shadowtbl_idx); + lua_rawget(L, -2); // throw error if no shadow table was found: if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); // get next key value pair from shadow table (using previous key from argument 2) @@ -692,7 +669,7 @@ lua_pushvalue(L, 2); if (!lua_next(L, -2)) return 0; // replace null-marker with nil: - if (lua_rawequal(L, -1, json_pairs_iterfunc_nullmark_idx)) { + if (json_isnullmark(L, -1)) { lua_pop(L, 1); lua_pushnil(L); } @@ -710,23 +687,16 @@ return 3; } -// special Lua stack indicies for json_ipairs_iterfunc function: -#define json_ipairs_iterfunc_nullmark_idx 3 -#define json_ipairs_iterfunc_shadowtbl_idx 4 - static int json_ipairs_iterfunc(lua_State *L) { lua_Integer idx; // stack shall contain two function arguments: lua_settop(L, 2); - // push nullmark onto stack position 3: - json_pushlightref(L, nullmark); - // push shadowtbl onto stack position 4: - json_regfetch(L, shadowtbl); // calculate new index by incrementing second argument: idx = lua_tointeger(L, 2) + 1; // get corresponding shadow table for first argument: + json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); - lua_rawget(L, json_ipairs_iterfunc_shadowtbl_idx); + lua_rawget(L, -2); // throw error if no shadow table was found: if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); // do integer lookup in shadow table: @@ -737,7 +707,7 @@ // either the looked up value if it is not equal to the null-marker // or nil instead of null-marker: lua_pushinteger(L, idx); - if (lua_rawequal(L, -2, json_ipairs_iterfunc_nullmark_idx)) lua_pushnil(L); + if (json_isnullmark(L, -2)) lua_pushnil(L); else lua_pushvalue(L, -2); return 2; } @@ -852,7 +822,7 @@ lua_call(L, 1, 1); luaL_addvalue(&buf); luaL_addchar(&buf, ':'); - if (json_islightref(L, 3, nullmark)) { + if (json_isnullmark(L, 3)) { luaL_addstring(&buf, "null"); } else { lua_pushcfunction(L, json_export);