aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-05-03 22:47:09 +0930
committerMark Pulford <mark@kyne.com.au>2011-05-03 22:47:09 +0930
commite1001b2f316448ce171434f31410ffc150877a82 (patch)
tree69622033d622d5ee7bafc5aaa888da345e5143a8
parent4cfafe0883da22cc020bb4e92d652ce16500b104 (diff)
downloadlua-cjson-e1001b2f316448ce171434f31410ffc150877a82.tar.gz
lua-cjson-e1001b2f316448ce171434f31410ffc150877a82.tar.bz2
lua-cjson-e1001b2f316448ce171434f31410ffc150877a82.zip
Preallocate temporary decode string buffer
The preallocated buffer removes the need for buffer length checks while processing strings and results in a 10 - 15% speedup.
-rw-r--r--lua_cjson.c25
-rw-r--r--strbuf.h6
2 files changed, 20 insertions, 11 deletions
diff --git a/lua_cjson.c b/lua_cjson.c
index 39e22ad..5f518f6 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -25,15 +25,13 @@
25/* Caveats: 25/* Caveats:
26 * - JSON "null" values are represented as lightuserdata since Lua 26 * - JSON "null" values are represented as lightuserdata since Lua
27 * tables cannot contain "nil". Compare with cjson.null. 27 * tables cannot contain "nil". Compare with cjson.null.
28 * - Only standard JSON escapes and \u0000 are used when encoding
29 * JSON. Most unprintable characters are not escaped.
30 * - Invalid UTF-8 characters are not detected and will be passed 28 * - Invalid UTF-8 characters are not detected and will be passed
31 * untouched. 29 * untouched.
32 * - Javascript comments are not part of the JSON spec, and are not 30 * - Javascript comments are not part of the JSON spec, and are not
33 * supported. 31 * supported.
34 * 32 *
35 * Note: Decoding is slower than encoding. Lua probably spends 33 * Note: Decoding is slower than encoding. Lua spends significant
36 * significant time rehashing tables when parsing JSON since it is 34 * time (30%) managing tables when parsing JSON since it is
37 * difficult to know object/array sizes ahead of time. 35 * difficult to know object/array sizes ahead of time.
38 */ 36 */
39 37
@@ -655,8 +653,8 @@ static int json_append_unicode_escape(json_parse_t *json)
655 return -1; 653 return -1;
656 } 654 }
657 655
658 /* Append bytes and advance counter */ 656 /* Append bytes and advance index */
659 strbuf_append_mem(json->tmp, utf8, len); 657 strbuf_append_mem_unsafe(json->tmp, utf8, len);
660 json->index += 6; 658 json->index += 6;
661 659
662 return 0; 660 return 0;
@@ -716,7 +714,7 @@ static void json_next_string_token(json_parse_t *json, json_token_t *token)
716 } 714 }
717 /* Append normal character or translated single character 715 /* Append normal character or translated single character
718 * Unicode escapes are handled above */ 716 * Unicode escapes are handled above */
719 strbuf_append_char(json->tmp, ch); 717 strbuf_append_char_unsafe(json->tmp, ch);
720 json->index++; 718 json->index++;
721 } 719 }
722 json->index++; /* Eat final quote (") */ 720 json->index++; /* Eat final quote (") */
@@ -1000,7 +998,7 @@ static void json_process_value(lua_State *l, json_parse_t *json, json_token_t *t
1000} 998}
1001 999
1002/* json_text must be null terminated string */ 1000/* json_text must be null terminated string */
1003static void lua_json_decode(lua_State *l, const char *json_text) 1001static void lua_json_decode(lua_State *l, const char *json_text, int json_len)
1004{ 1002{
1005 json_parse_t json; 1003 json_parse_t json;
1006 json_token_t token; 1004 json_token_t token;
@@ -1008,7 +1006,11 @@ static void lua_json_decode(lua_State *l, const char *json_text)
1008 json.cfg = json_fetch_config(l); 1006 json.cfg = json_fetch_config(l);
1009 json.data = json_text; 1007 json.data = json_text;
1010 json.index = 0; 1008 json.index = 0;
1011 json.tmp = strbuf_new(0); 1009
1010 /* Ensure the temporary buffer can hold the entire string.
1011 * This means we no longer need to do length checks since the decoded
1012 * string must be smaller than the entire json string */
1013 json.tmp = strbuf_new(json_len);
1012 1014
1013 json_next_token(&json, &token); 1015 json_next_token(&json, &token);
1014 json_process_value(l, &json, &token); 1016 json_process_value(l, &json, &token);
@@ -1025,11 +1027,12 @@ static void lua_json_decode(lua_State *l, const char *json_text)
1025static int json_decode(lua_State *l) 1027static int json_decode(lua_State *l)
1026{ 1028{
1027 const char *json; 1029 const char *json;
1030 size_t len;
1028 1031
1029 luaL_argcheck(l, lua_gettop(l) <= 1, 2, "found too many arguments"); 1032 luaL_argcheck(l, lua_gettop(l) <= 1, 2, "found too many arguments");
1030 json = luaL_checkstring(l, 1); 1033 json = luaL_checklstring(l, 1, &len);
1031 1034
1032 lua_json_decode(l, json); 1035 lua_json_decode(l, json, len);
1033 1036
1034 return 1; 1037 return 1;
1035} 1038}
diff --git a/strbuf.h b/strbuf.h
index 85f3261..7829c63 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -114,6 +114,12 @@ static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
114 s->length += len; 114 s->length += len;
115} 115}
116 116
117static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
118{
119 memcpy(s->buf + s->length, c, len);
120 s->length += len;
121}
122
117static inline void strbuf_ensure_null(strbuf_t *s) 123static inline void strbuf_ensure_null(strbuf_t *s)
118{ 124{
119 s->buf[s->length] = 0; 125 s->buf[s->length] = 0;