webmcp
changeset 147:da5ab2c226dc
Fixes and documentation in json_setnull and json_length functions of JSON library
author | jbe |
---|---|
date | Wed Jul 30 22:19:34 2014 +0200 (2014-07-30) |
parents | 7912a05ebc3f |
children | 5354d836e6fb |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Wed Jul 30 20:54:42 2014 +0200 1.2 +++ b/libraries/json/json.c Wed Jul 30 22:19:34 2014 +0200 1.3 @@ -114,15 +114,15 @@ 1.4 luaL_Buffer luabuf; // Lua buffer to decode JSON string values 1.5 char *cbuf; // C buffer to decode JSON string values 1.6 size_t writepos; // write position of decoded strings in C buffer 1.7 - // stack shall only contain one function argument: 1.8 + // stack shall contain one function argument: 1.9 lua_settop(L, 1); 1.10 - // push objectmt on stack position 2: 1.11 + // push objectmt onto stack position 2: 1.12 json_regfetch(L, objectmt); 1.13 - // push arraymt on stack position 3: 1.14 + // push arraymt onto stack position 3: 1.15 json_regfetch(L, arraymt); 1.16 - // push shadowtbl on stack position 4: 1.17 + // push shadowtbl onto stack position 4: 1.18 json_regfetch(L, shadowtbl); 1.19 - // push nullmark on stack position 5: 1.20 + // push nullmark onto stack position 5: 1.21 json_pushlightref(L, nullmark); 1.22 // require string as first argument: 1.23 str = luaL_checklstring(L, 1, &total); 1.24 @@ -363,17 +363,17 @@ 1.25 } else if (!strncmp(str+pos, "true", 4)) { 1.26 // consume 4 input characters for "true": 1.27 pos += 4; 1.28 - // put Lua true value on stack: 1.29 + // put Lua true value onto stack: 1.30 lua_pushboolean(L, 1); 1.31 } else if (!strncmp(str+pos, "false", 5)) { 1.32 // consume 5 input characters for "false": 1.33 pos += 5; 1.34 - // put Lua false value on stack: 1.35 + // put Lua false value onto stack: 1.36 lua_pushboolean(L, 0); 1.37 } else if (!strncmp(str+pos, "null", 4)) { 1.38 // consume 4 input characters for "null": 1.39 pos += 4; 1.40 - // put special null-marker on stack: 1.41 + // put special null-marker onto stack: 1.42 lua_pushvalue(L, json_import_nullmark_idx); 1.43 } else { 1.44 // all other cases are a syntax error: 1.45 @@ -427,14 +427,14 @@ 1.46 #define json_path_idxshift 2 1.47 1.48 // gets a value or its type from a JSON document (passed as first argument) 1.49 -// optionally using a path (passed as variable number of keys after first argument): 1.50 +// using a path (passed as variable number of keys after first argument): 1.51 static int json_path(lua_State *L, int type_mode) { 1.52 int stacktop; // stack index of top of stack (after shifting) 1.53 int idx = 2 + json_path_idxshift; // stack index of current argument to process 1.54 - // insert json_shadowtbl on stack at position 1 (shifting the arguments): 1.55 + // insert json_shadowtbl into stack at position 1 (shifting the arguments): 1.56 json_regfetch(L, shadowtbl); 1.57 lua_insert(L, 1); 1.58 - // insert json_nullmark on stack at position 2 (shifting the arguments): 1.59 + // insert json_nullmark into stack at position 2 (shifting the arguments): 1.60 json_pushlightref(L, nullmark); 1.61 lua_insert(L, 2); 1.62 // store stack index of top of stack: 1.63 @@ -512,24 +512,27 @@ 1.64 return 1; 1.65 } 1.66 1.67 -// gets a value from a JSON document (first argument) 1.68 -// optionally using a path (variable number of keys after first argument): 1.69 +// gets a value from a JSON document (passed as first argument) 1.70 +// using a path (passed as variable number of keys after first argument): 1.71 static int json_get(lua_State *L) { 1.72 return json_path(L, 0); 1.73 } 1.74 1.75 -// gets a value's type from a JSON document (first argument) 1.76 -// optionally using a path (variable number of keys after first argument): 1.77 +// gets a value's type from a JSON document (passed as first argument) 1.78 +// using a path (variable number of keys after first argument): 1.79 static int json_type(lua_State *L) { 1.80 return json_path(L, 1); 1.81 } 1.82 1.83 -// checks if a value in a JSON document (first argument) is null: 1.84 +// checks if a value in a JSON document (first argument) is 1.85 +// explicitly set to null: 1.86 static int json_isnull(lua_State *L) { 1.87 const char *jsontype; 1.88 + // call json_type function with variable arguments: 1.89 lua_pushcfunction(L, json_type); 1.90 lua_insert(L, 1); 1.91 lua_call(L, lua_gettop(L) - 1, 1); 1.92 + // return true if result equals to string "null", otherwise return false: 1.93 jsontype = lua_tostring(L, -1); 1.94 if (jsontype && !strcmp(jsontype, "null")) lua_pushboolean(L, 1); 1.95 else lua_pushboolean(L, 0); 1.96 @@ -542,47 +545,61 @@ 1.97 #define json_setnull_arraymt_idx 5 1.98 #define json_setnull_shadowtbl_idx 6 1.99 1.100 +// sets a value in a JSON object or JSON array explicitly to null: 1.101 +// NOTE: JSON null is different than absence of a key 1.102 static int json_setnull(lua_State *L) { 1.103 - // truncate stack to two elements: 1.104 + // stack shall contain two function arguments: 1.105 lua_settop(L, 2); 1.106 - // push json_unknownmt to stack position 3: 1.107 + // push json_unknownmt onto stack position 3: 1.108 json_regfetch(L, unknownmt); 1.109 - // push json_objectmt to stack position 4: 1.110 + // push json_objectmt onto stack position 4: 1.111 json_regfetch(L, objectmt); 1.112 - // push json_arraymt to stack position 5: 1.113 + // push json_arraymt onto stack position 5: 1.114 json_regfetch(L, arraymt); 1.115 - // push json_shadowtbl to stack position 6: 1.116 + // push json_shadowtbl onto stack position 6: 1.117 json_regfetch(L, shadowtbl); 1.118 - // 1.119 - lua_getmetatable(L, 1); 1.120 + // set metatable if necessary (leaves unknown number of elements on stack): 1.121 if ( 1.122 - !lua_rawequal(L, -1, json_setnull_unknownmt_idx) && 1.123 - !lua_rawequal(L, -1, json_setnull_objectmt_idx) && 1.124 - !lua_rawequal(L, -1, json_setnull_arraymt_idx) 1.125 + !lua_getmetatable(L, 1) || ( 1.126 + !lua_rawequal(L, -1, json_setnull_unknownmt_idx) && 1.127 + !lua_rawequal(L, -1, json_setnull_objectmt_idx) && 1.128 + !lua_rawequal(L, -1, json_setnull_arraymt_idx) 1.129 + ) 1.130 ) { 1.131 lua_pushvalue(L, json_setnull_unknownmt_idx); 1.132 lua_setmetatable(L, 1); 1.133 } 1.134 + // try to get shadow table: 1.135 lua_pushvalue(L, 1); 1.136 lua_rawget(L, json_setnull_shadowtbl_idx); 1.137 if (lua_isnil(L, -1)) { 1.138 + // if no shadow table is found, 1.139 + // create new shadow table (and leave it on top of stack): 1.140 lua_newtable(L); 1.141 + // register shadow table: 1.142 lua_pushvalue(L, 1); 1.143 lua_pushvalue(L, -2); 1.144 lua_rawset(L, json_setnull_shadowtbl_idx); 1.145 } 1.146 + // push key (second argument) and null-marker after shadow table onto stack: 1.147 lua_pushvalue(L, 2); 1.148 json_pushlightref(L, nullmark); 1.149 + // store key and null-marker in shadow table: 1.150 lua_rawset(L, -3); 1.151 + // return nothing: 1.152 return 0; 1.153 } 1.154 1.155 +// returns the length of a JSON array (or zero for a table without numeric keys): 1.156 static int json_len(lua_State *L) { 1.157 + // stack shall contain one function argument: 1.158 lua_settop(L, 1); 1.159 + // push corresponding shadow table (for first argument) on top of stack: 1.160 json_regfetch(L, shadowtbl); 1.161 lua_pushvalue(L, 1); 1.162 lua_rawget(L, -2); 1.163 - lua_pushinteger(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1)); 1.164 + // if shadow table does not exist, return length of argument, else length of shadow table: 1.165 + lua_pushnumber(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1)); 1.166 return 1; 1.167 } 1.168