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
Diffstat (limited to '')
| -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 ===== */ |
