diff options
author | Mark Pulford <mark@kyne.com.au> | 2011-04-16 03:25:47 +0930 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2011-04-16 03:25:47 +0930 |
commit | b8cf41c24626ecf184c15575412d1914b54a3db8 (patch) | |
tree | 7086cbb1508283433842f89a974218f8e4177f67 | |
parent | 9f3d6b59c5f097d66e94f987c7731d7a4113057f (diff) | |
download | lua-cjson-b8cf41c24626ecf184c15575412d1914b54a3db8.tar.gz lua-cjson-b8cf41c24626ecf184c15575412d1914b54a3db8.tar.bz2 lua-cjson-b8cf41c24626ecf184c15575412d1914b54a3db8.zip |
Improve exception handling in lua_json
- Add json_encode_exception()
- Update to throw exceptions during encoding
-rw-r--r-- | lua_json.c | 81 |
1 files changed, 60 insertions, 21 deletions
@@ -35,11 +35,21 @@ | |||
35 | #include <lauxlib.h> | 35 | #include <lauxlib.h> |
36 | 36 | ||
37 | #include "lua_json.h" | 37 | #include "lua_json.h" |
38 | #include "lua_misc.h" | ||
38 | #include "utils.h" | 39 | #include "utils.h" |
39 | #include "strbuf.h" | 40 | #include "strbuf.h" |
40 | 41 | ||
41 | /* ===== ENCODING ===== */ | 42 | /* ===== ENCODING ===== */ |
42 | 43 | ||
44 | static void json_encode_exception(lua_State *l, strbuf_t *json, | ||
45 | char *location, int lindex) | ||
46 | |||
47 | { | ||
48 | strbuf_free(json); | ||
49 | |||
50 | luaL_error(l, "Cannot serialise %s: %s", location, | ||
51 | lua_typename(l, lua_type(l, lindex))); | ||
52 | } | ||
43 | 53 | ||
44 | /* JSON escape a character if required, or return NULL */ | 54 | /* JSON escape a character if required, or return NULL */ |
45 | static inline char *json_escape_char(int c) | 55 | static inline char *json_escape_char(int c) |
@@ -177,7 +187,8 @@ static void json_append_object(lua_State *l, strbuf_t *json) | |||
177 | json_append_string(l, json, -2); | 187 | json_append_string(l, json, -2); |
178 | strbuf_append_string(json, ": "); | 188 | strbuf_append_string(json, ": "); |
179 | } else { | 189 | } else { |
180 | die("Cannot serialise table key %s", lua_typename(l, lua_type(l, -2))); | 190 | json_encode_exception(l, json, "table key", -2); |
191 | /* never returns */ | ||
181 | } | 192 | } |
182 | 193 | ||
183 | /* table, key, value */ | 194 | /* table, key, value */ |
@@ -189,11 +200,7 @@ static void json_append_object(lua_State *l, strbuf_t *json) | |||
189 | strbuf_append_string(json, " }"); | 200 | strbuf_append_string(json, " }"); |
190 | } | 201 | } |
191 | 202 | ||
192 | /* Serialise Lua data into JSON string. | 203 | /* Serialise Lua data into JSON string. */ |
193 | * | ||
194 | * FIXME: | ||
195 | * - Error handling when cannot serialise key or value (return to script) | ||
196 | */ | ||
197 | static void json_append_data(lua_State *l, strbuf_t *json) | 204 | static void json_append_data(lua_State *l, strbuf_t *json) |
198 | { | 205 | { |
199 | int len; | 206 | int len; |
@@ -227,13 +234,14 @@ static void json_append_data(lua_State *l, strbuf_t *json) | |||
227 | break; | 234 | break; |
228 | } | 235 | } |
229 | default: | 236 | default: |
230 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA) | 237 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, |
231 | * cannot be serialised */ | 238 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ |
232 | /* FIXME: return error */ | 239 | json_encode_exception(l, json, "value", -1); |
233 | die("Cannot serialise %s", lua_typename(l, lua_type(l, -1))); | 240 | /* never returns */ |
234 | } | 241 | } |
235 | } | 242 | } |
236 | 243 | ||
244 | /* lua_json_encode can throw an exception */ | ||
237 | char *lua_json_encode(lua_State *l, int *len) | 245 | char *lua_json_encode(lua_State *l, int *len) |
238 | { | 246 | { |
239 | strbuf_t buf; | 247 | strbuf_t buf; |
@@ -247,6 +255,23 @@ char *lua_json_encode(lua_State *l, int *len) | |||
247 | return json; | 255 | return json; |
248 | } | 256 | } |
249 | 257 | ||
258 | /* lua_c_json_encode(object) must be called via lua_pcall(). | ||
259 | * It can be used to catch any encoder exceptions */ | ||
260 | int lua_c_json_encode(lua_State *l) | ||
261 | { | ||
262 | char *json; | ||
263 | int len; | ||
264 | |||
265 | lua_ensure_arg_count(l, "lua_c_json_encode", 1); | ||
266 | |||
267 | json = lua_json_encode(l, &len); | ||
268 | |||
269 | lua_pushlightuserdata(l, json); | ||
270 | lua_pushnumber(l, len); | ||
271 | |||
272 | return 2; | ||
273 | } | ||
274 | |||
250 | int lua_api_json_encode(lua_State *l) | 275 | int lua_api_json_encode(lua_State *l) |
251 | { | 276 | { |
252 | char *json; | 277 | char *json; |
@@ -493,7 +518,7 @@ static void json_next_token(json_parse_t *json, json_token_t *token) | |||
493 | 518 | ||
494 | /* This function does not return. | 519 | /* This function does not return. |
495 | * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED. | 520 | * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED. |
496 | * The only allowed exception is the temporary parser string | 521 | * The only supported exception is the temporary parser string |
497 | * json->tmp struct. | 522 | * json->tmp struct. |
498 | * json and token should exist on the stack somewhere. | 523 | * json and token should exist on the stack somewhere. |
499 | * luaL_error() will long_jmp and release the stack */ | 524 | * luaL_error() will long_jmp and release the stack */ |
@@ -627,21 +652,35 @@ void lua_json_decode(lua_State *l, const char *json_text) | |||
627 | strbuf_free(json.tmp); | 652 | strbuf_free(json.tmp); |
628 | } | 653 | } |
629 | 654 | ||
655 | /* lua_c_json_decode(string) must be called from C with lua_pcall() */ | ||
656 | int lua_c_json_decode(lua_State *l) | ||
657 | { | ||
658 | const char *json; | ||
659 | |||
660 | lua_ensure_arg_count(l, "json_c_json_decode", 1); | ||
661 | luaL_argcheck(l, lua_islightuserdata(l, 1), 1, | ||
662 | "missing lightuserdata"); | ||
663 | |||
664 | json = lua_touserdata(l, 1); | ||
665 | lua_pop(l, 1); | ||
666 | |||
667 | lua_json_decode(l, json); | ||
668 | |||
669 | return 1; | ||
670 | } | ||
671 | |||
630 | static int lua_api_json_decode(lua_State *l) | 672 | static int lua_api_json_decode(lua_State *l) |
631 | { | 673 | { |
632 | int i, n; | 674 | const char *json; |
633 | 675 | ||
634 | n = lua_gettop(l); | 676 | lua_ensure_arg_count(l, "json.decode", 1); |
677 | json = luaL_checkstring(l, 1); | ||
635 | 678 | ||
636 | for (i = 1; i <= n; i++) { | 679 | lua_json_decode(l, json); |
637 | if (lua_isstring(l, i)) { | ||
638 | lua_json_decode(l, lua_tostring(l, i)); | ||
639 | } else { | ||
640 | lua_pushnil(l); | ||
641 | } | ||
642 | } | ||
643 | 680 | ||
644 | return n; /* Number of results */ | 681 | lua_remove(l, 1); |
682 | |||
683 | return 1; | ||
645 | } | 684 | } |
646 | 685 | ||
647 | /* ===== INITIALISATION ===== */ | 686 | /* ===== INITIALISATION ===== */ |