Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpx/lua-cjson.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
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
LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
#CFLAGS ?= -g -Wall -pedantic -fno-inline
-CFLAGS ?= -g -O2 -Wall -pedantic
+CFLAGS ?= -g -O3 -Wall -pedantic
override CFLAGS += -fpic -I$(LUA_INCLUDE_DIR) -DVERSION=\"$(CJSON_VERSION)\"
LDFLAGS += -lm
diff --git a/NEWS b/NEWS
index fb71cec..707a9a9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
Version 1.0.1 (May 10 2011)
* Added build support for OSX
* Removed unnecessary whitespace from JSON output
+* Added cjson.encode_keep_buffer()
Version 1.0 (May 9 2011)
* Initial release.
diff --git a/README b/README
index 1ff12d9..3fa7595 100644
--- a/README
+++ b/README
@@ -34,8 +34,7 @@ Build requirements:
Or:
- LuaJIT (http://www.luajit.org/)
-The included Makefile should be reviewed. Updated the Makefile to suit
-your platform and Lua header/library directories. Then:
+Review and update the included Makefile to suit your platform. Then:
# make
# make install
@@ -66,6 +65,7 @@ Synopsis
setting = cjson.refuse_invalid_numbers([setting])
depth = cjson.encode_max_depth([depth])
convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]])
+ keep = cjson.encode_keep_buffer([keep])
Encoding
@@ -204,6 +204,19 @@ the application. Eg:
a = {}; b = { a }; a[1] = b
+Persistent encoding buffer
+-------------------------
+
+ keep = cjson.keep_encode_buffer([keep])
+ -- "keep" must be a boolean
+
+By default, CJSON will reuse the JSON encoding buffer to improve
+performance. The buffer will grow to the largest size required and is
+not freed until CJSON is garbage collected. Setting this option to
+"false" will cause the buffer to be freed after each call to
+cjson.encode().
+
+
References
==========
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 @@
#define DEFAULT_MAX_DEPTH 20
#define DEFAULT_ENCODE_REFUSE_BADNUM 1
#define DEFAULT_DECODE_REFUSE_BADNUM 0
+#define DEFAULT_ENCODE_KEEP_BUFFER 1
typedef enum {
T_OBJ_BEGIN,
@@ -101,6 +102,7 @@ typedef struct {
int encode_max_depth;
int encode_refuse_badnum;
int decode_refuse_badnum;
+ int encode_keep_buffer;
} json_config_t;
typedef struct {
@@ -172,7 +174,7 @@ static json_config_t *json_fetch_config(lua_State *l)
lua_gettable(l, LUA_REGISTRYINDEX);
cfg = lua_touserdata(l, -1);
if (!cfg)
- luaL_error(l, "BUG: Unable to fetch cjson configuration");
+ luaL_error(l, "BUG: Unable to fetch CJSON configuration");
lua_pop(l, 1);
@@ -239,6 +241,23 @@ static int json_cfg_encode_max_depth(lua_State *l)
return 1;
}
+/* Configures JSON encoding buffer persistence */
+static int json_cfg_encode_keep_buffer(lua_State *l)
+{
+ json_config_t *cfg;
+
+ json_verify_arg_count(l, 1);
+ cfg = json_fetch_config(l);
+
+ if (lua_gettop(l)) {
+ luaL_checktype(l, 1, LUA_TBOOLEAN);
+ cfg->encode_keep_buffer = lua_toboolean(l, 1);
+ }
+
+ lua_pushboolean(l, cfg->encode_keep_buffer);
+
+ return 1;
+}
/* On argument: decode enum and set config variables
* **options must point to a NULL terminated array of 4 enums
@@ -317,6 +336,7 @@ static void json_create_config(lua_State *l)
cfg->encode_max_depth = DEFAULT_MAX_DEPTH;
cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM;
cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM;
+ cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;
/* Decoding init */
@@ -392,8 +412,11 @@ static void json_create_config(lua_State *l)
/* ===== ENCODING ===== */
-static void json_encode_exception(lua_State *l, int lindex, const char *reason)
+static void json_encode_exception(lua_State *l, json_config_t *cfg, int lindex,
+ const char *reason)
{
+ if (!cfg->encode_keep_buffer)
+ strbuf_free(&cfg->encode_buf);
luaL_error(l, "Cannot serialise %s: %s",
lua_typename(l, lua_type(l, lindex)), reason);
}
@@ -469,7 +492,7 @@ static int lua_array_length(lua_State *l, json_config_t *cfg)
max > items * cfg->encode_sparse_ratio &&
max > cfg->encode_sparse_safe) {
if (!cfg->encode_sparse_convert)
- json_encode_exception(l, -1, "excessively sparse array");
+ json_encode_exception(l, cfg, -1, "excessively sparse array");
return -1;
}
@@ -482,6 +505,8 @@ static void json_encode_descend(lua_State *l, json_config_t *cfg)
cfg->current_depth++;
if (cfg->current_depth > cfg->encode_max_depth) {
+ if (!cfg->encode_keep_buffer)
+ strbuf_free(&cfg->encode_buf);
luaL_error(l, "Cannot serialise, excessive nesting (%d)",
cfg->current_depth);
}
@@ -520,12 +545,12 @@ static void json_append_array(lua_State *l, json_config_t *cfg, strbuf_t *json,
}
static void json_append_number(lua_State *l, strbuf_t *json, int index,
- int refuse_badnum)
+ json_config_t *cfg)
{
double num = lua_tonumber(l, index);
- if (refuse_badnum && (isinf(num) || isnan(num)))
- json_encode_exception(l, index, "must not be NaN or Inf");
+ if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num)))
+ json_encode_exception(l, cfg, index, "must not be NaN or Inf");
strbuf_append_number(json, num);
}
@@ -553,13 +578,13 @@ static void json_append_object(lua_State *l, json_config_t *cfg,
keytype = lua_type(l, -2);
if (keytype == LUA_TNUMBER) {
strbuf_append_char(json, '"');
- json_append_number(l, json, -2, cfg->encode_refuse_badnum);
+ json_append_number(l, json, -2, cfg);
strbuf_append_mem(json, "\":", 2);
} else if (keytype == LUA_TSTRING) {
json_append_string(l, json, -2);
strbuf_append_char(json, ':');
} else {
- json_encode_exception(l, -2,
+ json_encode_exception(l, cfg, -2,
"table key must be a number or string");
/* never returns */
}
@@ -585,7 +610,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json)
json_append_string(l, json, -1);
break;
case LUA_TNUMBER:
- json_append_number(l, json, -1, cfg->encode_refuse_badnum);
+ json_append_number(l, json, -1, cfg);
break;
case LUA_TBOOLEAN:
if (lua_toboolean(l, -1))
@@ -611,7 +636,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json)
default:
/* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,
* and LUA_TLIGHTUSERDATA) cannot be serialised */
- json_encode_exception(l, -1, "type not supported");
+ json_encode_exception(l, cfg, -1, "type not supported");
/* never returns */
}
}
@@ -629,14 +654,21 @@ static int json_encode(lua_State *l)
cfg = json_fetch_config(l);
cfg->current_depth = 0;
- /* Reset persistent encode_buf. Avoids temporary allocation
- * for a single call. */
- strbuf_reset(&cfg->encode_buf);
+ /* Reset the persistent buffer if it exists.
+ * Otherwise allocate a new buffer. */
+ if (strbuf_allocated(&cfg->encode_buf))
+ strbuf_reset(&cfg->encode_buf);
+ else
+ strbuf_init(&cfg->encode_buf, 0);
+
json_append_data(l, cfg, &cfg->encode_buf);
json = strbuf_string(&cfg->encode_buf, &len);
lua_pushlstring(l, json, len);
+ if (!cfg->encode_keep_buffer)
+ strbuf_free(&cfg->encode_buf);
+
return 1;
}
@@ -1176,7 +1208,7 @@ static int json_decode(lua_State *l)
/* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)
*
* CJSON can support any simple data type, hence only the first
- * character is guaranteed to be ASCII (at worst: "). This is
+ * character is guaranteed to be ASCII (at worst: '"'). This is
* still enough to detect whether the wrong encoding is in use. */
if (len >= 2 && (!json[0] || !json[1]))
luaL_error(l, "JSON parser does not support UTF-16 or UTF-32");
@@ -1195,6 +1227,7 @@ int luaopen_cjson(lua_State *l)
{ "decode", json_decode },
{ "encode_sparse_array", json_cfg_encode_sparse_array },
{ "encode_max_depth", json_cfg_encode_max_depth },
+ { "encode_keep_buffer", json_cfg_encode_keep_buffer },
{ "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers },
{ NULL, NULL }
};
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)
}
}
+/* If strbuf_t has not been dynamically allocated, strbuf_free() can
+ * be called any number of times strbuf_init() */
void strbuf_free(strbuf_t *s)
{
debug_stats(s);
- if (s->buf)
+ if (s->buf) {
free(s->buf);
+ s->buf = NULL;
+ }
if (s->dynamic)
free(s);
}
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)
s->length = 0;
}
+static inline int strbuf_allocated(strbuf_t *s)
+{
+ return s->buf != NULL;
+}
+
/* Return bytes remaining in the string buffer
* Ensure there is space for a NULL terminator. */
static 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 = {
{ json.decode, { '[ 0.4eg10 ]' },
false, { "Expected comma or array end but found invalid token at character 6" } },
{ json.decode, { json_nested },
- false, { "stack overflow (too many nested data structures)" } }
+ false, { "Too many nested data structures" } }
}
local escape_tests = {