aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--NEWS1
-rw-r--r--README17
-rw-r--r--lua_cjson.c61
-rw-r--r--strbuf.c6
-rw-r--r--strbuf.h5
-rwxr-xr-xtests/test.lua2
7 files changed, 75 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index e2d5339..e96d736 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LUA_INCLUDE_DIR ?= $(PREFIX)/include
16LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) 16LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
17 17
18#CFLAGS ?= -g -Wall -pedantic -fno-inline 18#CFLAGS ?= -g -Wall -pedantic -fno-inline
19CFLAGS ?= -g -O2 -Wall -pedantic 19CFLAGS ?= -g -O3 -Wall -pedantic
20override CFLAGS += -fpic -I$(LUA_INCLUDE_DIR) -DVERSION=\"$(CJSON_VERSION)\" 20override CFLAGS += -fpic -I$(LUA_INCLUDE_DIR) -DVERSION=\"$(CJSON_VERSION)\"
21LDFLAGS += -lm 21LDFLAGS += -lm
22 22
diff --git a/NEWS b/NEWS
index fb71cec..707a9a9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
1Version 1.0.1 (May 10 2011) 1Version 1.0.1 (May 10 2011)
2* Added build support for OSX 2* Added build support for OSX
3* Removed unnecessary whitespace from JSON output 3* Removed unnecessary whitespace from JSON output
4* Added cjson.encode_keep_buffer()
4 5
5Version 1.0 (May 9 2011) 6Version 1.0 (May 9 2011)
6* Initial release. 7* Initial release.
diff --git a/README b/README
index 1ff12d9..3fa7595 100644
--- a/README
+++ b/README
@@ -34,8 +34,7 @@ Build requirements:
34Or: 34Or:
35- LuaJIT (http://www.luajit.org/) 35- LuaJIT (http://www.luajit.org/)
36 36
37The included Makefile should be reviewed. Updated the Makefile to suit 37Review and update the included Makefile to suit your platform. Then:
38your platform and Lua header/library directories. Then:
39 38
40 # make 39 # make
41 # make install 40 # make install
@@ -66,6 +65,7 @@ Synopsis
66 setting = cjson.refuse_invalid_numbers([setting]) 65 setting = cjson.refuse_invalid_numbers([setting])
67 depth = cjson.encode_max_depth([depth]) 66 depth = cjson.encode_max_depth([depth])
68 convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]]) 67 convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]])
68 keep = cjson.encode_keep_buffer([keep])
69 69
70 70
71Encoding 71Encoding
@@ -204,6 +204,19 @@ the application. Eg:
204 a = {}; b = { a }; a[1] = b 204 a = {}; b = { a }; a[1] = b
205 205
206 206
207Persistent encoding buffer
208-------------------------
209
210 keep = cjson.keep_encode_buffer([keep])
211 -- "keep" must be a boolean
212
213By default, CJSON will reuse the JSON encoding buffer to improve
214performance. The buffer will grow to the largest size required and is
215not freed until CJSON is garbage collected. Setting this option to
216"false" will cause the buffer to be freed after each call to
217cjson.encode().
218
219
207References 220References
208========== 221==========
209 222
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
53typedef enum { 54typedef 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
106typedef struct { 108typedef 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 */
245static 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
395static void json_encode_exception(lua_State *l, int lindex, const char *reason) 415static 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
522static void json_append_number(lua_State *l, strbuf_t *json, int index, 547static 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 };
diff --git a/strbuf.c b/strbuf.c
index 7a53a52..a850d41 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -99,12 +99,16 @@ static inline void debug_stats(strbuf_t *s)
99 } 99 }
100} 100}
101 101
102/* If strbuf_t has not been dynamically allocated, strbuf_free() can
103 * be called any number of times strbuf_init() */
102void strbuf_free(strbuf_t *s) 104void strbuf_free(strbuf_t *s)
103{ 105{
104 debug_stats(s); 106 debug_stats(s);
105 107
106 if (s->buf) 108 if (s->buf) {
107 free(s->buf); 109 free(s->buf);
110 s->buf = NULL;
111 }
108 if (s->dynamic) 112 if (s->dynamic)
109 free(s); 113 free(s);
110} 114}
diff --git a/strbuf.h b/strbuf.h
index 7829c63..28512f2 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -78,6 +78,11 @@ static inline void strbuf_reset(strbuf_t *s)
78 s->length = 0; 78 s->length = 0;
79} 79}
80 80
81static inline int strbuf_allocated(strbuf_t *s)
82{
83 return s->buf != NULL;
84}
85
81/* Return bytes remaining in the string buffer 86/* Return bytes remaining in the string buffer
82 * Ensure there is space for a NULL terminator. */ 87 * Ensure there is space for a NULL terminator. */
83static inline int strbuf_empty_length(strbuf_t *s) 88static inline int strbuf_empty_length(strbuf_t *s)
diff --git a/tests/test.lua b/tests/test.lua
index 1408bb9..4bb62be 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -181,7 +181,7 @@ local decode_error_tests = {
181 { json.decode, { '[ 0.4eg10 ]' }, 181 { json.decode, { '[ 0.4eg10 ]' },
182 false, { "Expected comma or array end but found invalid token at character 6" } }, 182 false, { "Expected comma or array end but found invalid token at character 6" } },
183 { json.decode, { json_nested }, 183 { json.decode, { json_nested },
184 false, { "stack overflow (too many nested data structures)" } } 184 false, { "Too many nested data structures" } }
185} 185}
186 186
187local escape_tests = { 187local escape_tests = {