# HG changeset patch # User jbe # Date 1406751574 -7200 # Node ID da5ab2c226dc46919e2da1249c73d9cf579a1994 # Parent 7912a05ebc3f4d874acc43381902123add114c37 Fixes and documentation in json_setnull and json_length functions of JSON library diff -r 7912a05ebc3f -r da5ab2c226dc libraries/json/json.c --- a/libraries/json/json.c Wed Jul 30 20:54:42 2014 +0200 +++ b/libraries/json/json.c Wed Jul 30 22:19:34 2014 +0200 @@ -114,15 +114,15 @@ luaL_Buffer luabuf; // Lua buffer to decode JSON string values char *cbuf; // C buffer to decode JSON string values size_t writepos; // write position of decoded strings in C buffer - // stack shall only contain one function argument: + // stack shall contain one function argument: lua_settop(L, 1); - // push objectmt on stack position 2: + // push objectmt onto stack position 2: json_regfetch(L, objectmt); - // push arraymt on stack position 3: + // push arraymt onto stack position 3: json_regfetch(L, arraymt); - // push shadowtbl on stack position 4: + // push shadowtbl onto stack position 4: json_regfetch(L, shadowtbl); - // push nullmark on stack position 5: + // push nullmark onto stack position 5: json_pushlightref(L, nullmark); // require string as first argument: str = luaL_checklstring(L, 1, &total); @@ -363,17 +363,17 @@ } else if (!strncmp(str+pos, "true", 4)) { // consume 4 input characters for "true": pos += 4; - // put Lua true value on stack: + // put Lua true value onto stack: lua_pushboolean(L, 1); } else if (!strncmp(str+pos, "false", 5)) { // consume 5 input characters for "false": pos += 5; - // put Lua false value on stack: + // put Lua false value onto stack: lua_pushboolean(L, 0); } else if (!strncmp(str+pos, "null", 4)) { // consume 4 input characters for "null": pos += 4; - // put special null-marker on stack: + // put special null-marker onto stack: lua_pushvalue(L, json_import_nullmark_idx); } else { // all other cases are a syntax error: @@ -427,14 +427,14 @@ #define json_path_idxshift 2 // gets a value or its type from a JSON document (passed as first argument) -// optionally using a path (passed as variable number of keys after first argument): +// using a path (passed as variable number of keys after first argument): static int json_path(lua_State *L, int type_mode) { int stacktop; // stack index of top of stack (after shifting) int idx = 2 + json_path_idxshift; // stack index of current argument to process - // insert json_shadowtbl on stack at position 1 (shifting the arguments): + // insert json_shadowtbl into stack at position 1 (shifting the arguments): json_regfetch(L, shadowtbl); lua_insert(L, 1); - // insert json_nullmark on stack at position 2 (shifting the arguments): + // insert json_nullmark into stack at position 2 (shifting the arguments): json_pushlightref(L, nullmark); lua_insert(L, 2); // store stack index of top of stack: @@ -512,24 +512,27 @@ return 1; } -// gets a value from a JSON document (first argument) -// optionally using a path (variable number of keys after first argument): +// gets a value from a JSON document (passed as first argument) +// using a path (passed as variable number of keys after first argument): static int json_get(lua_State *L) { return json_path(L, 0); } -// gets a value's type from a JSON document (first argument) -// optionally using a path (variable number of keys after first argument): +// gets a value's type from a JSON document (passed as first argument) +// using a path (variable number of keys after first argument): static int json_type(lua_State *L) { return json_path(L, 1); } -// checks if a value in a JSON document (first argument) is null: +// checks if a value in a JSON document (first argument) is +// explicitly set to null: static int json_isnull(lua_State *L) { const char *jsontype; + // call json_type function with variable arguments: lua_pushcfunction(L, json_type); lua_insert(L, 1); lua_call(L, lua_gettop(L) - 1, 1); + // return true if result equals to string "null", otherwise return false: jsontype = lua_tostring(L, -1); if (jsontype && !strcmp(jsontype, "null")) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -542,47 +545,61 @@ #define json_setnull_arraymt_idx 5 #define json_setnull_shadowtbl_idx 6 +// sets a value in a JSON object or JSON array explicitly to null: +// NOTE: JSON null is different than absence of a key static int json_setnull(lua_State *L) { - // truncate stack to two elements: + // stack shall contain two function arguments: lua_settop(L, 2); - // push json_unknownmt to stack position 3: + // push json_unknownmt onto stack position 3: json_regfetch(L, unknownmt); - // push json_objectmt to stack position 4: + // push json_objectmt onto stack position 4: json_regfetch(L, objectmt); - // push json_arraymt to stack position 5: + // push json_arraymt onto stack position 5: json_regfetch(L, arraymt); - // push json_shadowtbl to stack position 6: + // push json_shadowtbl onto stack position 6: json_regfetch(L, shadowtbl); - // - lua_getmetatable(L, 1); + // set metatable if necessary (leaves unknown number of elements on stack): if ( - !lua_rawequal(L, -1, json_setnull_unknownmt_idx) && - !lua_rawequal(L, -1, json_setnull_objectmt_idx) && - !lua_rawequal(L, -1, json_setnull_arraymt_idx) + !lua_getmetatable(L, 1) || ( + !lua_rawequal(L, -1, json_setnull_unknownmt_idx) && + !lua_rawequal(L, -1, json_setnull_objectmt_idx) && + !lua_rawequal(L, -1, json_setnull_arraymt_idx) + ) ) { lua_pushvalue(L, json_setnull_unknownmt_idx); lua_setmetatable(L, 1); } + // try to get shadow table: lua_pushvalue(L, 1); lua_rawget(L, json_setnull_shadowtbl_idx); if (lua_isnil(L, -1)) { + // if no shadow table is found, + // create new shadow table (and leave it on top of stack): lua_newtable(L); + // register shadow table: lua_pushvalue(L, 1); lua_pushvalue(L, -2); lua_rawset(L, json_setnull_shadowtbl_idx); } + // push key (second argument) and null-marker after shadow table onto stack: lua_pushvalue(L, 2); json_pushlightref(L, nullmark); + // store key and null-marker in shadow table: lua_rawset(L, -3); + // return nothing: return 0; } +// returns the length of a JSON array (or zero for a table without numeric keys): static int json_len(lua_State *L) { + // stack shall contain one function argument: lua_settop(L, 1); + // push corresponding shadow table (for first argument) on top of stack: json_regfetch(L, shadowtbl); lua_pushvalue(L, 1); lua_rawget(L, -2); - lua_pushinteger(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1)); + // if shadow table does not exist, return length of argument, else length of shadow table: + lua_pushnumber(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1)); return 1; }