diff options
Diffstat (limited to 'lua_cjson.c')
-rw-r--r-- | lua_cjson.c | 1344 |
1 files changed, 1344 insertions, 0 deletions
diff --git a/lua_cjson.c b/lua_cjson.c new file mode 100644 index 0000000..708e695 --- /dev/null +++ b/lua_cjson.c | |||
@@ -0,0 +1,1344 @@ | |||
1 | /* CJSON - JSON support for Lua | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Mark Pulford <mark@kyne.com.au> | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining | ||
6 | * a copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be | ||
14 | * included in all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
19 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
20 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
21 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
22 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
23 | */ | ||
24 | |||
25 | /* Caveats: | ||
26 | * - JSON "null" values are represented as lightuserdata since Lua | ||
27 | * tables cannot contain "nil". Compare with cjson.null. | ||
28 | * - Invalid UTF-8 characters are not detected and will be passed | ||
29 | * untouched. If required, UTF-8 error checking should be done | ||
30 | * outside this library. | ||
31 | * - Javascript comments are not part of the JSON spec, and are not | ||
32 | * currently supported. | ||
33 | * | ||
34 | * Note: Decoding is slower than encoding. Lua spends significant | ||
35 | * time (30%) managing tables when parsing JSON since it is | ||
36 | * difficult to know object/array sizes ahead of time. | ||
37 | */ | ||
38 | |||
39 | #include <assert.h> | ||
40 | #include <string.h> | ||
41 | #include <math.h> | ||
42 | #include <lua.h> | ||
43 | #include <lauxlib.h> | ||
44 | |||
45 | #include "strbuf.h" | ||
46 | #include "fpconv.h" | ||
47 | |||
48 | #ifndef CJSON_MODNAME | ||
49 | #define CJSON_MODNAME "cjson" | ||
50 | #endif | ||
51 | |||
52 | #ifndef CJSON_VERSION | ||
53 | #define CJSON_VERSION "1.0devel" | ||
54 | #endif | ||
55 | |||
56 | /* Workaround for Solaris platforms missing isinf() */ | ||
57 | #if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF)) | ||
58 | #define isinf(x) (!isnan(x) && isnan((x) - (x))) | ||
59 | #endif | ||
60 | |||
61 | #define DEFAULT_SPARSE_CONVERT 0 | ||
62 | #define DEFAULT_SPARSE_RATIO 2 | ||
63 | #define DEFAULT_SPARSE_SAFE 10 | ||
64 | #define DEFAULT_MAX_DEPTH 20 | ||
65 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 | ||
66 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 | ||
67 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 | ||
68 | #define DEFAULT_ENCODE_NUMBER_PRECISION 14 | ||
69 | |||
70 | #ifdef DISABLE_INVALID_NUMBERS | ||
71 | #undef DEFAULT_DECODE_REFUSE_BADNUM | ||
72 | #define DEFAULT_DECODE_REFUSE_BADNUM 1 | ||
73 | #endif | ||
74 | |||
75 | typedef enum { | ||
76 | T_OBJ_BEGIN, | ||
77 | T_OBJ_END, | ||
78 | T_ARR_BEGIN, | ||
79 | T_ARR_END, | ||
80 | T_STRING, | ||
81 | T_NUMBER, | ||
82 | T_BOOLEAN, | ||
83 | T_NULL, | ||
84 | T_COLON, | ||
85 | T_COMMA, | ||
86 | T_END, | ||
87 | T_WHITESPACE, | ||
88 | T_ERROR, | ||
89 | T_UNKNOWN | ||
90 | } json_token_type_t; | ||
91 | |||
92 | static const char *json_token_type_name[] = { | ||
93 | "T_OBJ_BEGIN", | ||
94 | "T_OBJ_END", | ||
95 | "T_ARR_BEGIN", | ||
96 | "T_ARR_END", | ||
97 | "T_STRING", | ||
98 | "T_NUMBER", | ||
99 | "T_BOOLEAN", | ||
100 | "T_NULL", | ||
101 | "T_COLON", | ||
102 | "T_COMMA", | ||
103 | "T_END", | ||
104 | "T_WHITESPACE", | ||
105 | "T_ERROR", | ||
106 | "T_UNKNOWN", | ||
107 | NULL | ||
108 | }; | ||
109 | |||
110 | typedef struct { | ||
111 | json_token_type_t ch2token[256]; | ||
112 | char escape2char[256]; /* Decoding */ | ||
113 | |||
114 | /* encode_buf is only allocated and used when | ||
115 | * encode_keep_buffer is set */ | ||
116 | strbuf_t encode_buf; | ||
117 | |||
118 | int encode_sparse_convert; | ||
119 | int encode_sparse_ratio; | ||
120 | int encode_sparse_safe; | ||
121 | int encode_max_depth; | ||
122 | int encode_refuse_badnum; | ||
123 | int decode_refuse_badnum; | ||
124 | int encode_keep_buffer; | ||
125 | int encode_number_precision; | ||
126 | } json_config_t; | ||
127 | |||
128 | typedef struct { | ||
129 | const char *data; | ||
130 | int index; | ||
131 | strbuf_t *tmp; /* Temporary storage for strings */ | ||
132 | json_config_t *cfg; | ||
133 | } json_parse_t; | ||
134 | |||
135 | typedef struct { | ||
136 | json_token_type_t type; | ||
137 | int index; | ||
138 | union { | ||
139 | const char *string; | ||
140 | double number; | ||
141 | int boolean; | ||
142 | } value; | ||
143 | int string_len; | ||
144 | } json_token_t; | ||
145 | |||
146 | static const char *char2escape[256] = { | ||
147 | "\\u0000", "\\u0001", "\\u0002", "\\u0003", | ||
148 | "\\u0004", "\\u0005", "\\u0006", "\\u0007", | ||
149 | "\\b", "\\t", "\\n", "\\u000b", | ||
150 | "\\f", "\\r", "\\u000e", "\\u000f", | ||
151 | "\\u0010", "\\u0011", "\\u0012", "\\u0013", | ||
152 | "\\u0014", "\\u0015", "\\u0016", "\\u0017", | ||
153 | "\\u0018", "\\u0019", "\\u001a", "\\u001b", | ||
154 | "\\u001c", "\\u001d", "\\u001e", "\\u001f", | ||
155 | NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL, | ||
156 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\/", | ||
157 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
158 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
159 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
160 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
161 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
162 | NULL, NULL, NULL, NULL, "\\\\", NULL, NULL, NULL, | ||
163 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
164 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
165 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
166 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\u007f", | ||
167 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
168 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
169 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
170 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
171 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
172 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
173 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
174 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
175 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
176 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
177 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
178 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
179 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
180 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
181 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
182 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
183 | }; | ||
184 | |||
185 | /* ===== CONFIGURATION ===== */ | ||
186 | |||
187 | static json_config_t *json_fetch_config(lua_State *l) | ||
188 | { | ||
189 | json_config_t *cfg; | ||
190 | |||
191 | cfg = lua_touserdata(l, lua_upvalueindex(1)); | ||
192 | if (!cfg) | ||
193 | luaL_error(l, "BUG: Unable to fetch CJSON configuration"); | ||
194 | |||
195 | return cfg; | ||
196 | } | ||
197 | |||
198 | static void json_verify_arg_count(lua_State *l, int args) | ||
199 | { | ||
200 | luaL_argcheck(l, lua_gettop(l) <= args, args + 1, | ||
201 | "found too many arguments"); | ||
202 | } | ||
203 | |||
204 | /* Configures handling of extremely sparse arrays: | ||
205 | * convert: Convert extremely sparse arrays into objects? Otherwise error. | ||
206 | * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio | ||
207 | * safe: Always use an array when the max index <= safe */ | ||
208 | static int json_cfg_encode_sparse_array(lua_State *l) | ||
209 | { | ||
210 | json_config_t *cfg; | ||
211 | int val; | ||
212 | |||
213 | json_verify_arg_count(l, 3); | ||
214 | cfg = json_fetch_config(l); | ||
215 | |||
216 | switch (lua_gettop(l)) { | ||
217 | case 3: | ||
218 | val = luaL_checkinteger(l, 3); | ||
219 | luaL_argcheck(l, val >= 0, 3, "expected integer >= 0"); | ||
220 | cfg->encode_sparse_safe = val; | ||
221 | case 2: | ||
222 | val = luaL_checkinteger(l, 2); | ||
223 | luaL_argcheck(l, val >= 0, 2, "expected integer >= 0"); | ||
224 | cfg->encode_sparse_ratio = val; | ||
225 | case 1: | ||
226 | luaL_argcheck(l, lua_isboolean(l, 1), 1, "expected boolean"); | ||
227 | cfg->encode_sparse_convert = lua_toboolean(l, 1); | ||
228 | } | ||
229 | |||
230 | lua_pushboolean(l, cfg->encode_sparse_convert); | ||
231 | lua_pushinteger(l, cfg->encode_sparse_ratio); | ||
232 | lua_pushinteger(l, cfg->encode_sparse_safe); | ||
233 | |||
234 | return 3; | ||
235 | } | ||
236 | |||
237 | /* Configures the maximum number of nested arrays/objects allowed when | ||
238 | * encoding */ | ||
239 | static int json_cfg_encode_max_depth(lua_State *l) | ||
240 | { | ||
241 | json_config_t *cfg; | ||
242 | int depth; | ||
243 | |||
244 | json_verify_arg_count(l, 1); | ||
245 | cfg = json_fetch_config(l); | ||
246 | |||
247 | if (lua_gettop(l)) { | ||
248 | depth = luaL_checkinteger(l, 1); | ||
249 | luaL_argcheck(l, depth > 0, 1, "expected positive integer"); | ||
250 | cfg->encode_max_depth = depth; | ||
251 | } | ||
252 | |||
253 | lua_pushinteger(l, cfg->encode_max_depth); | ||
254 | |||
255 | return 1; | ||
256 | } | ||
257 | |||
258 | /* Configures number precision when converting doubles to text */ | ||
259 | static int json_cfg_encode_number_precision(lua_State *l) | ||
260 | { | ||
261 | json_config_t *cfg; | ||
262 | int precision; | ||
263 | |||
264 | json_verify_arg_count(l, 1); | ||
265 | cfg = json_fetch_config(l); | ||
266 | |||
267 | if (lua_gettop(l)) { | ||
268 | precision = luaL_checkinteger(l, 1); | ||
269 | luaL_argcheck(l, 1 <= precision && precision <= 14, 1, | ||
270 | "expected integer between 1 and 14"); | ||
271 | cfg->encode_number_precision = precision; | ||
272 | } | ||
273 | |||
274 | lua_pushinteger(l, cfg->encode_number_precision); | ||
275 | |||
276 | return 1; | ||
277 | } | ||
278 | |||
279 | /* Configures JSON encoding buffer persistence */ | ||
280 | static int json_cfg_encode_keep_buffer(lua_State *l) | ||
281 | { | ||
282 | json_config_t *cfg; | ||
283 | int old_value; | ||
284 | |||
285 | json_verify_arg_count(l, 1); | ||
286 | cfg = json_fetch_config(l); | ||
287 | |||
288 | old_value = cfg->encode_keep_buffer; | ||
289 | |||
290 | if (lua_gettop(l)) { | ||
291 | luaL_checktype(l, 1, LUA_TBOOLEAN); | ||
292 | cfg->encode_keep_buffer = lua_toboolean(l, 1); | ||
293 | } | ||
294 | |||
295 | /* Init / free the buffer if the setting has changed */ | ||
296 | if (old_value ^ cfg->encode_keep_buffer) { | ||
297 | if (cfg->encode_keep_buffer) | ||
298 | strbuf_init(&cfg->encode_buf, 0); | ||
299 | else | ||
300 | strbuf_free(&cfg->encode_buf); | ||
301 | } | ||
302 | |||
303 | lua_pushboolean(l, cfg->encode_keep_buffer); | ||
304 | |||
305 | return 1; | ||
306 | } | ||
307 | |||
308 | /* On argument: decode enum and set config variables | ||
309 | * **options must point to a NULL terminated array of 4 enums | ||
310 | * Returns: current enum value */ | ||
311 | static void json_enum_option(lua_State *l, const char **options, | ||
312 | int *opt1, int *opt2) | ||
313 | { | ||
314 | int setting; | ||
315 | |||
316 | if (lua_gettop(l)) { | ||
317 | if (lua_isboolean(l, 1)) | ||
318 | setting = lua_toboolean(l, 1) * 3; | ||
319 | else | ||
320 | setting = luaL_checkoption(l, 1, NULL, options); | ||
321 | |||
322 | *opt1 = setting & 1 ? 1 : 0; | ||
323 | *opt2 = setting & 2 ? 1 : 0; | ||
324 | } else { | ||
325 | setting = *opt1 | (*opt2 << 1); | ||
326 | } | ||
327 | |||
328 | if (setting) | ||
329 | lua_pushstring(l, options[setting]); | ||
330 | else | ||
331 | lua_pushboolean(l, 0); | ||
332 | } | ||
333 | |||
334 | |||
335 | /* When enabled, rejects: NaN, Infinity, hexadecimal numbers */ | ||
336 | static int json_cfg_refuse_invalid_numbers(lua_State *l) | ||
337 | { | ||
338 | static const char *options_enc_dec[] = { "none", "encode", "decode", | ||
339 | "both", NULL }; | ||
340 | json_config_t *cfg; | ||
341 | |||
342 | json_verify_arg_count(l, 1); | ||
343 | cfg = json_fetch_config(l); | ||
344 | |||
345 | json_enum_option(l, options_enc_dec, | ||
346 | &cfg->encode_refuse_badnum, | ||
347 | &cfg->decode_refuse_badnum); | ||
348 | |||
349 | #if DISABLE_INVALID_NUMBERS | ||
350 | /* Some non-POSIX platforms don't handle double <-> string translations | ||
351 | * for Infinity/NaN/hexadecimal properly. Throw an error if the | ||
352 | * user attempts to enable them. */ | ||
353 | if (!cfg->encode_refuse_badnum || !cfg->decode_refuse_badnum) { | ||
354 | cfg->encode_refuse_badnum = cfg->decode_refuse_badnum = 1; | ||
355 | luaL_error(l, "Infinity, NaN, and/or hexadecimal numbers are not supported."); | ||
356 | } | ||
357 | #endif | ||
358 | |||
359 | return 1; | ||
360 | } | ||
361 | |||
362 | static int json_destroy_config(lua_State *l) | ||
363 | { | ||
364 | json_config_t *cfg; | ||
365 | |||
366 | cfg = lua_touserdata(l, 1); | ||
367 | if (cfg) | ||
368 | strbuf_free(&cfg->encode_buf); | ||
369 | cfg = NULL; | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void json_create_config(lua_State *l) | ||
375 | { | ||
376 | json_config_t *cfg; | ||
377 | int i; | ||
378 | |||
379 | cfg = lua_newuserdata(l, sizeof(*cfg)); | ||
380 | |||
381 | /* Create GC method to clean up strbuf */ | ||
382 | lua_newtable(l); | ||
383 | lua_pushcfunction(l, json_destroy_config); | ||
384 | lua_setfield(l, -2, "__gc"); | ||
385 | lua_setmetatable(l, -2); | ||
386 | |||
387 | cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT; | ||
388 | cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO; | ||
389 | cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE; | ||
390 | cfg->encode_max_depth = DEFAULT_MAX_DEPTH; | ||
391 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; | ||
392 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; | ||
393 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; | ||
394 | cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; | ||
395 | |||
396 | #if DEFAULT_ENCODE_KEEP_BUFFER > 0 | ||
397 | strbuf_init(&cfg->encode_buf, 0); | ||
398 | #endif | ||
399 | |||
400 | /* Decoding init */ | ||
401 | |||
402 | /* Tag all characters as an error */ | ||
403 | for (i = 0; i < 256; i++) | ||
404 | cfg->ch2token[i] = T_ERROR; | ||
405 | |||
406 | /* Set tokens that require no further processing */ | ||
407 | cfg->ch2token['{'] = T_OBJ_BEGIN; | ||
408 | cfg->ch2token['}'] = T_OBJ_END; | ||
409 | cfg->ch2token['['] = T_ARR_BEGIN; | ||
410 | cfg->ch2token[']'] = T_ARR_END; | ||
411 | cfg->ch2token[','] = T_COMMA; | ||
412 | cfg->ch2token[':'] = T_COLON; | ||
413 | cfg->ch2token['\0'] = T_END; | ||
414 | cfg->ch2token[' '] = T_WHITESPACE; | ||
415 | cfg->ch2token['\t'] = T_WHITESPACE; | ||
416 | cfg->ch2token['\n'] = T_WHITESPACE; | ||
417 | cfg->ch2token['\r'] = T_WHITESPACE; | ||
418 | |||
419 | /* Update characters that require further processing */ | ||
420 | cfg->ch2token['f'] = T_UNKNOWN; /* false? */ | ||
421 | cfg->ch2token['i'] = T_UNKNOWN; /* inf, ininity? */ | ||
422 | cfg->ch2token['I'] = T_UNKNOWN; | ||
423 | cfg->ch2token['n'] = T_UNKNOWN; /* null, nan? */ | ||
424 | cfg->ch2token['N'] = T_UNKNOWN; | ||
425 | cfg->ch2token['t'] = T_UNKNOWN; /* true? */ | ||
426 | cfg->ch2token['"'] = T_UNKNOWN; /* string? */ | ||
427 | cfg->ch2token['+'] = T_UNKNOWN; /* number? */ | ||
428 | cfg->ch2token['-'] = T_UNKNOWN; | ||
429 | for (i = 0; i < 10; i++) | ||
430 | cfg->ch2token['0' + i] = T_UNKNOWN; | ||
431 | |||
432 | /* Lookup table for parsing escape characters */ | ||
433 | for (i = 0; i < 256; i++) | ||
434 | cfg->escape2char[i] = 0; /* String error */ | ||
435 | cfg->escape2char['"'] = '"'; | ||
436 | cfg->escape2char['\\'] = '\\'; | ||
437 | cfg->escape2char['/'] = '/'; | ||
438 | cfg->escape2char['b'] = '\b'; | ||
439 | cfg->escape2char['t'] = '\t'; | ||
440 | cfg->escape2char['n'] = '\n'; | ||
441 | cfg->escape2char['f'] = '\f'; | ||
442 | cfg->escape2char['r'] = '\r'; | ||
443 | cfg->escape2char['u'] = 'u'; /* Unicode parsing required */ | ||
444 | } | ||
445 | |||
446 | /* ===== ENCODING ===== */ | ||
447 | |||
448 | static void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex, | ||
449 | const char *reason) | ||
450 | { | ||
451 | if (!cfg->encode_keep_buffer) | ||
452 | strbuf_free(json); | ||
453 | luaL_error(l, "Cannot serialise %s: %s", | ||
454 | lua_typename(l, lua_type(l, lindex)), reason); | ||
455 | } | ||
456 | |||
457 | /* json_append_string args: | ||
458 | * - lua_State | ||
459 | * - JSON strbuf | ||
460 | * - String (Lua stack index) | ||
461 | * | ||
462 | * Returns nothing. Doesn't remove string from Lua stack */ | ||
463 | static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | ||
464 | { | ||
465 | const char *escstr; | ||
466 | int i; | ||
467 | const char *str; | ||
468 | size_t len; | ||
469 | |||
470 | str = lua_tolstring(l, lindex, &len); | ||
471 | |||
472 | /* Worst case is len * 6 (all unicode escapes). | ||
473 | * This buffer is reused constantly for small strings | ||
474 | * If there are any excess pages, they won't be hit anyway. | ||
475 | * This gains ~5% speedup. */ | ||
476 | strbuf_ensure_empty_length(json, len * 6 + 2); | ||
477 | |||
478 | strbuf_append_char_unsafe(json, '\"'); | ||
479 | for (i = 0; i < len; i++) { | ||
480 | escstr = char2escape[(unsigned char)str[i]]; | ||
481 | if (escstr) | ||
482 | strbuf_append_string(json, escstr); | ||
483 | else | ||
484 | strbuf_append_char_unsafe(json, str[i]); | ||
485 | } | ||
486 | strbuf_append_char_unsafe(json, '\"'); | ||
487 | } | ||
488 | |||
489 | /* Find the size of the array on the top of the Lua stack | ||
490 | * -1 object (not a pure array) | ||
491 | * >=0 elements in array | ||
492 | */ | ||
493 | static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json) | ||
494 | { | ||
495 | double k; | ||
496 | int max; | ||
497 | int items; | ||
498 | |||
499 | max = 0; | ||
500 | items = 0; | ||
501 | |||
502 | lua_pushnil(l); | ||
503 | /* table, startkey */ | ||
504 | while (lua_next(l, -2) != 0) { | ||
505 | /* table, key, value */ | ||
506 | if (lua_type(l, -2) == LUA_TNUMBER && | ||
507 | (k = lua_tonumber(l, -2))) { | ||
508 | /* Integer >= 1 ? */ | ||
509 | if (floor(k) == k && k >= 1) { | ||
510 | if (k > max) | ||
511 | max = k; | ||
512 | items++; | ||
513 | lua_pop(l, 1); | ||
514 | continue; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /* Must not be an array (non integer key) */ | ||
519 | lua_pop(l, 2); | ||
520 | return -1; | ||
521 | } | ||
522 | |||
523 | /* Encode excessively sparse arrays as objects (if enabled) */ | ||
524 | if (cfg->encode_sparse_ratio > 0 && | ||
525 | max > items * cfg->encode_sparse_ratio && | ||
526 | max > cfg->encode_sparse_safe) { | ||
527 | if (!cfg->encode_sparse_convert) | ||
528 | json_encode_exception(l, cfg, json, -1, "excessively sparse array"); | ||
529 | |||
530 | return -1; | ||
531 | } | ||
532 | |||
533 | return max; | ||
534 | } | ||
535 | |||
536 | static void json_check_encode_depth(lua_State *l, json_config_t *cfg, | ||
537 | int current_depth, strbuf_t *json) | ||
538 | { | ||
539 | if (current_depth > cfg->encode_max_depth) { | ||
540 | if (!cfg->encode_keep_buffer) | ||
541 | strbuf_free(json); | ||
542 | luaL_error(l, "Cannot serialise, excessive nesting (%d)", | ||
543 | current_depth); | ||
544 | } | ||
545 | } | ||
546 | |||
547 | static void json_append_data(lua_State *l, json_config_t *cfg, | ||
548 | int current_depth, strbuf_t *json); | ||
549 | |||
550 | /* json_append_array args: | ||
551 | * - lua_State | ||
552 | * - JSON strbuf | ||
553 | * - Size of passwd Lua array (top of stack) */ | ||
554 | static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth, | ||
555 | strbuf_t *json, int array_length) | ||
556 | { | ||
557 | int comma, i; | ||
558 | |||
559 | strbuf_append_char(json, '['); | ||
560 | |||
561 | comma = 0; | ||
562 | for (i = 1; i <= array_length; i++) { | ||
563 | if (comma) | ||
564 | strbuf_append_char(json, ','); | ||
565 | else | ||
566 | comma = 1; | ||
567 | |||
568 | lua_rawgeti(l, -1, i); | ||
569 | json_append_data(l, cfg, current_depth, json); | ||
570 | lua_pop(l, 1); | ||
571 | } | ||
572 | |||
573 | strbuf_append_char(json, ']'); | ||
574 | } | ||
575 | |||
576 | static void json_append_number(lua_State *l, json_config_t *cfg, | ||
577 | strbuf_t *json, int lindex) | ||
578 | { | ||
579 | double num = lua_tonumber(l, lindex); | ||
580 | int len; | ||
581 | |||
582 | if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num))) | ||
583 | json_encode_exception(l, cfg, json, lindex, "must not be NaN or Inf"); | ||
584 | |||
585 | if (isnan(num)) { | ||
586 | /* Some platforms may print -nan, just hard code it */ | ||
587 | strbuf_append_mem(json, "nan", 3); | ||
588 | } else { | ||
589 | strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); | ||
590 | len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision); | ||
591 | strbuf_extend_length(json, len); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | static void json_append_object(lua_State *l, json_config_t *cfg, | ||
596 | int current_depth, strbuf_t *json) | ||
597 | { | ||
598 | int comma, keytype; | ||
599 | |||
600 | /* Object */ | ||
601 | strbuf_append_char(json, '{'); | ||
602 | |||
603 | lua_pushnil(l); | ||
604 | /* table, startkey */ | ||
605 | comma = 0; | ||
606 | while (lua_next(l, -2) != 0) { | ||
607 | if (comma) | ||
608 | strbuf_append_char(json, ','); | ||
609 | else | ||
610 | comma = 1; | ||
611 | |||
612 | /* table, key, value */ | ||
613 | keytype = lua_type(l, -2); | ||
614 | if (keytype == LUA_TNUMBER) { | ||
615 | strbuf_append_char(json, '"'); | ||
616 | json_append_number(l, cfg, json, -2); | ||
617 | strbuf_append_mem(json, "\":", 2); | ||
618 | } else if (keytype == LUA_TSTRING) { | ||
619 | json_append_string(l, json, -2); | ||
620 | strbuf_append_char(json, ':'); | ||
621 | } else { | ||
622 | json_encode_exception(l, cfg, json, -2, | ||
623 | "table key must be a number or string"); | ||
624 | /* never returns */ | ||
625 | } | ||
626 | |||
627 | /* table, key, value */ | ||
628 | json_append_data(l, cfg, current_depth, json); | ||
629 | lua_pop(l, 1); | ||
630 | /* table, key */ | ||
631 | } | ||
632 | |||
633 | strbuf_append_char(json, '}'); | ||
634 | } | ||
635 | |||
636 | /* Serialise Lua data into JSON string. */ | ||
637 | static void json_append_data(lua_State *l, json_config_t *cfg, | ||
638 | int current_depth, strbuf_t *json) | ||
639 | { | ||
640 | int len; | ||
641 | |||
642 | switch (lua_type(l, -1)) { | ||
643 | case LUA_TSTRING: | ||
644 | json_append_string(l, json, -1); | ||
645 | break; | ||
646 | case LUA_TNUMBER: | ||
647 | json_append_number(l, cfg, json, -1); | ||
648 | break; | ||
649 | case LUA_TBOOLEAN: | ||
650 | if (lua_toboolean(l, -1)) | ||
651 | strbuf_append_mem(json, "true", 4); | ||
652 | else | ||
653 | strbuf_append_mem(json, "false", 5); | ||
654 | break; | ||
655 | case LUA_TTABLE: | ||
656 | len = lua_array_length(l, cfg, json); | ||
657 | current_depth++; | ||
658 | json_check_encode_depth(l, cfg, current_depth, json); | ||
659 | if (len > 0) | ||
660 | json_append_array(l, cfg, current_depth, json, len); | ||
661 | else | ||
662 | json_append_object(l, cfg, current_depth, json); | ||
663 | break; | ||
664 | case LUA_TNIL: | ||
665 | strbuf_append_mem(json, "null", 4); | ||
666 | break; | ||
667 | case LUA_TLIGHTUSERDATA: | ||
668 | if (lua_touserdata(l, -1) == NULL) { | ||
669 | strbuf_append_mem(json, "null", 4); | ||
670 | break; | ||
671 | } | ||
672 | default: | ||
673 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, | ||
674 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ | ||
675 | json_encode_exception(l, cfg, json, -1, "type not supported"); | ||
676 | /* never returns */ | ||
677 | } | ||
678 | } | ||
679 | |||
680 | static int json_encode(lua_State *l) | ||
681 | { | ||
682 | json_config_t *cfg; | ||
683 | strbuf_t local_encode_buf; | ||
684 | strbuf_t *encode_buf; | ||
685 | char *json; | ||
686 | int len; | ||
687 | |||
688 | /* Can't use json_verify_arg_count() since we need to ensure | ||
689 | * there is only 1 argument */ | ||
690 | luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument"); | ||
691 | |||
692 | cfg = json_fetch_config(l); | ||
693 | |||
694 | if (!cfg->encode_keep_buffer) { | ||
695 | /* Use private buffer */ | ||
696 | encode_buf = &local_encode_buf; | ||
697 | strbuf_init(encode_buf, 0); | ||
698 | } else { | ||
699 | /* Reuse existing buffer */ | ||
700 | encode_buf = &cfg->encode_buf; | ||
701 | strbuf_reset(encode_buf); | ||
702 | } | ||
703 | |||
704 | json_append_data(l, cfg, 0, encode_buf); | ||
705 | json = strbuf_string(encode_buf, &len); | ||
706 | |||
707 | lua_pushlstring(l, json, len); | ||
708 | |||
709 | if (!cfg->encode_keep_buffer) | ||
710 | strbuf_free(encode_buf); | ||
711 | |||
712 | return 1; | ||
713 | } | ||
714 | |||
715 | /* ===== DECODING ===== */ | ||
716 | |||
717 | static void json_process_value(lua_State *l, json_parse_t *json, | ||
718 | json_token_t *token); | ||
719 | |||
720 | static int hexdigit2int(char hex) | ||
721 | { | ||
722 | if ('0' <= hex && hex <= '9') | ||
723 | return hex - '0'; | ||
724 | |||
725 | /* Force lowercase */ | ||
726 | hex |= 0x20; | ||
727 | if ('a' <= hex && hex <= 'f') | ||
728 | return 10 + hex - 'a'; | ||
729 | |||
730 | return -1; | ||
731 | } | ||
732 | |||
733 | static int decode_hex4(const char *hex) | ||
734 | { | ||
735 | int digit[4]; | ||
736 | int i; | ||
737 | |||
738 | /* Convert ASCII hex digit to numeric digit | ||
739 | * Note: this returns an error for invalid hex digits, including | ||
740 | * NULL */ | ||
741 | for (i = 0; i < 4; i++) { | ||
742 | digit[i] = hexdigit2int(hex[i]); | ||
743 | if (digit[i] < 0) { | ||
744 | return -1; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | return (digit[0] << 12) + | ||
749 | (digit[1] << 8) + | ||
750 | (digit[2] << 4) + | ||
751 | digit[3]; | ||
752 | } | ||
753 | |||
754 | /* Converts a Unicode codepoint to UTF-8. | ||
755 | * Returns UTF-8 string length, and up to 4 bytes in *utf8 */ | ||
756 | static int codepoint_to_utf8(char *utf8, int codepoint) | ||
757 | { | ||
758 | /* 0xxxxxxx */ | ||
759 | if (codepoint <= 0x7F) { | ||
760 | utf8[0] = codepoint; | ||
761 | return 1; | ||
762 | } | ||
763 | |||
764 | /* 110xxxxx 10xxxxxx */ | ||
765 | if (codepoint <= 0x7FF) { | ||
766 | utf8[0] = (codepoint >> 6) | 0xC0; | ||
767 | utf8[1] = (codepoint & 0x3F) | 0x80; | ||
768 | return 2; | ||
769 | } | ||
770 | |||
771 | /* 1110xxxx 10xxxxxx 10xxxxxx */ | ||
772 | if (codepoint <= 0xFFFF) { | ||
773 | utf8[0] = (codepoint >> 12) | 0xE0; | ||
774 | utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80; | ||
775 | utf8[2] = (codepoint & 0x3F) | 0x80; | ||
776 | return 3; | ||
777 | } | ||
778 | |||
779 | /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ | ||
780 | if (codepoint <= 0x1FFFFF) { | ||
781 | utf8[0] = (codepoint >> 18) | 0xF0; | ||
782 | utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80; | ||
783 | utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80; | ||
784 | utf8[3] = (codepoint & 0x3F) | 0x80; | ||
785 | return 4; | ||
786 | } | ||
787 | |||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | |||
792 | /* Called when index pointing to beginning of UTF-16 code escape: \uXXXX | ||
793 | * \u is guaranteed to exist, but the remaining hex characters may be | ||
794 | * missing. | ||
795 | * Translate to UTF-8 and append to temporary token string. | ||
796 | * Must advance index to the next character to be processed. | ||
797 | * Returns: 0 success | ||
798 | * -1 error | ||
799 | */ | ||
800 | static int json_append_unicode_escape(json_parse_t *json) | ||
801 | { | ||
802 | char utf8[4]; /* Surrogate pairs require 4 UTF-8 bytes */ | ||
803 | int codepoint; | ||
804 | int surrogate_low; | ||
805 | int len; | ||
806 | int escape_len = 6; | ||
807 | |||
808 | /* Fetch UTF-16 code unit */ | ||
809 | codepoint = decode_hex4(&json->data[json->index + 2]); | ||
810 | if (codepoint < 0) | ||
811 | return -1; | ||
812 | |||
813 | /* UTF-16 surrogate pairs take the following 2 byte form: | ||
814 | * 11011 x yyyyyyyyyy | ||
815 | * When x = 0: y is the high 10 bits of the codepoint | ||
816 | * x = 1: y is the low 10 bits of the codepoint | ||
817 | * | ||
818 | * Check for a surrogate pair (high or low) */ | ||
819 | if ((codepoint & 0xF800) == 0xD800) { | ||
820 | /* Error if the 1st surrogate is not high */ | ||
821 | if (codepoint & 0x400) | ||
822 | return -1; | ||
823 | |||
824 | /* Ensure the next code is a unicode escape */ | ||
825 | if (json->data[json->index + escape_len] != '\\' || | ||
826 | json->data[json->index + escape_len + 1] != 'u') { | ||
827 | return -1; | ||
828 | } | ||
829 | |||
830 | /* Fetch the next codepoint */ | ||
831 | surrogate_low = decode_hex4(&json->data[json->index + 2 + escape_len]); | ||
832 | if (surrogate_low < 0) | ||
833 | return -1; | ||
834 | |||
835 | /* Error if the 2nd code is not a low surrogate */ | ||
836 | if ((surrogate_low & 0xFC00) != 0xDC00) | ||
837 | return -1; | ||
838 | |||
839 | /* Calculate Unicode codepoint */ | ||
840 | codepoint = (codepoint & 0x3FF) << 10; | ||
841 | surrogate_low &= 0x3FF; | ||
842 | codepoint = (codepoint | surrogate_low) + 0x10000; | ||
843 | escape_len = 12; | ||
844 | } | ||
845 | |||
846 | /* Convert codepoint to UTF-8 */ | ||
847 | len = codepoint_to_utf8(utf8, codepoint); | ||
848 | if (!len) | ||
849 | return -1; | ||
850 | |||
851 | /* Append bytes and advance parse index */ | ||
852 | strbuf_append_mem_unsafe(json->tmp, utf8, len); | ||
853 | json->index += escape_len; | ||
854 | |||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static void json_set_token_error(json_token_t *token, json_parse_t *json, | ||
859 | const char *errtype) | ||
860 | { | ||
861 | token->type = T_ERROR; | ||
862 | token->index = json->index; | ||
863 | token->value.string = errtype; | ||
864 | } | ||
865 | |||
866 | static void json_next_string_token(json_parse_t *json, json_token_t *token) | ||
867 | { | ||
868 | char *escape2char = json->cfg->escape2char; | ||
869 | char ch; | ||
870 | |||
871 | /* Caller must ensure a string is next */ | ||
872 | assert(json->data[json->index] == '"'); | ||
873 | |||
874 | /* Skip " */ | ||
875 | json->index++; | ||
876 | |||
877 | /* json->tmp is the temporary strbuf used to accumulate the | ||
878 | * decoded string value. | ||
879 | * json->tmp is sized to handle JSON containing only a string value. | ||
880 | */ | ||
881 | strbuf_reset(json->tmp); | ||
882 | |||
883 | while ((ch = json->data[json->index]) != '"') { | ||
884 | if (!ch) { | ||
885 | /* Premature end of the string */ | ||
886 | json_set_token_error(token, json, "unexpected end of string"); | ||
887 | return; | ||
888 | } | ||
889 | |||
890 | /* Handle escapes */ | ||
891 | if (ch == '\\') { | ||
892 | /* Fetch escape character */ | ||
893 | ch = json->data[json->index + 1]; | ||
894 | |||
895 | /* Translate escape code and append to tmp string */ | ||
896 | ch = escape2char[(unsigned char)ch]; | ||
897 | if (ch == 'u') { | ||
898 | if (json_append_unicode_escape(json) == 0) | ||
899 | continue; | ||
900 | |||
901 | json_set_token_error(token, json, | ||
902 | "invalid unicode escape code"); | ||
903 | return; | ||
904 | } | ||
905 | if (!ch) { | ||
906 | json_set_token_error(token, json, "invalid escape code"); | ||
907 | return; | ||
908 | } | ||
909 | |||
910 | /* Skip '\' */ | ||
911 | json->index++; | ||
912 | } | ||
913 | /* Append normal character or translated single character | ||
914 | * Unicode escapes are handled above */ | ||
915 | strbuf_append_char_unsafe(json->tmp, ch); | ||
916 | json->index++; | ||
917 | } | ||
918 | json->index++; /* Eat final quote (") */ | ||
919 | |||
920 | strbuf_ensure_null(json->tmp); | ||
921 | |||
922 | token->type = T_STRING; | ||
923 | token->value.string = strbuf_string(json->tmp, &token->string_len); | ||
924 | } | ||
925 | |||
926 | /* JSON numbers should take the following form: | ||
927 | * -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)? | ||
928 | * | ||
929 | * json_next_number_token() uses strtod() which allows other forms: | ||
930 | * - numbers starting with '+' | ||
931 | * - NaN, -NaN, infinity, -infinity | ||
932 | * - hexadecimal numbers | ||
933 | * - numbers with leading zeros | ||
934 | * | ||
935 | * json_is_invalid_number() detects "numbers" which may pass strtod()'s | ||
936 | * error checking, but should not be allowed with strict JSON. | ||
937 | * | ||
938 | * json_is_invalid_number() may pass numbers which cause strtod() | ||
939 | * to generate an error. | ||
940 | */ | ||
941 | static int json_is_invalid_number(json_parse_t *json) | ||
942 | { | ||
943 | int i = json->index; | ||
944 | |||
945 | /* Reject numbers starting with + */ | ||
946 | if (json->data[i] == '+') | ||
947 | return 1; | ||
948 | |||
949 | /* Skip minus sign if it exists */ | ||
950 | if (json->data[i] == '-') | ||
951 | i++; | ||
952 | |||
953 | /* Reject numbers starting with 0x, or leading zeros */ | ||
954 | if (json->data[i] == '0') { | ||
955 | int ch2 = json->data[i + 1]; | ||
956 | |||
957 | if ((ch2 | 0x20) == 'x' || /* Hex */ | ||
958 | ('0' <= ch2 && ch2 <= '9')) /* Leading zero */ | ||
959 | return 1; | ||
960 | |||
961 | return 0; | ||
962 | } else if (json->data[i] <= '9') { | ||
963 | return 0; /* Ordinary number */ | ||
964 | } | ||
965 | |||
966 | /* Reject inf/nan */ | ||
967 | if (!strncasecmp(&json->data[i], "inf", 3)) | ||
968 | return 1; | ||
969 | if (!strncasecmp(&json->data[i], "nan", 3)) | ||
970 | return 1; | ||
971 | |||
972 | /* Pass all other numbers which may still be invalid, but | ||
973 | * strtod() will catch them. */ | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static void json_next_number_token(json_parse_t *json, json_token_t *token) | ||
978 | { | ||
979 | const char *startptr; | ||
980 | char *endptr; | ||
981 | |||
982 | token->type = T_NUMBER; | ||
983 | startptr = &json->data[json->index]; | ||
984 | token->value.number = fpconv_strtod(&json->data[json->index], &endptr); | ||
985 | if (startptr == endptr) | ||
986 | json_set_token_error(token, json, "invalid number"); | ||
987 | else | ||
988 | json->index += endptr - startptr; /* Skip the processed number */ | ||
989 | |||
990 | return; | ||
991 | } | ||
992 | |||
993 | /* Fills in the token struct. | ||
994 | * T_STRING will return a pointer to the json_parse_t temporary string | ||
995 | * T_ERROR will leave the json->index pointer at the error. | ||
996 | */ | ||
997 | static void json_next_token(json_parse_t *json, json_token_t *token) | ||
998 | { | ||
999 | json_token_type_t *ch2token = json->cfg->ch2token; | ||
1000 | int ch; | ||
1001 | |||
1002 | /* Eat whitespace. FIXME: UGLY */ | ||
1003 | token->type = ch2token[(unsigned char)json->data[json->index]]; | ||
1004 | while (token->type == T_WHITESPACE) | ||
1005 | token->type = ch2token[(unsigned char)json->data[++json->index]]; | ||
1006 | |||
1007 | token->index = json->index; | ||
1008 | |||
1009 | /* Don't advance the pointer for an error or the end */ | ||
1010 | if (token->type == T_ERROR) { | ||
1011 | json_set_token_error(token, json, "invalid token"); | ||
1012 | return; | ||
1013 | } | ||
1014 | |||
1015 | if (token->type == T_END) { | ||
1016 | return; | ||
1017 | } | ||
1018 | |||
1019 | /* Found a known single character token, advance index and return */ | ||
1020 | if (token->type != T_UNKNOWN) { | ||
1021 | json->index++; | ||
1022 | return; | ||
1023 | } | ||
1024 | |||
1025 | /* Process characters which triggered T_UNKNOWN */ | ||
1026 | ch = json->data[json->index]; | ||
1027 | |||
1028 | /* Must use strncmp() to match the front of the JSON string. | ||
1029 | * JSON identifier must be lowercase. | ||
1030 | * When strict_numbers if disabled, either case is allowed for | ||
1031 | * Infinity/NaN (since we are no longer following the spec..) */ | ||
1032 | if (ch == '"') { | ||
1033 | json_next_string_token(json, token); | ||
1034 | return; | ||
1035 | } else if (ch == '-' || ('0' <= ch && ch <= '9')) { | ||
1036 | if (json->cfg->decode_refuse_badnum && json_is_invalid_number(json)) { | ||
1037 | json_set_token_error(token, json, "invalid number"); | ||
1038 | return; | ||
1039 | } | ||
1040 | json_next_number_token(json, token); | ||
1041 | return; | ||
1042 | } else if (!strncmp(&json->data[json->index], "true", 4)) { | ||
1043 | token->type = T_BOOLEAN; | ||
1044 | token->value.boolean = 1; | ||
1045 | json->index += 4; | ||
1046 | return; | ||
1047 | } else if (!strncmp(&json->data[json->index], "false", 5)) { | ||
1048 | token->type = T_BOOLEAN; | ||
1049 | token->value.boolean = 0; | ||
1050 | json->index += 5; | ||
1051 | return; | ||
1052 | } else if (!strncmp(&json->data[json->index], "null", 4)) { | ||
1053 | token->type = T_NULL; | ||
1054 | json->index += 4; | ||
1055 | return; | ||
1056 | } else if (!json->cfg->decode_refuse_badnum && | ||
1057 | json_is_invalid_number(json)) { | ||
1058 | /* When refuse_badnum is disabled, only attempt to process | ||
1059 | * numbers we know are invalid JSON (Inf, NaN, hex) | ||
1060 | * This is required to generate an appropriate token error, | ||
1061 | * otherwise all bad tokens will register as "invalid number" | ||
1062 | */ | ||
1063 | json_next_number_token(json, token); | ||
1064 | return; | ||
1065 | } | ||
1066 | |||
1067 | /* Token starts with t/f/n but isn't recognised above. */ | ||
1068 | json_set_token_error(token, json, "invalid token"); | ||
1069 | } | ||
1070 | |||
1071 | /* This function does not return. | ||
1072 | * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED. | ||
1073 | * The only supported exception is the temporary parser string | ||
1074 | * json->tmp struct. | ||
1075 | * json and token should exist on the stack somewhere. | ||
1076 | * luaL_error() will long_jmp and release the stack */ | ||
1077 | static void json_throw_parse_error(lua_State *l, json_parse_t *json, | ||
1078 | const char *exp, json_token_t *token) | ||
1079 | { | ||
1080 | const char *found; | ||
1081 | |||
1082 | strbuf_free(json->tmp); | ||
1083 | |||
1084 | if (token->type == T_ERROR) | ||
1085 | found = token->value.string; | ||
1086 | else | ||
1087 | found = json_token_type_name[token->type]; | ||
1088 | |||
1089 | /* Note: token->index is 0 based, display starting from 1 */ | ||
1090 | luaL_error(l, "Expected %s but found %s at character %d", | ||
1091 | exp, found, token->index + 1); | ||
1092 | } | ||
1093 | |||
1094 | static void json_decode_checkstack(lua_State *l, json_parse_t *json, int n) | ||
1095 | { | ||
1096 | if (lua_checkstack(l, n)) | ||
1097 | return; | ||
1098 | |||
1099 | strbuf_free(json->tmp); | ||
1100 | luaL_error(l, "Too many nested data structures"); | ||
1101 | } | ||
1102 | |||
1103 | static void json_parse_object_context(lua_State *l, json_parse_t *json) | ||
1104 | { | ||
1105 | json_token_t token; | ||
1106 | |||
1107 | /* 3 slots required: | ||
1108 | * .., table, key, value */ | ||
1109 | json_decode_checkstack(l, json, 3); | ||
1110 | |||
1111 | lua_newtable(l); | ||
1112 | |||
1113 | json_next_token(json, &token); | ||
1114 | |||
1115 | /* Handle empty objects */ | ||
1116 | if (token.type == T_OBJ_END) { | ||
1117 | return; | ||
1118 | } | ||
1119 | |||
1120 | while (1) { | ||
1121 | if (token.type != T_STRING) | ||
1122 | json_throw_parse_error(l, json, "object key string", &token); | ||
1123 | |||
1124 | /* Push key */ | ||
1125 | lua_pushlstring(l, token.value.string, token.string_len); | ||
1126 | |||
1127 | json_next_token(json, &token); | ||
1128 | if (token.type != T_COLON) | ||
1129 | json_throw_parse_error(l, json, "colon", &token); | ||
1130 | |||
1131 | /* Fetch value */ | ||
1132 | json_next_token(json, &token); | ||
1133 | json_process_value(l, json, &token); | ||
1134 | |||
1135 | /* Set key = value */ | ||
1136 | lua_rawset(l, -3); | ||
1137 | |||
1138 | json_next_token(json, &token); | ||
1139 | |||
1140 | if (token.type == T_OBJ_END) | ||
1141 | return; | ||
1142 | |||
1143 | if (token.type != T_COMMA) | ||
1144 | json_throw_parse_error(l, json, "comma or object end", &token); | ||
1145 | |||
1146 | json_next_token(json, &token); | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | /* Handle the array context */ | ||
1151 | static void json_parse_array_context(lua_State *l, json_parse_t *json) | ||
1152 | { | ||
1153 | json_token_t token; | ||
1154 | int i; | ||
1155 | |||
1156 | /* 2 slots required: | ||
1157 | * .., table, value */ | ||
1158 | json_decode_checkstack(l, json, 2); | ||
1159 | |||
1160 | lua_newtable(l); | ||
1161 | |||
1162 | json_next_token(json, &token); | ||
1163 | |||
1164 | /* Handle empty arrays */ | ||
1165 | if (token.type == T_ARR_END) | ||
1166 | return; | ||
1167 | |||
1168 | for (i = 1; ; i++) { | ||
1169 | json_process_value(l, json, &token); | ||
1170 | lua_rawseti(l, -2, i); /* arr[i] = value */ | ||
1171 | |||
1172 | json_next_token(json, &token); | ||
1173 | |||
1174 | if (token.type == T_ARR_END) | ||
1175 | return; | ||
1176 | |||
1177 | if (token.type != T_COMMA) | ||
1178 | json_throw_parse_error(l, json, "comma or array end", &token); | ||
1179 | |||
1180 | json_next_token(json, &token); | ||
1181 | } | ||
1182 | } | ||
1183 | |||
1184 | /* Handle the "value" context */ | ||
1185 | static void json_process_value(lua_State *l, json_parse_t *json, | ||
1186 | json_token_t *token) | ||
1187 | { | ||
1188 | switch (token->type) { | ||
1189 | case T_STRING: | ||
1190 | lua_pushlstring(l, token->value.string, token->string_len); | ||
1191 | break;; | ||
1192 | case T_NUMBER: | ||
1193 | lua_pushnumber(l, token->value.number); | ||
1194 | break;; | ||
1195 | case T_BOOLEAN: | ||
1196 | lua_pushboolean(l, token->value.boolean); | ||
1197 | break;; | ||
1198 | case T_OBJ_BEGIN: | ||
1199 | json_parse_object_context(l, json); | ||
1200 | break;; | ||
1201 | case T_ARR_BEGIN: | ||
1202 | json_parse_array_context(l, json); | ||
1203 | break;; | ||
1204 | case T_NULL: | ||
1205 | /* In Lua, setting "t[k] = nil" will delete k from the table. | ||
1206 | * Hence a NULL pointer lightuserdata object is used instead */ | ||
1207 | lua_pushlightuserdata(l, NULL); | ||
1208 | break;; | ||
1209 | default: | ||
1210 | json_throw_parse_error(l, json, "value", token); | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | /* json_text must be null terminated string */ | ||
1215 | static void lua_json_decode(lua_State *l, const char *json_text, int json_len) | ||
1216 | { | ||
1217 | json_parse_t json; | ||
1218 | json_token_t token; | ||
1219 | |||
1220 | json.cfg = json_fetch_config(l); | ||
1221 | json.data = json_text; | ||
1222 | json.index = 0; | ||
1223 | |||
1224 | /* Ensure the temporary buffer can hold the entire string. | ||
1225 | * This means we no longer need to do length checks since the decoded | ||
1226 | * string must be smaller than the entire json string */ | ||
1227 | json.tmp = strbuf_new(json_len); | ||
1228 | |||
1229 | json_next_token(&json, &token); | ||
1230 | json_process_value(l, &json, &token); | ||
1231 | |||
1232 | /* Ensure there is no more input left */ | ||
1233 | json_next_token(&json, &token); | ||
1234 | |||
1235 | if (token.type != T_END) | ||
1236 | json_throw_parse_error(l, &json, "the end", &token); | ||
1237 | |||
1238 | strbuf_free(json.tmp); | ||
1239 | } | ||
1240 | |||
1241 | static int json_decode(lua_State *l) | ||
1242 | { | ||
1243 | const char *json; | ||
1244 | size_t len; | ||
1245 | |||
1246 | json_verify_arg_count(l, 1); | ||
1247 | |||
1248 | json = luaL_checklstring(l, 1, &len); | ||
1249 | |||
1250 | /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3) | ||
1251 | * | ||
1252 | * CJSON can support any simple data type, hence only the first | ||
1253 | * character is guaranteed to be ASCII (at worst: '"'). This is | ||
1254 | * still enough to detect whether the wrong encoding is in use. */ | ||
1255 | if (len >= 2 && (!json[0] || !json[1])) | ||
1256 | luaL_error(l, "JSON parser does not support UTF-16 or UTF-32"); | ||
1257 | |||
1258 | lua_json_decode(l, json, len); | ||
1259 | |||
1260 | return 1; | ||
1261 | } | ||
1262 | |||
1263 | /* ===== INITIALISATION ===== */ | ||
1264 | |||
1265 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 | ||
1266 | /* Compatibility for Lua 5.1. | ||
1267 | * | ||
1268 | * luaL_setfuncs() is used to create a module table where the functions have | ||
1269 | * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */ | ||
1270 | static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup) | ||
1271 | { | ||
1272 | int i; | ||
1273 | |||
1274 | luaL_checkstack(l, nup, "too many upvalues"); | ||
1275 | for (; reg->name != NULL; reg++) { /* fill the table with given functions */ | ||
1276 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
1277 | lua_pushvalue(l, -nup); | ||
1278 | lua_pushcclosure(l, reg->func, nup); /* closure with those upvalues */ | ||
1279 | lua_setfield(l, -(nup + 2), reg->name); | ||
1280 | } | ||
1281 | lua_pop(l, nup); /* remove upvalues */ | ||
1282 | } | ||
1283 | #endif | ||
1284 | |||
1285 | static int lua_cjson_new(lua_State *l) | ||
1286 | { | ||
1287 | luaL_Reg reg[] = { | ||
1288 | { "encode", json_encode }, | ||
1289 | { "decode", json_decode }, | ||
1290 | { "encode_sparse_array", json_cfg_encode_sparse_array }, | ||
1291 | { "encode_max_depth", json_cfg_encode_max_depth }, | ||
1292 | { "encode_number_precision", json_cfg_encode_number_precision }, | ||
1293 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, | ||
1294 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, | ||
1295 | { "new", lua_cjson_new }, | ||
1296 | { NULL, NULL } | ||
1297 | }; | ||
1298 | |||
1299 | /* Initialise number conversions */ | ||
1300 | fpconv_init(); | ||
1301 | |||
1302 | /* cjson module table */ | ||
1303 | lua_newtable(l); | ||
1304 | |||
1305 | /* Register functions with config data as upvalue */ | ||
1306 | json_create_config(l); | ||
1307 | luaL_setfuncs(l, reg, 1); | ||
1308 | |||
1309 | /* Set cjson.null */ | ||
1310 | lua_pushlightuserdata(l, NULL); | ||
1311 | lua_setfield(l, -2, "null"); | ||
1312 | |||
1313 | /* Set module name / version fields */ | ||
1314 | lua_pushliteral(l, CJSON_MODNAME); | ||
1315 | lua_setfield(l, -2, "_NAME"); | ||
1316 | lua_pushliteral(l, CJSON_VERSION); | ||
1317 | lua_setfield(l, -2, "_VERSION"); | ||
1318 | lua_pushliteral(l, CJSON_VERSION); | ||
1319 | lua_setfield(l, -2, "version"); | ||
1320 | |||
1321 | return 1; | ||
1322 | } | ||
1323 | |||
1324 | int luaopen_cjson(lua_State *l) | ||
1325 | { | ||
1326 | lua_cjson_new(l); | ||
1327 | |||
1328 | #if !defined(DISABLE_CJSON_GLOBAL) && (!defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502) | ||
1329 | /* Register a global "cjson" table to maintain compatibility with earlier | ||
1330 | * versions of Lua CJSON which used luaL_register() under Lua 5.1. | ||
1331 | * | ||
1332 | * From Lua 5.2 onwards, Lua CJSON does not automatically register a global | ||
1333 | * table. | ||
1334 | */ | ||
1335 | lua_pushvalue(l, -1); | ||
1336 | lua_setglobal(l, CJSON_MODNAME); | ||
1337 | #endif | ||
1338 | |||
1339 | /* Return cjson table */ | ||
1340 | return 1; | ||
1341 | } | ||
1342 | |||
1343 | /* vi:ai et sw=4 ts=4: | ||
1344 | */ | ||