webmcp
changeset 175:20e393d2e6e1
Completed comments and minor code cleanup in JSON library; Added emergency garbage collection for memory allocation in json.export function
author | jbe |
---|---|
date | Fri Aug 01 21:54:45 2014 +0200 (2014-08-01) |
parents | 070edea2a92f |
children | 8d7665e0d490 |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Fri Aug 01 20:29:30 2014 +0200 1.2 +++ b/libraries/json/json.c Fri Aug 01 21:54:45 2014 +0200 1.3 @@ -48,7 +48,7 @@ 1.4 #define json_convert_iterfun_idx 5 1.5 #define json_convert_itertbl_idx 6 1.6 1.7 -// converts a Lua table to a JSON object or JSON array: 1.8 +// converts a Lua table (or any other iterable value) to a JSON object or JSON array: 1.9 // (does never modify the argument, returns an empty object or array if argument is nil) 1.10 static int json_convert(lua_State *L, int array) { 1.11 int arrayidx = 0; 1.12 @@ -100,6 +100,7 @@ 1.13 } else { 1.14 // for an array, copy consecutive integer value pairs to shadow table: 1.15 while (1) { 1.16 + // throw error if array would exceed INT_MAX elements: 1.17 // TODO: Lua 5.3 may support more elements 1.18 if (arrayidx == INT_MAX) { 1.19 lua_pushnumber(L, (size_t)INT_MAX+1); 1.20 @@ -107,9 +108,12 @@ 1.21 if (lua_isnil(L, -1)) break; 1.22 return luaL_error(L, "Array exceeded length of %d elements", INT_MAX); 1.23 } 1.24 + // get next array entry: 1.25 arrayidx++; 1.26 lua_rawgeti(L, json_convert_source_idx, arrayidx); 1.27 + // break if value is nil: 1.28 if (lua_isnil(L, -1)) break; 1.29 + // store value in shadow table: 1.30 lua_rawseti(L, json_convert_shadow_idx, arrayidx); 1.31 } 1.32 } 1.33 @@ -120,21 +124,30 @@ 1.34 lua_pushvalue(L, json_convert_iterator_idx); 1.35 lua_pushvalue(L, 1); 1.36 lua_call(L, 1, 3); 1.37 - // iterate through key value pairs and store them in shadow table 1.38 + // iterate through key value pairs and store some of them in shadow table 1.39 // while replacing nil values with null-marker: 1.40 while (1) { 1.41 + // call iterfun function: 1.42 lua_pushvalue(L, json_convert_iterfun_idx); 1.43 lua_pushvalue(L, json_convert_itertbl_idx); 1.44 lua_pushvalue(L, -3); 1.45 lua_remove(L, -4); 1.46 lua_call(L, 2, 2); 1.47 + // break iteration loop if key is nil: 1.48 if (lua_isnil(L, -2)) break; 1.49 + // store key value pair only if key type is correct: 1.50 if (lua_type(L, -2) == (array ? LUA_TNUMBER : LUA_TSTRING)) { 1.51 + // if key type is correct, 1.52 + // push key onto stack: 1.53 lua_pushvalue(L, -2); 1.54 + // if value is nil, push null-marker onto stack (as value): 1.55 if (lua_isnil(L, -2)) json_pushnullmark(L); 1.56 + // else push value onto stack: 1.57 else lua_pushvalue(L, -2); 1.58 + // set key value pair in shadow table: 1.59 lua_rawset(L, json_convert_shadow_idx); 1.60 } 1.61 + // pop value from stack, but leave key on stack: 1.62 lua_pop(L, 1); 1.63 } 1.64 } 1.65 @@ -149,10 +162,14 @@ 1.66 return 1; 1.67 } 1.68 1.69 +// converts a Lua table (or any other iterable value) to a JSON object: 1.70 +// (does never modify the argument, returns an empty object or array if argument is nil) 1.71 static int json_object(lua_State *L) { 1.72 return json_convert(L, 0); 1.73 } 1.74 1.75 +// converts a Lua table (or any other iterable value) to a JSON array: 1.76 +// (does never modify the argument, returns an empty object or array if argument is nil) 1.77 static int json_array(lua_State *L) { 1.78 return json_convert(L, 1); 1.79 } 1.80 @@ -595,7 +612,7 @@ 1.81 #define json_path_idxshift 1 1.82 1.83 // gets a value or its type from a JSON document (passed as first argument) 1.84 -// using a path (passed as variable number of keys after first argument): 1.85 +// using a path (passed as variable number of keys after the first argument): 1.86 static int json_path(lua_State *L, int type_mode) { 1.87 int stacktop; // stack index of top of stack (after shifting) 1.88 int idx = 2 + json_path_idxshift; // stack index of current argument to process 1.89 @@ -680,13 +697,13 @@ 1.90 } 1.91 1.92 // gets a value from a JSON document (passed as first argument) 1.93 -// using a path (passed as variable number of keys after first argument): 1.94 +// using a path (passed as variable number of keys after the first argument): 1.95 static int json_get(lua_State *L) { 1.96 return json_path(L, 0); 1.97 } 1.98 1.99 // gets a value's type from a JSON document (passed as first argument) 1.100 -// using a path (variable number of keys after first argument): 1.101 +// using a path (passed as variable number of keys after first the argument): 1.102 static int json_type(lua_State *L) { 1.103 return json_path(L, 1); 1.104 } 1.105 @@ -700,7 +717,7 @@ 1.106 #define json_set_idxshift 3 1.107 1.108 // sets a value (passed as second argument) in a JSON document (passed as first argument) 1.109 -// using a path (variable number of keys starting at third argument): 1.110 +// using a path (passed as variable number of keys starting at third argument): 1.111 static int json_set(lua_State *L) { 1.112 int stacktop; // stack index of top of stack (after shifting) 1.113 int idx = 3; // stack index of current argument to process 1.114 @@ -827,6 +844,7 @@ 1.115 return 1; 1.116 } 1.117 1.118 +// __index metamethod for JSON objects and JSON arrays: 1.119 static int json_index(lua_State *L) { 1.120 // stack shall contain two function arguments: 1.121 lua_settop(L, 2); 1.122 @@ -845,6 +863,7 @@ 1.123 return 1; 1.124 } 1.125 1.126 +// __newindex metamethod for JSON objects and JSON arrays: 1.127 static int json_newindex(lua_State *L) { 1.128 // stack shall contain three function arguments: 1.129 lua_settop(L, 3); 1.130 @@ -863,6 +882,7 @@ 1.131 return 0; 1.132 } 1.133 1.134 +// function returned as first value by json_pairs function: 1.135 static int json_pairs_iterfunc(lua_State *L) { 1.136 // stack shall contain two function arguments: 1.137 lua_settop(L, 2); 1.138 @@ -886,7 +906,7 @@ 1.139 } 1.140 1.141 // returns a triple such that 'for key, value in pairs(obj) do ... end' 1.142 -// iterates through all key value pairs (including JSON null keys represented as Lua nil): 1.143 +// iterates through all key value pairs (including JSON null values represented as Lua nil): 1.144 static int json_pairs(lua_State *L) { 1.145 // require one argument to function 1.146 luaL_checkany(L, 1); 1.147 @@ -897,6 +917,7 @@ 1.148 return 3; 1.149 } 1.150 1.151 +// function returned as first value by json_ipairs function: 1.152 static int json_ipairs_iterfunc(lua_State *L) { 1.153 lua_Integer idx; 1.154 // stack shall contain two function arguments: 1.155 @@ -923,7 +944,7 @@ 1.156 } 1.157 1.158 // returns a triple such that 'for idx, value in ipairs(ary) do ... end' 1.159 -// iterates through all values (including JSON null represented as Lua nil): 1.160 +// iterates through all values (including JSON null values represented as Lua nil): 1.161 static int json_ipairs(lua_State *L) { 1.162 // require one argument to function 1.163 luaL_checkany(L, 1); 1.164 @@ -934,11 +955,14 @@ 1.165 return 3; 1.166 } 1.167 1.168 +// datatype representing a table key: 1.169 +// (used for sorting) 1.170 typedef struct { 1.171 size_t length; 1.172 const char *data; 1.173 } json_key_t; 1.174 1.175 +// comparation function for table keys to be passed to qsort function: 1.176 static int json_key_cmp(json_key_t *key1, json_key_t *key2) { 1.177 size_t pos = 0; 1.178 unsigned char c1, c2; 1.179 @@ -963,55 +987,74 @@ 1.180 } 1.181 } 1.182 1.183 +// constants for type detection of ambiguous tables: 1.184 #define JSON_TABLETYPE_UNKNOWN 0 1.185 #define JSON_TABLETYPE_OBJECT 1 1.186 #define JSON_TABLETYPE_ARRAY 2 1.187 1.188 +// special Lua stack indicies for json_export_internal function: 1.189 #define json_export_internal_indentstring_idx 1 1.190 #define json_export_internal_level_idx 2 1.191 #define json_export_internal_value_idx 3 1.192 #define json_export_internal_tmp_idx 4 1.193 1.194 +// encodes a JSON document (passed as third argument) 1.195 +// optionally using indentation (indentation string passed as first argument) 1.196 +// for a certain depth level (passed as second argument): 1.197 static int json_export_internal(lua_State *L) { 1.198 - int level; 1.199 - int pretty; 1.200 - int i; 1.201 - lua_Number num; 1.202 - const char *str; 1.203 - unsigned char c; 1.204 - size_t strlen; 1.205 - size_t pos = 0; 1.206 - luaL_Buffer buf; 1.207 - char hexcode[7]; // backslash, character 'u', 4 hex digits, and terminating NULL byte 1.208 - int tabletype = JSON_TABLETYPE_UNKNOWN; 1.209 - int anyelement = 0; 1.210 - size_t keycount = 0; 1.211 - size_t keypos = 0; 1.212 - json_key_t *keybuf = NULL; 1.213 - lua_Integer idx; 1.214 + int level; // current depth level 1.215 + int pretty; // pretty printing on? (i.e. printing with indentation) 1.216 + int i; // iteration variable for level dependent repetitions: 1.217 + lua_Number num; // number to encode 1.218 + const char *str; // string to encode 1.219 + size_t strlen; // length of string to encode 1.220 + unsigned char c; // character to encode (unsigned!) 1.221 + size_t pos = 0; // position in string or position of current key (initialized with zero!) 1.222 + luaL_Buffer buf; // Lua buffer to create strings 1.223 + char hexcode[7]; // store for unicode hex escape sequence 1.224 + // NOTE: 7 bytes due to backslash, character 'u', 4 hex digits, and terminating NULL byte 1.225 + int tabletype = JSON_TABLETYPE_UNKNOWN; // table type: unknown, JSON object, or JSON array 1.226 + int anyelement = 0; // set to 1 if at least one array element has been processed 1.227 + size_t keycount = 0; // number of string keys in object 1.228 + json_key_t *keybuf = NULL; // temporary buffer to store (and sort) string keys of objects 1.229 + lua_Integer arrayidx; // index to iterate through arrays 1.230 + // stack shall contain three function arguments: 1.231 lua_settop(L, json_export_internal_value_idx); 1.232 + // if value to encode is the null-marker, then treat it the same as nil: 1.233 if (json_isnullmark(L, json_export_internal_value_idx)) { 1.234 lua_pop(L, 1); 1.235 lua_pushnil(L); 1.236 } 1.237 + // distinguish between different Lua types: 1.238 switch (lua_type(L, json_export_internal_value_idx)) { 1.239 + // value to encode is nil: 1.240 case LUA_TNIL: 1.241 + // return string "null": 1.242 lua_pushliteral(L, "null"); 1.243 return 1; 1.244 + // value to encode is of type number: 1.245 case LUA_TNUMBER: 1.246 + // convert value to double precision number: 1.247 num = lua_tonumber(L, json_export_internal_value_idx); 1.248 + // throw error if number is not-a-number: 1.249 if (isnan(num)) return luaL_error(L, "JSON export not possible for NaN value"); 1.250 + // throw error if number is positive or negative infinity: 1.251 if (isinf(num)) return luaL_error(L, "JSON export not possible for infinite numbers"); 1.252 + // return Lua's string encoding of the number: 1.253 lua_tostring(L, json_export_internal_value_idx); 1.254 return 1; 1.255 + // value to encode is of type boolean: 1.256 case LUA_TBOOLEAN: 1.257 + // return string "true" or "false" according to boolean value: 1.258 if (lua_toboolean(L, json_export_internal_value_idx)) { 1.259 lua_pushliteral(L, "true"); 1.260 } else { 1.261 lua_pushliteral(L, "false"); 1.262 } 1.263 return 1; 1.264 + // value to encode is of type string: 1.265 case LUA_TSTRING: 1.266 + // quote, escape and return string: 1.267 str = lua_tolstring(L, 3, &strlen); 1.268 luaL_buffinit(L, &buf); 1.269 luaL_addchar(&buf, '"'); 1.270 @@ -1035,7 +1078,9 @@ 1.271 luaL_addchar(&buf, '"'); 1.272 luaL_pushresult(&buf); 1.273 return 1; 1.274 + // value to encode is of type table (this includes JSON objects and JSON arrays): 1.275 case LUA_TTABLE: 1.276 + // use table's metatable to try to determine type of table: 1.277 if (lua_getmetatable(L, json_export_internal_value_idx)) { 1.278 json_regfetch(L, objectmt); 1.279 if (lua_rawequal(L, -2, -1)) { 1.280 @@ -1049,54 +1094,91 @@ 1.281 } 1.282 } 1.283 } 1.284 + // replace table with its shadow table if existent, and reset stack: 1.285 json_regfetch(L, shadowtbl); 1.286 lua_pushvalue(L, json_export_internal_value_idx); 1.287 lua_rawget(L, -2); 1.288 if (!lua_isnil(L, -1)) lua_replace(L, json_export_internal_value_idx); 1.289 lua_settop(L, json_export_internal_value_idx); 1.290 + // check if type of table is still undetermined: 1.291 if (tabletype == JSON_TABLETYPE_UNKNOWN) { 1.292 + // if yes, iterate over all keys: 1.293 for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) { 1.294 switch (lua_type(L, -2)) { 1.295 case LUA_TSTRING: 1.296 + // for string keys, 1.297 + // increase keycount (may avoid another iteration): 1.298 keycount++; 1.299 + // if type of table was unknown, then type of table is a JSON object now: 1.300 if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_OBJECT; 1.301 + // if type of table was a JSON array, then the type of table is ambiguous now 1.302 + // and an error is thrown: 1.303 else if (tabletype == JSON_TABLETYPE_ARRAY) goto json_export_tabletype_error; 1.304 break; 1.305 case LUA_TNUMBER: 1.306 + // for numeric keys, 1.307 + // if type of table was unknown, then type of table is a JSON array now: 1.308 if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_ARRAY; 1.309 + // if type of table was a JSON object, then the type of table is ambiguous now 1.310 + // and an error is thrown: 1.311 else if (tabletype == JSON_TABLETYPE_OBJECT) goto json_export_tabletype_error; 1.312 break; 1.313 } 1.314 } 1.315 } 1.316 + // set pretty variable to 1 if pretty printing (with indentation) is desired: 1.317 pretty = lua_toboolean(L, json_export_internal_indentstring_idx); 1.318 + // set level variable to corresponding function argument increased by one: 1.319 level = lua_tointeger(L, json_export_internal_level_idx) + 1; 1.320 + // throw error if there are more levels that could be imported by this library: 1.321 if (level > JSON_MAXDEPTH) { 1.322 return luaL_error(L, "More than %d nested JSON levels", JSON_MAXDEPTH); 1.323 } 1.324 + // distinguish between JSON objects and JSON arrays: 1.325 switch (tabletype) { 1.326 + // JSON object: 1.327 case JSON_TABLETYPE_OBJECT: 1.328 + // calculate count of string keys unless it has been calculated before: 1.329 if (!keycount) { 1.330 for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) { 1.331 if (lua_type(L, -2) == LUA_TSTRING) keycount++; 1.332 } 1.333 } 1.334 + // create a sorted list of all string keys in memory: 1.335 if (keycount) { 1.336 + // allocate memory for string keys: 1.337 keybuf = calloc(keycount, sizeof(json_key_t)); 1.338 - if (!keybuf) return luaL_error(L, "Memory allocation failed in JSON library"); 1.339 + // check if memory allocation was successful: 1.340 + if (!keybuf) { 1.341 + // in case of memory exhaustion, try to collect garbage: 1.342 + lua_gc(L, LUA_GCCOLLECT, 0); 1.343 + // try to allocate memory again: 1.344 + keybuf = calloc(keycount, sizeof(json_key_t)); 1.345 + // throw error if memory allocation failed again: 1.346 + if (!keybuf) { 1.347 + return luaL_error(L, "Memory allocation failed in JSON library"); 1.348 + } 1.349 + } 1.350 + // copy all string keys to the C array: 1.351 for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) { 1.352 if (lua_type(L, -2) == LUA_TSTRING) { 1.353 - json_key_t *key = keybuf + (keypos++); 1.354 + json_key_t *key = keybuf + (pos++); 1.355 key->data = lua_tolstring(L, -2, &key->length); 1.356 } 1.357 } 1.358 + // sort C array using quicksort: 1.359 qsort(keybuf, keycount, sizeof(json_key_t), (void *)json_key_cmp); 1.360 } 1.361 + // create Lua string buffer: 1.362 luaL_buffinit(L, &buf); 1.363 + // add opening bracket to output buffer: 1.364 luaL_addchar(&buf, '{'); 1.365 - for (keypos=0; keypos<keycount; keypos++) { 1.366 - json_key_t *key = keybuf + keypos; 1.367 - if (keypos) luaL_addchar(&buf, ','); 1.368 + // iterate through all (sorted) string keys: 1.369 + for (pos=0; pos<keycount; pos++) { 1.370 + json_key_t *key = keybuf + pos; 1.371 + // add comma to output buffer unless we process the first key: 1.372 + if (pos) luaL_addchar(&buf, ','); 1.373 + // handle indentation for pretty results: 1.374 if (pretty) { 1.375 luaL_addchar(&buf, '\n'); 1.376 for (i=0; i<level; i++) { 1.377 @@ -1104,53 +1186,81 @@ 1.378 luaL_addvalue(&buf); 1.379 } 1.380 } 1.381 + // recursive call to encode key: 1.382 lua_pushcfunction(L, json_export_internal); 1.383 lua_pushvalue(L, json_export_internal_indentstring_idx); 1.384 lua_pushinteger(L, level); 1.385 lua_pushlstring(L, key->data, key->length); 1.386 if (lua_pcall(L, 3, 1, 0)) { 1.387 + // free memory of sorted string keys on error: 1.388 if (keybuf) free(keybuf); 1.389 + // rethrow error: 1.390 return lua_error(L); 1.391 } 1.392 + // add encoded key to output buffer: 1.393 luaL_addvalue(&buf); 1.394 + // add colon to output buffer: 1.395 luaL_addchar(&buf, ':'); 1.396 + // handle indentation for pretty results: 1.397 if (pretty) luaL_addchar(&buf, ' '); 1.398 + // recursive call to encode value: 1.399 lua_pushcfunction(L, json_export_internal); 1.400 lua_pushvalue(L, json_export_internal_indentstring_idx); 1.401 lua_pushinteger(L, level); 1.402 lua_pushlstring(L, key->data, key->length); 1.403 lua_rawget(L, json_export_internal_value_idx); 1.404 if (lua_pcall(L, 3, 1, 0)) { 1.405 + // free memory of sorted string keys on error: 1.406 if (keybuf) free(keybuf); 1.407 + // rethrow error: 1.408 return lua_error(L); 1.409 } 1.410 + // add encoded value to output buffer: 1.411 luaL_addvalue(&buf); 1.412 } 1.413 + // decrement level variable for all following statements: 1.414 + level--; 1.415 + // free memory of sorted string keys: 1.416 if (keybuf) free(keybuf); 1.417 + // handle indentation for pretty results: 1.418 if (pretty && keycount != 0) { 1.419 luaL_addchar(&buf, '\n'); 1.420 - for (i=0; i<level-1; i++) { 1.421 + for (i=0; i<level; i++) { 1.422 lua_pushvalue(L, json_export_internal_indentstring_idx); 1.423 luaL_addvalue(&buf); 1.424 } 1.425 } 1.426 + // add closing bracket to output buffer: 1.427 luaL_addchar(&buf, '}'); 1.428 - if (pretty && level == 1) luaL_addchar(&buf, '\n'); 1.429 + // for pretty results, add final newline character if outermost container is processed: 1.430 + if (pretty && level == 0) luaL_addchar(&buf, '\n'); 1.431 + // convert and return buffer: 1.432 luaL_pushresult(&buf); 1.433 return 1; 1.434 + // JSON array: 1.435 case JSON_TABLETYPE_ARRAY: 1.436 + // reserve an extra element on the stack (needed because Lua buffer has unknown size on stack): 1.437 lua_settop(L, json_export_internal_tmp_idx); 1.438 + // create Lua string buffer: 1.439 luaL_buffinit(L, &buf); 1.440 + // add opening bracket to output buffer: 1.441 luaL_addchar(&buf, '['); 1.442 - for (idx = 1; ; idx++) { 1.443 - lua_rawgeti(L, json_export_internal_value_idx, idx); 1.444 + // iterate through integer keys: 1.445 + for (arrayidx = 1; ; arrayidx++) { 1.446 + // get value in array, and break if nil: 1.447 + lua_rawgeti(L, json_export_internal_value_idx, arrayidx); 1.448 if (lua_isnil(L, -1)) { 1.449 lua_pop(L, 1); 1.450 break; 1.451 } 1.452 + // store value below Lua string buffer on stack (to allow operation on string buffer): 1.453 lua_replace(L, json_export_internal_tmp_idx); 1.454 + // 1.455 + // add comma to output buffer unless we process the first element: 1.456 if (anyelement) luaL_addchar(&buf, ','); 1.457 + // remember that we processed an element: 1.458 anyelement = 1; 1.459 + // handle indentation for pretty results: 1.460 if (pretty) { 1.461 luaL_addchar(&buf, '\n'); 1.462 for (i=0; i<level; i++) { 1.463 @@ -1158,49 +1268,68 @@ 1.464 luaL_addvalue(&buf); 1.465 } 1.466 } 1.467 + // recursive call to encode previously stored value: 1.468 lua_pushcfunction(L, json_export_internal); 1.469 lua_pushvalue(L, json_export_internal_indentstring_idx); 1.470 lua_pushinteger(L, level); 1.471 lua_pushvalue(L, json_export_internal_tmp_idx); 1.472 lua_call(L, 3, 1); 1.473 + // add encoded value to output buffer: 1.474 luaL_addvalue(&buf); 1.475 } 1.476 + // decrement level variable for all following statements: 1.477 + level--; 1.478 + // handle indentation for pretty results: 1.479 if (pretty && anyelement) { 1.480 luaL_addchar(&buf, '\n'); 1.481 - for (i=0; i<level-1; i++) { 1.482 + for (i=0; i<level; i++) { 1.483 lua_pushvalue(L, json_export_internal_indentstring_idx); 1.484 luaL_addvalue(&buf); 1.485 } 1.486 } 1.487 + // add closing bracket to output buffer: 1.488 luaL_addchar(&buf, ']'); 1.489 - if (pretty && level == 1) luaL_addchar(&buf, '\n'); 1.490 + // for pretty results, add final newline character if outermost container is processed: 1.491 + if (pretty && level == 0) luaL_addchar(&buf, '\n'); 1.492 + // convert and return buffer: 1.493 luaL_pushresult(&buf); 1.494 return 1; 1.495 } 1.496 + // throw error if table type is unknown: 1.497 json_export_tabletype_error: 1.498 return luaL_error(L, "JSON export not possible for ambiguous table (cannot decide whether it is an object or array)"); 1.499 } 1.500 + // all other datatypes are considered an error: 1.501 return luaL_error(L, "JSON export not possible for values of type \"%s\"", lua_typename(L, lua_type(L, json_export_internal_value_idx))); 1.502 } 1.503 1.504 +// encodes a JSON document (passed as argument): 1.505 static int json_export(lua_State *L) { 1.506 + // stack shall contain one function argument: 1.507 lua_settop(L, 1); 1.508 + // call json_export_internal function with proper arguments: 1.509 lua_pushcfunction(L, json_export_internal); 1.510 lua_pushnil(L); 1.511 lua_pushinteger(L, 0); 1.512 lua_pushvalue(L, 1); 1.513 lua_call(L, 3, 1); 1.514 + // return result: 1.515 return 1; 1.516 } 1.517 1.518 +// encodes a JSON document (passed as first argument) 1.519 +// with indentation (indentation string may be passed as second argument): 1.520 static int json_pretty(lua_State *L) { 1.521 + // stack shall contain two function arguments: 1.522 lua_settop(L, 2); 1.523 + // call json_export_internal function with proper arguments: 1.524 lua_pushcfunction(L, json_export_internal); 1.525 if (lua_isnil(L, 2)) lua_pushliteral(L, " "); 1.526 else lua_pushvalue(L, 2); 1.527 lua_pushinteger(L, 0); 1.528 lua_pushvalue(L, 1); 1.529 lua_call(L, 3, 1); 1.530 + // return result: 1.531 return 1; 1.532 } 1.533