diff options
-rw-r--r-- | lua_cjson.c | 141 |
1 files changed, 94 insertions, 47 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index cab1922..df3b71c 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -85,7 +85,11 @@ static const char *json_token_type_name[] = { | |||
85 | 85 | ||
86 | typedef struct { | 86 | typedef struct { |
87 | json_token_type_t ch2token[256]; | 87 | json_token_type_t ch2token[256]; |
88 | char ch2escape[256]; | 88 | char escape2char[256]; /* Decoding */ |
89 | #if 0 | ||
90 | char escapes[35][8]; /* Pre-generated escape string buffer */ | ||
91 | char *char2escape[256]; /* Encoding */ | ||
92 | #endif | ||
89 | strbuf_t encode_buf; | 93 | strbuf_t encode_buf; |
90 | int sparse_ratio; | 94 | int sparse_ratio; |
91 | int max_depth; | 95 | int max_depth; |
@@ -111,10 +115,49 @@ typedef struct { | |||
111 | int string_len; | 115 | int string_len; |
112 | } json_token_t; | 116 | } json_token_t; |
113 | 117 | ||
114 | /* ===== CONFIGURATION ===== */ | 118 | static const char *char2escape[256] = { |
119 | "\\u0000", "\\u0001", "\\u0002", "\\u0003", | ||
120 | "\\u0004", "\\u0005", "\\u0006", "\\u0007", | ||
121 | "\\b", "\\t", "\\n", "\\u000b", | ||
122 | "\\f", "\\r", "\\u000e", "\\u000f", | ||
123 | "\\u0010", "\\u0011", "\\u0012", "\\u0013", | ||
124 | "\\u0014", "\\u0015", "\\u0016", "\\u0017", | ||
125 | "\\u0018", "\\u0019", "\\u001a", "\\u001b", | ||
126 | "\\u001c", "\\u001d", "\\u001e", "\\u001f", | ||
127 | NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL, | ||
128 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
129 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
130 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
131 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
132 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
133 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
134 | NULL, NULL, NULL, NULL, "\\\\", NULL, NULL, NULL, | ||
135 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
136 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
137 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
138 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\u007f", | ||
139 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
140 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
141 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
142 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
143 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
144 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
145 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
146 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
147 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
148 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
149 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
150 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
151 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
152 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
153 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
154 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
155 | }; | ||
115 | 156 | ||
116 | static int json_config_key; | 157 | static int json_config_key; |
117 | 158 | ||
159 | /* ===== CONFIGURATION ===== */ | ||
160 | |||
118 | static json_config_t *json_fetch_config(lua_State *l) | 161 | static json_config_t *json_fetch_config(lua_State *l) |
119 | { | 162 | { |
120 | json_config_t *cfg; | 163 | json_config_t *cfg; |
@@ -201,6 +244,12 @@ static void json_create_config(lua_State *l) | |||
201 | 244 | ||
202 | cfg = lua_newuserdata(l, sizeof(*cfg)); | 245 | cfg = lua_newuserdata(l, sizeof(*cfg)); |
203 | 246 | ||
247 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; | ||
248 | cfg->max_depth = DEFAULT_MAX_DEPTH; | ||
249 | cfg->strict_numbers = 1; | ||
250 | |||
251 | /* Decoding init */ | ||
252 | |||
204 | /* Tag all characters as an error */ | 253 | /* Tag all characters as an error */ |
205 | for (i = 0; i < 256; i++) | 254 | for (i = 0; i < 256; i++) |
206 | cfg->ch2token[i] = T_ERROR; | 255 | cfg->ch2token[i] = T_ERROR; |
@@ -233,22 +282,45 @@ static void json_create_config(lua_State *l) | |||
233 | 282 | ||
234 | /* Lookup table for parsing escape characters */ | 283 | /* Lookup table for parsing escape characters */ |
235 | for (i = 0; i < 256; i++) | 284 | for (i = 0; i < 256; i++) |
236 | cfg->ch2escape[i] = 0; /* String error */ | 285 | cfg->escape2char[i] = 0; /* String error */ |
237 | cfg->ch2escape['"'] = '"'; | 286 | cfg->escape2char['"'] = '"'; |
238 | cfg->ch2escape['\\'] = '\\'; | 287 | cfg->escape2char['\\'] = '\\'; |
239 | cfg->ch2escape['/'] = '/'; | 288 | cfg->escape2char['/'] = '/'; |
240 | cfg->ch2escape['b'] = '\b'; | 289 | cfg->escape2char['b'] = '\b'; |
241 | cfg->ch2escape['t'] = '\t'; | 290 | cfg->escape2char['t'] = '\t'; |
242 | cfg->ch2escape['n'] = '\n'; | 291 | cfg->escape2char['n'] = '\n'; |
243 | cfg->ch2escape['f'] = '\f'; | 292 | cfg->escape2char['f'] = '\f'; |
244 | cfg->ch2escape['r'] = '\r'; | 293 | cfg->escape2char['r'] = '\r'; |
245 | cfg->ch2escape['u'] = 'u'; /* Unicode parsing required */ | 294 | cfg->escape2char['u'] = 'u'; /* Unicode parsing required */ |
246 | 295 | ||
247 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; | 296 | /* Encoding init */ |
248 | cfg->max_depth = DEFAULT_MAX_DEPTH; | ||
249 | cfg->strict_numbers = 1; | ||
250 | 297 | ||
251 | strbuf_init(&cfg->encode_buf, 0); | 298 | strbuf_init(&cfg->encode_buf, 0); |
299 | |||
300 | #if 0 | ||
301 | /* Initialise separate storage for pre-generated escape codes. | ||
302 | * Escapes 0-31 map directly, 34, 92, 127 follow afterwards to | ||
303 | * save memory. */ | ||
304 | for (i = 0 ; i < 32; i++) | ||
305 | sprintf(cfg->escapes[i], "\\u%04x", i); | ||
306 | strcpy(cfg->escapes[8], "\b"); /* Override simpler escapes */ | ||
307 | strcpy(cfg->escapes[9], "\t"); | ||
308 | strcpy(cfg->escapes[10], "\n"); | ||
309 | strcpy(cfg->escapes[12], "\f"); | ||
310 | strcpy(cfg->escapes[13], "\r"); | ||
311 | strcpy(cfg->escapes[32], "\\\""); /* chr(34) */ | ||
312 | strcpy(cfg->escapes[33], "\\\\"); /* chr(92) */ | ||
313 | sprintf(cfg->escapes[34], "\\u%04x", 127); /* char(127) */ | ||
314 | |||
315 | /* Initialise encoding escape lookup table */ | ||
316 | for (i = 0; i < 32; i++) | ||
317 | cfg->char2escape[i] = cfg->escapes[i]; | ||
318 | for (i = 32; i < 256; i++) | ||
319 | cfg->char2escape[i] = NULL; | ||
320 | cfg->char2escape[34] = cfg->escapes[32]; | ||
321 | cfg->char2escape[92] = cfg->escapes[33]; | ||
322 | cfg->char2escape[127] = cfg->escapes[34]; | ||
323 | #endif | ||
252 | } | 324 | } |
253 | 325 | ||
254 | /* ===== ENCODING ===== */ | 326 | /* ===== ENCODING ===== */ |
@@ -259,31 +331,6 @@ static void json_encode_exception(lua_State *l, int lindex, const char *reason) | |||
259 | lua_typename(l, lua_type(l, lindex)), reason); | 331 | lua_typename(l, lua_type(l, lindex)), reason); |
260 | } | 332 | } |
261 | 333 | ||
262 | /* JSON escape a character if required, or return NULL */ | ||
263 | static inline char *json_escape_char(int c) | ||
264 | { | ||
265 | switch(c) { | ||
266 | case 0: | ||
267 | return "\\u0000"; | ||
268 | case '\\': | ||
269 | return "\\\\"; | ||
270 | case '"': | ||
271 | return "\\\""; | ||
272 | case '\b': | ||
273 | return "\\b"; | ||
274 | case '\t': | ||
275 | return "\\t"; | ||
276 | case '\n': | ||
277 | return "\\n"; | ||
278 | case '\f': | ||
279 | return "\\f"; | ||
280 | case '\r': | ||
281 | return "\\r"; | ||
282 | } | ||
283 | |||
284 | return NULL; | ||
285 | } | ||
286 | |||
287 | /* json_append_string args: | 334 | /* json_append_string args: |
288 | * - lua_State | 335 | * - lua_State |
289 | * - JSON strbuf | 336 | * - JSON strbuf |
@@ -292,7 +339,7 @@ static inline char *json_escape_char(int c) | |||
292 | * Returns nothing. Doesn't remove string from Lua stack */ | 339 | * Returns nothing. Doesn't remove string from Lua stack */ |
293 | static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | 340 | static void json_append_string(lua_State *l, strbuf_t *json, int lindex) |
294 | { | 341 | { |
295 | const char *p; | 342 | const char *escstr; |
296 | int i; | 343 | int i; |
297 | const char *str; | 344 | const char *str; |
298 | size_t len; | 345 | size_t len; |
@@ -307,9 +354,9 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | |||
307 | 354 | ||
308 | strbuf_append_char_unsafe(json, '\"'); | 355 | strbuf_append_char_unsafe(json, '\"'); |
309 | for (i = 0; i < len; i++) { | 356 | for (i = 0; i < len; i++) { |
310 | p = json_escape_char(str[i]); | 357 | escstr = char2escape[(unsigned char)str[i]]; |
311 | if (p) | 358 | if (escstr) |
312 | strbuf_append_string(json, p); | 359 | strbuf_append_string(json, escstr); |
313 | else | 360 | else |
314 | strbuf_append_char_unsafe(json, str[i]); | 361 | strbuf_append_char_unsafe(json, str[i]); |
315 | } | 362 | } |
@@ -625,7 +672,7 @@ static void json_set_token_error(json_token_t *token, json_parse_t *json, | |||
625 | 672 | ||
626 | static void json_next_string_token(json_parse_t *json, json_token_t *token) | 673 | static void json_next_string_token(json_parse_t *json, json_token_t *token) |
627 | { | 674 | { |
628 | char *ch2escape = json->cfg->ch2escape; | 675 | char *escape2char = json->cfg->escape2char; |
629 | char ch; | 676 | char ch; |
630 | 677 | ||
631 | /* Caller must ensure a string is next */ | 678 | /* Caller must ensure a string is next */ |
@@ -650,7 +697,7 @@ static void json_next_string_token(json_parse_t *json, json_token_t *token) | |||
650 | ch = json->data[json->index + 1]; | 697 | ch = json->data[json->index + 1]; |
651 | 698 | ||
652 | /* Translate escape code and append to tmp string */ | 699 | /* Translate escape code and append to tmp string */ |
653 | ch = ch2escape[(unsigned char)ch]; | 700 | ch = escape2char[(unsigned char)ch]; |
654 | if (ch == 'u') { | 701 | if (ch == 'u') { |
655 | if (json_append_unicode_escape(json) == 0) | 702 | if (json_append_unicode_escape(json) == 0) |
656 | continue; | 703 | continue; |