diff options
-rw-r--r-- | lua_cjson.c | 58 | ||||
-rw-r--r-- | manual.txt | 34 | ||||
-rwxr-xr-x | tests/test.lua | 14 |
3 files changed, 94 insertions, 12 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index 498c686..afa5266 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -1310,6 +1310,35 @@ static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup) | |||
1310 | } | 1310 | } |
1311 | #endif | 1311 | #endif |
1312 | 1312 | ||
1313 | /* Call target function in protected mode with all supplied args. | ||
1314 | * Assumes target function only returns a single non-nil value. | ||
1315 | * Convert and return thrown errors as: nil, "error message" */ | ||
1316 | static int json_protect_conversion(lua_State *l) | ||
1317 | { | ||
1318 | int err; | ||
1319 | |||
1320 | /* Deliberately throw an error for invalid arguments */ | ||
1321 | luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument"); | ||
1322 | |||
1323 | /* pcall() the function stored as upvalue(1) */ | ||
1324 | lua_pushvalue(l, lua_upvalueindex(1)); | ||
1325 | lua_insert(l, 1); | ||
1326 | err = lua_pcall(l, 1, 1, 0); | ||
1327 | if (!err) | ||
1328 | return 1; | ||
1329 | |||
1330 | if (err == LUA_ERRRUN) { | ||
1331 | lua_pushnil(l); | ||
1332 | lua_insert(l, -2); | ||
1333 | return 2; | ||
1334 | } | ||
1335 | |||
1336 | /* Since we are not using a custom error handler, the only remaining | ||
1337 | * errors are memory related */ | ||
1338 | return luaL_error(l, "Memory allocation error in CJSON protected call"); | ||
1339 | } | ||
1340 | |||
1341 | /* Return cjson module table */ | ||
1313 | static int lua_cjson_new(lua_State *l) | 1342 | static int lua_cjson_new(lua_State *l) |
1314 | { | 1343 | { |
1315 | luaL_Reg reg[] = { | 1344 | luaL_Reg reg[] = { |
@@ -1349,6 +1378,27 @@ static int lua_cjson_new(lua_State *l) | |||
1349 | return 1; | 1378 | return 1; |
1350 | } | 1379 | } |
1351 | 1380 | ||
1381 | /* Return cjson.safe module table */ | ||
1382 | static int lua_cjson_safe_new(lua_State *l) | ||
1383 | { | ||
1384 | const char *func[] = { "decode", "encode", NULL }; | ||
1385 | int i; | ||
1386 | |||
1387 | lua_cjson_new(l); | ||
1388 | |||
1389 | /* Fix new() method */ | ||
1390 | lua_pushcfunction(l, lua_cjson_safe_new); | ||
1391 | lua_setfield(l, -2, "new"); | ||
1392 | |||
1393 | for (i = 0; func[i]; i++) { | ||
1394 | lua_getfield(l, -1, func[i]); | ||
1395 | lua_pushcclosure(l, json_protect_conversion, 1); | ||
1396 | lua_setfield(l, -2, func[i]); | ||
1397 | } | ||
1398 | |||
1399 | return 1; | ||
1400 | } | ||
1401 | |||
1352 | int luaopen_cjson(lua_State *l) | 1402 | int luaopen_cjson(lua_State *l) |
1353 | { | 1403 | { |
1354 | lua_cjson_new(l); | 1404 | lua_cjson_new(l); |
@@ -1363,5 +1413,13 @@ int luaopen_cjson(lua_State *l) | |||
1363 | return 1; | 1413 | return 1; |
1364 | } | 1414 | } |
1365 | 1415 | ||
1416 | int luaopen_cjson_safe(lua_State *l) | ||
1417 | { | ||
1418 | lua_cjson_safe_new(l); | ||
1419 | |||
1420 | /* Return cjson.safe table */ | ||
1421 | return 1; | ||
1422 | } | ||
1423 | |||
1366 | /* vi:ai et sw=4 ts=4: | 1424 | /* vi:ai et sw=4 ts=4: |
1367 | */ | 1425 | */ |
@@ -173,6 +173,7 @@ Synopsis | |||
173 | -- Module instantiation | 173 | -- Module instantiation |
174 | local cjson = require "cjson" | 174 | local cjson = require "cjson" |
175 | local cjson2 = cjson.new() | 175 | local cjson2 = cjson.new() |
176 | local cjson_safe = require "cjson.safe" | ||
176 | 177 | ||
177 | -- Translate Lua value to/from JSON | 178 | -- Translate Lua value to/from JSON |
178 | text = cjson.encode(value) | 179 | text = cjson.encode(value) |
@@ -195,11 +196,20 @@ Module Instantiation | |||
195 | ------------ | 196 | ------------ |
196 | local cjson = require "cjson" | 197 | local cjson = require "cjson" |
197 | local cjson2 = cjson.new() | 198 | local cjson2 = cjson.new() |
199 | local cjson_safe = require "cjson.safe" | ||
198 | ------------ | 200 | ------------ |
199 | 201 | ||
200 | Import Lua CJSON via the Lua +require+ function. Lua CJSON does not | 202 | Import Lua CJSON via the Lua +require+ function. Lua CJSON does not |
201 | register a global module table with the default | 203 | register a global module table. |
202 | <<build_options,build options>>. | 204 | |
205 | The +cjson+ module will throw an error during JSON conversion if any | ||
206 | invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>> | ||
207 | and <<cjson_decode,+cjson.decode+>> for details. | ||
208 | |||
209 | The +cjson.safe+ module behaves identically to the +cjson+ module, | ||
210 | except when errors are encountered during JSON conversion. On error, the | ||
211 | +cjson_safe.encode+ and +cjson_safe.decode+ functions will return | ||
212 | +nil+ followed by the error message. | ||
203 | 213 | ||
204 | +cjson.new+ can be used to instantiate an independent copy of the Lua | 214 | +cjson.new+ can be used to instantiate an independent copy of the Lua |
205 | CJSON module. The new module has a separate persistent encoding buffer, | 215 | CJSON module. The new module has a separate persistent encoding buffer, |
@@ -276,8 +286,8 @@ setting = cjson.decode_invalid_numbers([setting]) | |||
276 | -- "setting" must be a boolean. Default: true. | 286 | -- "setting" must be a boolean. Default: true. |
277 | ------------ | 287 | ------------ |
278 | 288 | ||
279 | Lua CJSON may throw an error when trying to decode numbers not supported | 289 | Lua CJSON may generate an error when trying to decode numbers not |
280 | by the JSON specification. _Invalid numbers_ are defined as: | 290 | supported by the JSON specification. _Invalid numbers_ are defined as: |
281 | 291 | ||
282 | - infinity | 292 | - infinity |
283 | - not-a-number (NaN) | 293 | - not-a-number (NaN) |
@@ -303,13 +313,13 @@ depth = cjson.decode_max_depth([depth]) | |||
303 | -- "depth" must be a positive integer. Default: 1000. | 313 | -- "depth" must be a positive integer. Default: 1000. |
304 | ------------ | 314 | ------------ |
305 | 315 | ||
306 | Lua CJSON will throw an error when parsing deeply nested JSON once the | 316 | Lua CJSON will generate an error when parsing deeply nested JSON once |
307 | maximum array/object depth has been exceeded. This check prevents | 317 | the maximum array/object depth has been exceeded. This check prevents |
308 | unnecessarily complicated JSON from slowing down the application, or | 318 | unnecessarily complicated JSON from slowing down the application, or |
309 | crashing the application due to lack of process stack space. | 319 | crashing the application due to lack of process stack space. |
310 | 320 | ||
311 | An error may be thrown before the depth limit is hit if Lua is unable to | 321 | An error may be generated before the depth limit is hit if Lua is unable |
312 | allocate more objects on the Lua stack. | 322 | to allocate more objects on the Lua stack. |
313 | 323 | ||
314 | By default, Lua CJSON will reject JSON with arrays and/or objects nested | 324 | By default, Lua CJSON will reject JSON with arrays and/or objects nested |
315 | more than 1000 levels deep. | 325 | more than 1000 levels deep. |
@@ -424,7 +434,7 @@ setting = cjson.encode_invalid_numbers([setting]) | |||
424 | -- "setting" must a boolean or "null". Default: false. | 434 | -- "setting" must a boolean or "null". Default: false. |
425 | ------------ | 435 | ------------ |
426 | 436 | ||
427 | Lua CJSON may throw an error when encoding floating point numbers not | 437 | Lua CJSON may generate an error when encoding floating point numbers not |
428 | supported by the JSON specification (_invalid numbers_): | 438 | supported by the JSON specification (_invalid numbers_): |
429 | 439 | ||
430 | - infinity | 440 | - infinity |
@@ -476,11 +486,11 @@ depth = cjson.encode_max_depth([depth]) | |||
476 | -- "depth" must be a positive integer. Default: 1000. | 486 | -- "depth" must be a positive integer. Default: 1000. |
477 | ------------ | 487 | ------------ |
478 | 488 | ||
479 | Once the maximum table depth has been exceeded Lua CJSON will throw an | 489 | Once the maximum table depth has been exceeded Lua CJSON will generate |
480 | error. This prevents a deeply nested or recursive data structure from | 490 | an error. This prevents a deeply nested or recursive data structure from |
481 | crashing the application. | 491 | crashing the application. |
482 | 492 | ||
483 | By default, Lua CJSON will throw an error when trying to encode data | 493 | By default, Lua CJSON will generate an error when trying to encode data |
484 | structures with more than 1000 nested tables. | 494 | structures with more than 1000 nested tables. |
485 | 495 | ||
486 | The current setting is always returned, and is only updated when an | 496 | The current setting is always returned, and is only updated when an |
diff --git a/tests/test.lua b/tests/test.lua index ac6419a..96b47ff 100755 --- a/tests/test.lua +++ b/tests/test.lua | |||
@@ -7,6 +7,7 @@ | |||
7 | -- Note: The output of this script is easier to read with "less -S" | 7 | -- Note: The output of this script is easier to read with "less -S" |
8 | 8 | ||
9 | local json = require "cjson" | 9 | local json = require "cjson" |
10 | local json_safe = require "cjson.safe" | ||
10 | local util = require "cjson.util" | 11 | local util = require "cjson.util" |
11 | 12 | ||
12 | local function gen_raw_octets() | 13 | local function gen_raw_octets() |
@@ -386,6 +387,19 @@ local cjson_tests = { | |||
386 | { "Check encode_sparse_array()", | 387 | { "Check encode_sparse_array()", |
387 | function (...) return json.encode_sparse_array(...) end, { }, | 388 | function (...) return json.encode_sparse_array(...) end, { }, |
388 | true, { false, 2, 10 } }, | 389 | true, { false, 2, 10 } }, |
390 | |||
391 | { "Encode (safe) simple value", | ||
392 | json_safe.encode, { true }, | ||
393 | true, { "true" } }, | ||
394 | { "Encode (safe) argument validation [throw error]", | ||
395 | json_safe.encode, { "arg1", "arg2" }, | ||
396 | false, { "bad argument #1 to '?' (expected 1 argument)" } }, | ||
397 | { "Decode (safe) error generation", | ||
398 | json_safe.decode, { "Oops" }, | ||
399 | true, { nil, "Expected value but found invalid token at character 1" } }, | ||
400 | { "Decode (safe) error generation after new()", | ||
401 | function(...) return json_safe.new().decode(...) end, { "Oops" }, | ||
402 | true, { nil, "Expected value but found invalid token at character 1" } }, | ||
389 | } | 403 | } |
390 | 404 | ||
391 | print(("==> Testing Lua CJSON version %s\n"):format(json._VERSION)) | 405 | print(("==> Testing Lua CJSON version %s\n"):format(json._VERSION)) |