diff options
| author | Mark Pulford <mark@kyne.com.au> | 2011-05-10 22:32:01 +0930 |
|---|---|---|
| committer | Mark Pulford <mark@kyne.com.au> | 2011-05-10 22:32:01 +0930 |
| commit | 126470cc7b6c2314c02805e4d00afe04b6b00312 (patch) | |
| tree | 9dd59bcc02307403410ef405b0f02bf39bd57560 /lua_cjson.c | |
| parent | c877da6c1f84b19cd2e7e8154b4a0d0e355745a0 (diff) | |
| download | lua-cjson-126470cc7b6c2314c02805e4d00afe04b6b00312.tar.gz lua-cjson-126470cc7b6c2314c02805e4d00afe04b6b00312.tar.bz2 lua-cjson-126470cc7b6c2314c02805e4d00afe04b6b00312.zip | |
Add runtime option for persistent encode buffer
Diffstat (limited to '')
| -rw-r--r-- | lua_cjson.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index f888644..50f27c2 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define DEFAULT_MAX_DEPTH 20 | 49 | #define DEFAULT_MAX_DEPTH 20 |
| 50 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 | 50 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 |
| 51 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 | 51 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 |
| 52 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 | ||
| 52 | 53 | ||
| 53 | typedef enum { | 54 | typedef enum { |
| 54 | T_OBJ_BEGIN, | 55 | T_OBJ_BEGIN, |
| @@ -101,6 +102,7 @@ typedef struct { | |||
| 101 | int encode_max_depth; | 102 | int encode_max_depth; |
| 102 | int encode_refuse_badnum; | 103 | int encode_refuse_badnum; |
| 103 | int decode_refuse_badnum; | 104 | int decode_refuse_badnum; |
| 105 | int encode_keep_buffer; | ||
| 104 | } json_config_t; | 106 | } json_config_t; |
| 105 | 107 | ||
| 106 | typedef struct { | 108 | typedef struct { |
| @@ -172,7 +174,7 @@ static json_config_t *json_fetch_config(lua_State *l) | |||
| 172 | lua_gettable(l, LUA_REGISTRYINDEX); | 174 | lua_gettable(l, LUA_REGISTRYINDEX); |
| 173 | cfg = lua_touserdata(l, -1); | 175 | cfg = lua_touserdata(l, -1); |
| 174 | if (!cfg) | 176 | if (!cfg) |
| 175 | luaL_error(l, "BUG: Unable to fetch cjson configuration"); | 177 | luaL_error(l, "BUG: Unable to fetch CJSON configuration"); |
| 176 | 178 | ||
| 177 | lua_pop(l, 1); | 179 | lua_pop(l, 1); |
| 178 | 180 | ||
| @@ -239,6 +241,23 @@ static int json_cfg_encode_max_depth(lua_State *l) | |||
| 239 | return 1; | 241 | return 1; |
| 240 | } | 242 | } |
| 241 | 243 | ||
| 244 | /* Configures JSON encoding buffer persistence */ | ||
| 245 | static int json_cfg_encode_keep_buffer(lua_State *l) | ||
| 246 | { | ||
| 247 | json_config_t *cfg; | ||
| 248 | |||
| 249 | json_verify_arg_count(l, 1); | ||
| 250 | cfg = json_fetch_config(l); | ||
| 251 | |||
| 252 | if (lua_gettop(l)) { | ||
| 253 | luaL_checktype(l, 1, LUA_TBOOLEAN); | ||
| 254 | cfg->encode_keep_buffer = lua_toboolean(l, 1); | ||
| 255 | } | ||
| 256 | |||
| 257 | lua_pushboolean(l, cfg->encode_keep_buffer); | ||
| 258 | |||
| 259 | return 1; | ||
| 260 | } | ||
| 242 | 261 | ||
| 243 | /* On argument: decode enum and set config variables | 262 | /* On argument: decode enum and set config variables |
| 244 | * **options must point to a NULL terminated array of 4 enums | 263 | * **options must point to a NULL terminated array of 4 enums |
| @@ -317,6 +336,7 @@ static void json_create_config(lua_State *l) | |||
| 317 | cfg->encode_max_depth = DEFAULT_MAX_DEPTH; | 336 | cfg->encode_max_depth = DEFAULT_MAX_DEPTH; |
| 318 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; | 337 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; |
| 319 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; | 338 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; |
| 339 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; | ||
| 320 | 340 | ||
| 321 | /* Decoding init */ | 341 | /* Decoding init */ |
| 322 | 342 | ||
| @@ -392,8 +412,11 @@ static void json_create_config(lua_State *l) | |||
| 392 | 412 | ||
| 393 | /* ===== ENCODING ===== */ | 413 | /* ===== ENCODING ===== */ |
| 394 | 414 | ||
| 395 | static void json_encode_exception(lua_State *l, int lindex, const char *reason) | 415 | static void json_encode_exception(lua_State *l, json_config_t *cfg, int lindex, |
| 416 | const char *reason) | ||
| 396 | { | 417 | { |
| 418 | if (!cfg->encode_keep_buffer) | ||
| 419 | strbuf_free(&cfg->encode_buf); | ||
| 397 | luaL_error(l, "Cannot serialise %s: %s", | 420 | luaL_error(l, "Cannot serialise %s: %s", |
| 398 | lua_typename(l, lua_type(l, lindex)), reason); | 421 | lua_typename(l, lua_type(l, lindex)), reason); |
| 399 | } | 422 | } |
| @@ -469,7 +492,7 @@ static int lua_array_length(lua_State *l, json_config_t *cfg) | |||
| 469 | max > items * cfg->encode_sparse_ratio && | 492 | max > items * cfg->encode_sparse_ratio && |
| 470 | max > cfg->encode_sparse_safe) { | 493 | max > cfg->encode_sparse_safe) { |
| 471 | if (!cfg->encode_sparse_convert) | 494 | if (!cfg->encode_sparse_convert) |
| 472 | json_encode_exception(l, -1, "excessively sparse array"); | 495 | json_encode_exception(l, cfg, -1, "excessively sparse array"); |
| 473 | 496 | ||
| 474 | return -1; | 497 | return -1; |
| 475 | } | 498 | } |
| @@ -482,6 +505,8 @@ static void json_encode_descend(lua_State *l, json_config_t *cfg) | |||
| 482 | cfg->current_depth++; | 505 | cfg->current_depth++; |
| 483 | 506 | ||
| 484 | if (cfg->current_depth > cfg->encode_max_depth) { | 507 | if (cfg->current_depth > cfg->encode_max_depth) { |
| 508 | if (!cfg->encode_keep_buffer) | ||
| 509 | strbuf_free(&cfg->encode_buf); | ||
| 485 | luaL_error(l, "Cannot serialise, excessive nesting (%d)", | 510 | luaL_error(l, "Cannot serialise, excessive nesting (%d)", |
| 486 | cfg->current_depth); | 511 | cfg->current_depth); |
| 487 | } | 512 | } |
| @@ -520,12 +545,12 @@ static void json_append_array(lua_State *l, json_config_t *cfg, strbuf_t *json, | |||
| 520 | } | 545 | } |
| 521 | 546 | ||
| 522 | static void json_append_number(lua_State *l, strbuf_t *json, int index, | 547 | static void json_append_number(lua_State *l, strbuf_t *json, int index, |
| 523 | int refuse_badnum) | 548 | json_config_t *cfg) |
| 524 | { | 549 | { |
| 525 | double num = lua_tonumber(l, index); | 550 | double num = lua_tonumber(l, index); |
| 526 | 551 | ||
| 527 | if (refuse_badnum && (isinf(num) || isnan(num))) | 552 | if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num))) |
| 528 | json_encode_exception(l, index, "must not be NaN or Inf"); | 553 | json_encode_exception(l, cfg, index, "must not be NaN or Inf"); |
| 529 | 554 | ||
| 530 | strbuf_append_number(json, num); | 555 | strbuf_append_number(json, num); |
| 531 | } | 556 | } |
| @@ -553,13 +578,13 @@ static void json_append_object(lua_State *l, json_config_t *cfg, | |||
| 553 | keytype = lua_type(l, -2); | 578 | keytype = lua_type(l, -2); |
| 554 | if (keytype == LUA_TNUMBER) { | 579 | if (keytype == LUA_TNUMBER) { |
| 555 | strbuf_append_char(json, '"'); | 580 | strbuf_append_char(json, '"'); |
| 556 | json_append_number(l, json, -2, cfg->encode_refuse_badnum); | 581 | json_append_number(l, json, -2, cfg); |
| 557 | strbuf_append_mem(json, "\":", 2); | 582 | strbuf_append_mem(json, "\":", 2); |
| 558 | } else if (keytype == LUA_TSTRING) { | 583 | } else if (keytype == LUA_TSTRING) { |
| 559 | json_append_string(l, json, -2); | 584 | json_append_string(l, json, -2); |
| 560 | strbuf_append_char(json, ':'); | 585 | strbuf_append_char(json, ':'); |
| 561 | } else { | 586 | } else { |
| 562 | json_encode_exception(l, -2, | 587 | json_encode_exception(l, cfg, -2, |
| 563 | "table key must be a number or string"); | 588 | "table key must be a number or string"); |
| 564 | /* never returns */ | 589 | /* never returns */ |
| 565 | } | 590 | } |
| @@ -585,7 +610,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json) | |||
| 585 | json_append_string(l, json, -1); | 610 | json_append_string(l, json, -1); |
| 586 | break; | 611 | break; |
| 587 | case LUA_TNUMBER: | 612 | case LUA_TNUMBER: |
| 588 | json_append_number(l, json, -1, cfg->encode_refuse_badnum); | 613 | json_append_number(l, json, -1, cfg); |
| 589 | break; | 614 | break; |
| 590 | case LUA_TBOOLEAN: | 615 | case LUA_TBOOLEAN: |
| 591 | if (lua_toboolean(l, -1)) | 616 | if (lua_toboolean(l, -1)) |
| @@ -611,7 +636,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json) | |||
| 611 | default: | 636 | default: |
| 612 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, | 637 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, |
| 613 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ | 638 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ |
| 614 | json_encode_exception(l, -1, "type not supported"); | 639 | json_encode_exception(l, cfg, -1, "type not supported"); |
| 615 | /* never returns */ | 640 | /* never returns */ |
| 616 | } | 641 | } |
| 617 | } | 642 | } |
| @@ -629,14 +654,21 @@ static int json_encode(lua_State *l) | |||
| 629 | cfg = json_fetch_config(l); | 654 | cfg = json_fetch_config(l); |
| 630 | cfg->current_depth = 0; | 655 | cfg->current_depth = 0; |
| 631 | 656 | ||
| 632 | /* Reset persistent encode_buf. Avoids temporary allocation | 657 | /* Reset the persistent buffer if it exists. |
| 633 | * for a single call. */ | 658 | * Otherwise allocate a new buffer. */ |
| 634 | strbuf_reset(&cfg->encode_buf); | 659 | if (strbuf_allocated(&cfg->encode_buf)) |
| 660 | strbuf_reset(&cfg->encode_buf); | ||
| 661 | else | ||
| 662 | strbuf_init(&cfg->encode_buf, 0); | ||
| 663 | |||
| 635 | json_append_data(l, cfg, &cfg->encode_buf); | 664 | json_append_data(l, cfg, &cfg->encode_buf); |
| 636 | json = strbuf_string(&cfg->encode_buf, &len); | 665 | json = strbuf_string(&cfg->encode_buf, &len); |
| 637 | 666 | ||
| 638 | lua_pushlstring(l, json, len); | 667 | lua_pushlstring(l, json, len); |
| 639 | 668 | ||
| 669 | if (!cfg->encode_keep_buffer) | ||
| 670 | strbuf_free(&cfg->encode_buf); | ||
| 671 | |||
| 640 | return 1; | 672 | return 1; |
| 641 | } | 673 | } |
| 642 | 674 | ||
| @@ -1176,7 +1208,7 @@ static int json_decode(lua_State *l) | |||
| 1176 | /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3) | 1208 | /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3) |
| 1177 | * | 1209 | * |
| 1178 | * CJSON can support any simple data type, hence only the first | 1210 | * CJSON can support any simple data type, hence only the first |
| 1179 | * character is guaranteed to be ASCII (at worst: "). This is | 1211 | * character is guaranteed to be ASCII (at worst: '"'). This is |
| 1180 | * still enough to detect whether the wrong encoding is in use. */ | 1212 | * still enough to detect whether the wrong encoding is in use. */ |
| 1181 | if (len >= 2 && (!json[0] || !json[1])) | 1213 | if (len >= 2 && (!json[0] || !json[1])) |
| 1182 | luaL_error(l, "JSON parser does not support UTF-16 or UTF-32"); | 1214 | luaL_error(l, "JSON parser does not support UTF-16 or UTF-32"); |
| @@ -1195,6 +1227,7 @@ int luaopen_cjson(lua_State *l) | |||
| 1195 | { "decode", json_decode }, | 1227 | { "decode", json_decode }, |
| 1196 | { "encode_sparse_array", json_cfg_encode_sparse_array }, | 1228 | { "encode_sparse_array", json_cfg_encode_sparse_array }, |
| 1197 | { "encode_max_depth", json_cfg_encode_max_depth }, | 1229 | { "encode_max_depth", json_cfg_encode_max_depth }, |
| 1230 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, | ||
| 1198 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, | 1231 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, |
| 1199 | { NULL, NULL } | 1232 | { NULL, NULL } |
| 1200 | }; | 1233 | }; |
