hirlite 0.0.2 → 0.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/ext/hirlite_ext/extconf.rb +2 -2
  3. data/lib/hirlite/version.rb +1 -1
  4. data/vendor/rlite/deps/lua/Makefile +128 -0
  5. data/vendor/rlite/deps/lua/src/fpconv.c +205 -0
  6. data/vendor/rlite/deps/lua/src/fpconv.h +22 -0
  7. data/vendor/rlite/deps/lua/src/lapi.c +1087 -0
  8. data/vendor/rlite/deps/lua/src/lapi.h +16 -0
  9. data/vendor/rlite/deps/lua/src/lauxlib.c +652 -0
  10. data/vendor/rlite/deps/lua/src/lauxlib.h +174 -0
  11. data/vendor/rlite/deps/lua/src/lbaselib.c +653 -0
  12. data/vendor/rlite/deps/lua/src/lcode.c +831 -0
  13. data/vendor/rlite/deps/lua/src/lcode.h +76 -0
  14. data/vendor/rlite/deps/lua/src/ldblib.c +398 -0
  15. data/vendor/rlite/deps/lua/src/ldebug.c +638 -0
  16. data/vendor/rlite/deps/lua/src/ldebug.h +33 -0
  17. data/vendor/rlite/deps/lua/src/ldo.c +519 -0
  18. data/vendor/rlite/deps/lua/src/ldo.h +57 -0
  19. data/vendor/rlite/deps/lua/src/ldump.c +164 -0
  20. data/vendor/rlite/deps/lua/src/lfunc.c +174 -0
  21. data/vendor/rlite/deps/lua/src/lfunc.h +34 -0
  22. data/vendor/rlite/deps/lua/src/lgc.c +710 -0
  23. data/vendor/rlite/deps/lua/src/lgc.h +110 -0
  24. data/vendor/rlite/deps/lua/src/linit.c +38 -0
  25. data/vendor/rlite/deps/lua/src/liolib.c +556 -0
  26. data/vendor/rlite/deps/lua/src/llex.c +463 -0
  27. data/vendor/rlite/deps/lua/src/llex.h +81 -0
  28. data/vendor/rlite/deps/lua/src/llimits.h +128 -0
  29. data/vendor/rlite/deps/lua/src/lmathlib.c +263 -0
  30. data/vendor/rlite/deps/lua/src/lmem.c +86 -0
  31. data/vendor/rlite/deps/lua/src/lmem.h +49 -0
  32. data/vendor/rlite/deps/lua/src/loadlib.c +666 -0
  33. data/vendor/rlite/deps/lua/src/lobject.c +214 -0
  34. data/vendor/rlite/deps/lua/src/lobject.h +381 -0
  35. data/vendor/rlite/deps/lua/src/lopcodes.c +102 -0
  36. data/vendor/rlite/deps/lua/src/lopcodes.h +268 -0
  37. data/vendor/rlite/deps/lua/src/loslib.c +243 -0
  38. data/vendor/rlite/deps/lua/src/lparser.c +1339 -0
  39. data/vendor/rlite/deps/lua/src/lparser.h +82 -0
  40. data/vendor/rlite/deps/lua/src/lstate.c +214 -0
  41. data/vendor/rlite/deps/lua/src/lstate.h +169 -0
  42. data/vendor/rlite/deps/lua/src/lstring.c +111 -0
  43. data/vendor/rlite/deps/lua/src/lstring.h +31 -0
  44. data/vendor/rlite/deps/lua/src/lstrlib.c +871 -0
  45. data/vendor/rlite/deps/lua/src/ltable.c +588 -0
  46. data/vendor/rlite/deps/lua/src/ltable.h +40 -0
  47. data/vendor/rlite/deps/lua/src/ltablib.c +287 -0
  48. data/vendor/rlite/deps/lua/src/ltm.c +75 -0
  49. data/vendor/rlite/deps/lua/src/ltm.h +54 -0
  50. data/vendor/rlite/deps/lua/src/lua.c +392 -0
  51. data/vendor/rlite/deps/lua/src/lua.h +388 -0
  52. data/vendor/rlite/deps/lua/src/lua_bit.c +189 -0
  53. data/vendor/rlite/deps/lua/src/lua_cjson.c +1427 -0
  54. data/vendor/rlite/deps/lua/src/lua_cmsgpack.c +957 -0
  55. data/vendor/rlite/deps/lua/src/lua_struct.c +421 -0
  56. data/vendor/rlite/deps/lua/src/luac.c +200 -0
  57. data/vendor/rlite/deps/lua/src/luaconf.h +763 -0
  58. data/vendor/rlite/deps/lua/src/lualib.h +53 -0
  59. data/vendor/rlite/deps/lua/src/lundump.c +227 -0
  60. data/vendor/rlite/deps/lua/src/lundump.h +36 -0
  61. data/vendor/rlite/deps/lua/src/lvm.c +767 -0
  62. data/vendor/rlite/deps/lua/src/lvm.h +36 -0
  63. data/vendor/rlite/deps/lua/src/lzio.c +82 -0
  64. data/vendor/rlite/deps/lua/src/lzio.h +67 -0
  65. data/vendor/rlite/deps/lua/src/print.c +227 -0
  66. data/vendor/rlite/deps/lua/src/strbuf.c +251 -0
  67. data/vendor/rlite/deps/lua/src/strbuf.h +154 -0
  68. data/vendor/rlite/src/Makefile +97 -25
  69. data/vendor/rlite/{deps → src}/crc64.c +0 -0
  70. data/vendor/rlite/{deps → src}/crc64.h +0 -0
  71. data/vendor/rlite/src/dump.c +2 -2
  72. data/vendor/rlite/{deps → src}/endianconv.h +0 -0
  73. data/vendor/rlite/src/hirlite.c +134 -90
  74. data/vendor/rlite/src/hirlite.h +34 -1
  75. data/vendor/rlite/{deps → src}/hyperloglog.c +0 -0
  76. data/vendor/rlite/{deps → src}/hyperloglog.h +0 -0
  77. data/vendor/rlite/{deps → src}/lzf.h +0 -0
  78. data/vendor/rlite/{deps → src}/lzfP.h +0 -0
  79. data/vendor/rlite/{deps → src}/lzf_c.c +0 -0
  80. data/vendor/rlite/{deps → src}/lzf_d.c +0 -0
  81. data/vendor/rlite/src/page_btree.c +10 -10
  82. data/vendor/rlite/src/page_btree.h +2 -2
  83. data/vendor/rlite/src/page_list.c +3 -3
  84. data/vendor/rlite/src/page_list.h +1 -1
  85. data/vendor/rlite/src/page_multi_string.c +1 -1
  86. data/vendor/rlite/src/page_skiplist.c +1 -1
  87. data/vendor/rlite/src/page_skiplist.h +1 -1
  88. data/vendor/rlite/src/rand.c +93 -0
  89. data/vendor/rlite/src/rand.h +38 -0
  90. data/vendor/rlite/src/restore.c +286 -155
  91. data/vendor/rlite/src/restore.h +6 -0
  92. data/vendor/rlite/src/rlite.c +30 -30
  93. data/vendor/rlite/src/rlite.h +1 -1
  94. data/vendor/rlite/src/scripting.c +1138 -0
  95. data/vendor/rlite/src/scripting.h +10 -0
  96. data/vendor/rlite/{deps → src}/sha1.c +0 -0
  97. data/vendor/rlite/{deps → src}/sha1.h +0 -0
  98. data/vendor/rlite/src/solarisfixes.h +54 -0
  99. data/vendor/rlite/src/sort.c +4 -2
  100. data/vendor/rlite/src/sort.h +1 -1
  101. data/vendor/rlite/src/type_string.c +1 -1
  102. data/vendor/rlite/src/util.c +4 -4
  103. data/vendor/rlite/src/util.h +3 -3
  104. data/vendor/rlite/{deps → src}/utilfromredis.c +0 -0
  105. data/vendor/rlite/{deps → src}/utilfromredis.h +0 -0
  106. metadata +84 -15
@@ -0,0 +1,1427 @@
1
+ /* Lua CJSON - JSON support for Lua
2
+ *
3
+ * Copyright (c) 2010-2012 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 <limits.h>
43
+ #include "lua.h"
44
+ #include "lauxlib.h"
45
+
46
+ #include "strbuf.h"
47
+ #include "fpconv.h"
48
+
49
+ #include "../../../src/solarisfixes.h"
50
+
51
+ #ifndef CJSON_MODNAME
52
+ #define CJSON_MODNAME "cjson"
53
+ #endif
54
+
55
+ #ifndef CJSON_VERSION
56
+ #define CJSON_VERSION "2.1.0"
57
+ #endif
58
+
59
+ /* Workaround for Solaris platforms missing isinf() */
60
+ #if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))
61
+ #define isinf(x) (!isnan(x) && isnan((x) - (x)))
62
+ #endif
63
+
64
+ #define DEFAULT_SPARSE_CONVERT 0
65
+ #define DEFAULT_SPARSE_RATIO 2
66
+ #define DEFAULT_SPARSE_SAFE 10
67
+ #define DEFAULT_ENCODE_MAX_DEPTH 1000
68
+ #define DEFAULT_DECODE_MAX_DEPTH 1000
69
+ #define DEFAULT_ENCODE_INVALID_NUMBERS 0
70
+ #define DEFAULT_DECODE_INVALID_NUMBERS 1
71
+ #define DEFAULT_ENCODE_KEEP_BUFFER 1
72
+ #define DEFAULT_ENCODE_NUMBER_PRECISION 14
73
+
74
+ #ifdef DISABLE_INVALID_NUMBERS
75
+ #undef DEFAULT_DECODE_INVALID_NUMBERS
76
+ #define DEFAULT_DECODE_INVALID_NUMBERS 0
77
+ #endif
78
+
79
+ typedef enum {
80
+ T_OBJ_BEGIN,
81
+ T_OBJ_END,
82
+ T_ARR_BEGIN,
83
+ T_ARR_END,
84
+ T_STRING,
85
+ T_NUMBER,
86
+ T_BOOLEAN,
87
+ T_NULL,
88
+ T_COLON,
89
+ T_COMMA,
90
+ T_END,
91
+ T_WHITESPACE,
92
+ T_ERROR,
93
+ T_UNKNOWN
94
+ } json_token_type_t;
95
+
96
+ static const char *json_token_type_name[] = {
97
+ "T_OBJ_BEGIN",
98
+ "T_OBJ_END",
99
+ "T_ARR_BEGIN",
100
+ "T_ARR_END",
101
+ "T_STRING",
102
+ "T_NUMBER",
103
+ "T_BOOLEAN",
104
+ "T_NULL",
105
+ "T_COLON",
106
+ "T_COMMA",
107
+ "T_END",
108
+ "T_WHITESPACE",
109
+ "T_ERROR",
110
+ "T_UNKNOWN",
111
+ NULL
112
+ };
113
+
114
+ typedef struct {
115
+ json_token_type_t ch2token[256];
116
+ char escape2char[256]; /* Decoding */
117
+
118
+ /* encode_buf is only allocated and used when
119
+ * encode_keep_buffer is set */
120
+ strbuf_t encode_buf;
121
+
122
+ int encode_sparse_convert;
123
+ int encode_sparse_ratio;
124
+ int encode_sparse_safe;
125
+ int encode_max_depth;
126
+ int encode_invalid_numbers; /* 2 => Encode as "null" */
127
+ int encode_number_precision;
128
+ int encode_keep_buffer;
129
+
130
+ int decode_invalid_numbers;
131
+ int decode_max_depth;
132
+ } json_config_t;
133
+
134
+ typedef struct {
135
+ const char *data;
136
+ const char *ptr;
137
+ strbuf_t *tmp; /* Temporary storage for strings */
138
+ json_config_t *cfg;
139
+ int current_depth;
140
+ } json_parse_t;
141
+
142
+ typedef struct {
143
+ json_token_type_t type;
144
+ int index;
145
+ union {
146
+ const char *string;
147
+ double number;
148
+ int boolean;
149
+ } value;
150
+ int string_len;
151
+ } json_token_t;
152
+
153
+ static const char *char2escape[256] = {
154
+ "\\u0000", "\\u0001", "\\u0002", "\\u0003",
155
+ "\\u0004", "\\u0005", "\\u0006", "\\u0007",
156
+ "\\b", "\\t", "\\n", "\\u000b",
157
+ "\\f", "\\r", "\\u000e", "\\u000f",
158
+ "\\u0010", "\\u0011", "\\u0012", "\\u0013",
159
+ "\\u0014", "\\u0015", "\\u0016", "\\u0017",
160
+ "\\u0018", "\\u0019", "\\u001a", "\\u001b",
161
+ "\\u001c", "\\u001d", "\\u001e", "\\u001f",
162
+ NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL,
163
+ 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, NULL,
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,
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, "\\u007f",
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
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
184
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
185
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
186
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
187
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
188
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
189
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
190
+ };
191
+
192
+ /* ===== CONFIGURATION ===== */
193
+
194
+ static json_config_t *json_fetch_config(lua_State *l)
195
+ {
196
+ json_config_t *cfg;
197
+
198
+ cfg = lua_touserdata(l, lua_upvalueindex(1));
199
+ if (!cfg)
200
+ luaL_error(l, "BUG: Unable to fetch CJSON configuration");
201
+
202
+ return cfg;
203
+ }
204
+
205
+ /* Ensure the correct number of arguments have been provided.
206
+ * Pad with nil to allow other functions to simply check arg[i]
207
+ * to find whether an argument was provided */
208
+ static json_config_t *json_arg_init(lua_State *l, int args)
209
+ {
210
+ luaL_argcheck(l, lua_gettop(l) <= args, args + 1,
211
+ "found too many arguments");
212
+
213
+ while (lua_gettop(l) < args)
214
+ lua_pushnil(l);
215
+
216
+ return json_fetch_config(l);
217
+ }
218
+
219
+ /* Process integer options for configuration functions */
220
+ static int json_integer_option(lua_State *l, int optindex, int *setting,
221
+ int min, int max)
222
+ {
223
+ char errmsg[64];
224
+ int value;
225
+
226
+ if (!lua_isnil(l, optindex)) {
227
+ value = luaL_checkinteger(l, optindex);
228
+ snprintf(errmsg, sizeof(errmsg), "expected integer between %d and %d", min, max);
229
+ luaL_argcheck(l, min <= value && value <= max, 1, errmsg);
230
+ *setting = value;
231
+ }
232
+
233
+ lua_pushinteger(l, *setting);
234
+
235
+ return 1;
236
+ }
237
+
238
+ /* Process enumerated arguments for a configuration function */
239
+ static int json_enum_option(lua_State *l, int optindex, int *setting,
240
+ const char **options, int bool_true)
241
+ {
242
+ static const char *bool_options[] = { "off", "on", NULL };
243
+
244
+ if (!options) {
245
+ options = bool_options;
246
+ bool_true = 1;
247
+ }
248
+
249
+ if (!lua_isnil(l, optindex)) {
250
+ if (bool_true && lua_isboolean(l, optindex))
251
+ *setting = lua_toboolean(l, optindex) * bool_true;
252
+ else
253
+ *setting = luaL_checkoption(l, optindex, NULL, options);
254
+ }
255
+
256
+ if (bool_true && (*setting == 0 || *setting == bool_true))
257
+ lua_pushboolean(l, *setting);
258
+ else
259
+ lua_pushstring(l, options[*setting]);
260
+
261
+ return 1;
262
+ }
263
+
264
+ /* Configures handling of extremely sparse arrays:
265
+ * convert: Convert extremely sparse arrays into objects? Otherwise error.
266
+ * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio
267
+ * safe: Always use an array when the max index <= safe */
268
+ static int json_cfg_encode_sparse_array(lua_State *l)
269
+ {
270
+ json_config_t *cfg = json_arg_init(l, 3);
271
+
272
+ json_enum_option(l, 1, &cfg->encode_sparse_convert, NULL, 1);
273
+ json_integer_option(l, 2, &cfg->encode_sparse_ratio, 0, INT_MAX);
274
+ json_integer_option(l, 3, &cfg->encode_sparse_safe, 0, INT_MAX);
275
+
276
+ return 3;
277
+ }
278
+
279
+ /* Configures the maximum number of nested arrays/objects allowed when
280
+ * encoding */
281
+ static int json_cfg_encode_max_depth(lua_State *l)
282
+ {
283
+ json_config_t *cfg = json_arg_init(l, 1);
284
+
285
+ return json_integer_option(l, 1, &cfg->encode_max_depth, 1, INT_MAX);
286
+ }
287
+
288
+ /* Configures the maximum number of nested arrays/objects allowed when
289
+ * encoding */
290
+ static int json_cfg_decode_max_depth(lua_State *l)
291
+ {
292
+ json_config_t *cfg = json_arg_init(l, 1);
293
+
294
+ return json_integer_option(l, 1, &cfg->decode_max_depth, 1, INT_MAX);
295
+ }
296
+
297
+ /* Configures number precision when converting doubles to text */
298
+ static int json_cfg_encode_number_precision(lua_State *l)
299
+ {
300
+ json_config_t *cfg = json_arg_init(l, 1);
301
+
302
+ return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14);
303
+ }
304
+
305
+ /* Configures JSON encoding buffer persistence */
306
+ static int json_cfg_encode_keep_buffer(lua_State *l)
307
+ {
308
+ json_config_t *cfg = json_arg_init(l, 1);
309
+ int old_value;
310
+
311
+ old_value = cfg->encode_keep_buffer;
312
+
313
+ json_enum_option(l, 1, &cfg->encode_keep_buffer, NULL, 1);
314
+
315
+ /* Init / free the buffer if the setting has changed */
316
+ if (old_value ^ cfg->encode_keep_buffer) {
317
+ if (cfg->encode_keep_buffer)
318
+ strbuf_init(&cfg->encode_buf, 0);
319
+ else
320
+ strbuf_free(&cfg->encode_buf);
321
+ }
322
+
323
+ return 1;
324
+ }
325
+
326
+ #if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)
327
+ void json_verify_invalid_number_setting(lua_State *l, int *setting)
328
+ {
329
+ if (*setting == 1) {
330
+ *setting = 0;
331
+ luaL_error(l, "Infinity, NaN, and/or hexadecimal numbers are not supported.");
332
+ }
333
+ }
334
+ #else
335
+ #define json_verify_invalid_number_setting(l, s) do { } while(0)
336
+ #endif
337
+
338
+ static int json_cfg_encode_invalid_numbers(lua_State *l)
339
+ {
340
+ static const char *options[] = { "off", "on", "null", NULL };
341
+ json_config_t *cfg = json_arg_init(l, 1);
342
+
343
+ json_enum_option(l, 1, &cfg->encode_invalid_numbers, options, 1);
344
+
345
+ json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);
346
+
347
+ return 1;
348
+ }
349
+
350
+ static int json_cfg_decode_invalid_numbers(lua_State *l)
351
+ {
352
+ json_config_t *cfg = json_arg_init(l, 1);
353
+
354
+ json_enum_option(l, 1, &cfg->decode_invalid_numbers, NULL, 1);
355
+
356
+ json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);
357
+
358
+ return 1;
359
+ }
360
+
361
+ static int json_destroy_config(lua_State *l)
362
+ {
363
+ json_config_t *cfg;
364
+
365
+ cfg = lua_touserdata(l, 1);
366
+ if (cfg)
367
+ strbuf_free(&cfg->encode_buf);
368
+ cfg = NULL;
369
+
370
+ return 0;
371
+ }
372
+
373
+ static void json_create_config(lua_State *l)
374
+ {
375
+ json_config_t *cfg;
376
+ int i;
377
+
378
+ cfg = lua_newuserdata(l, sizeof(*cfg));
379
+
380
+ /* Create GC method to clean up strbuf */
381
+ lua_newtable(l);
382
+ lua_pushcfunction(l, json_destroy_config);
383
+ lua_setfield(l, -2, "__gc");
384
+ lua_setmetatable(l, -2);
385
+
386
+ cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;
387
+ cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;
388
+ cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;
389
+ cfg->encode_max_depth = DEFAULT_ENCODE_MAX_DEPTH;
390
+ cfg->decode_max_depth = DEFAULT_DECODE_MAX_DEPTH;
391
+ cfg->encode_invalid_numbers = DEFAULT_ENCODE_INVALID_NUMBERS;
392
+ cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS;
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
+ /* Ensure there are enough slots free to traverse a table (key,
540
+ * value) and push a string for a potential error message.
541
+ *
542
+ * Unlike "decode", the key and value are still on the stack when
543
+ * lua_checkstack() is called. Hence an extra slot for luaL_error()
544
+ * below is required just in case the next check to lua_checkstack()
545
+ * fails.
546
+ *
547
+ * While this won't cause a crash due to the EXTRA_STACK reserve
548
+ * slots, it would still be an improper use of the API. */
549
+ if (current_depth <= cfg->encode_max_depth && lua_checkstack(l, 3))
550
+ return;
551
+
552
+ if (!cfg->encode_keep_buffer)
553
+ strbuf_free(json);
554
+
555
+ luaL_error(l, "Cannot serialise, excessive nesting (%d)",
556
+ current_depth);
557
+ }
558
+
559
+ static void json_append_data(lua_State *l, json_config_t *cfg,
560
+ int current_depth, strbuf_t *json);
561
+
562
+ /* json_append_array args:
563
+ * - lua_State
564
+ * - JSON strbuf
565
+ * - Size of passwd Lua array (top of stack) */
566
+ static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,
567
+ strbuf_t *json, int array_length)
568
+ {
569
+ int comma, i;
570
+
571
+ strbuf_append_char(json, '[');
572
+
573
+ comma = 0;
574
+ for (i = 1; i <= array_length; i++) {
575
+ if (comma)
576
+ strbuf_append_char(json, ',');
577
+ else
578
+ comma = 1;
579
+
580
+ lua_rawgeti(l, -1, i);
581
+ json_append_data(l, cfg, current_depth, json);
582
+ lua_pop(l, 1);
583
+ }
584
+
585
+ strbuf_append_char(json, ']');
586
+ }
587
+
588
+ static void json_append_number(lua_State *l, json_config_t *cfg,
589
+ strbuf_t *json, int lindex)
590
+ {
591
+ double num = lua_tonumber(l, lindex);
592
+ int len;
593
+
594
+ if (cfg->encode_invalid_numbers == 0) {
595
+ /* Prevent encoding invalid numbers */
596
+ if (isinf(num) || isnan(num))
597
+ json_encode_exception(l, cfg, json, lindex, "must not be NaN or Inf");
598
+ } else if (cfg->encode_invalid_numbers == 1) {
599
+ /* Encode invalid numbers, but handle "nan" separately
600
+ * since some platforms may encode as "-nan". */
601
+ if (isnan(num)) {
602
+ strbuf_append_mem(json, "nan", 3);
603
+ return;
604
+ }
605
+ } else {
606
+ /* Encode invalid numbers as "null" */
607
+ if (isinf(num) || isnan(num)) {
608
+ strbuf_append_mem(json, "null", 4);
609
+ return;
610
+ }
611
+ }
612
+
613
+ strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);
614
+ len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision);
615
+ strbuf_extend_length(json, len);
616
+ }
617
+
618
+ static void json_append_object(lua_State *l, json_config_t *cfg,
619
+ int current_depth, strbuf_t *json)
620
+ {
621
+ int comma, keytype;
622
+
623
+ /* Object */
624
+ strbuf_append_char(json, '{');
625
+
626
+ lua_pushnil(l);
627
+ /* table, startkey */
628
+ comma = 0;
629
+ while (lua_next(l, -2) != 0) {
630
+ if (comma)
631
+ strbuf_append_char(json, ',');
632
+ else
633
+ comma = 1;
634
+
635
+ /* table, key, value */
636
+ keytype = lua_type(l, -2);
637
+ if (keytype == LUA_TNUMBER) {
638
+ strbuf_append_char(json, '"');
639
+ json_append_number(l, cfg, json, -2);
640
+ strbuf_append_mem(json, "\":", 2);
641
+ } else if (keytype == LUA_TSTRING) {
642
+ json_append_string(l, json, -2);
643
+ strbuf_append_char(json, ':');
644
+ } else {
645
+ json_encode_exception(l, cfg, json, -2,
646
+ "table key must be a number or string");
647
+ /* never returns */
648
+ }
649
+
650
+ /* table, key, value */
651
+ json_append_data(l, cfg, current_depth, json);
652
+ lua_pop(l, 1);
653
+ /* table, key */
654
+ }
655
+
656
+ strbuf_append_char(json, '}');
657
+ }
658
+
659
+ /* Serialise Lua data into JSON string. */
660
+ static void json_append_data(lua_State *l, json_config_t *cfg,
661
+ int current_depth, strbuf_t *json)
662
+ {
663
+ int len;
664
+
665
+ switch (lua_type(l, -1)) {
666
+ case LUA_TSTRING:
667
+ json_append_string(l, json, -1);
668
+ break;
669
+ case LUA_TNUMBER:
670
+ json_append_number(l, cfg, json, -1);
671
+ break;
672
+ case LUA_TBOOLEAN:
673
+ if (lua_toboolean(l, -1))
674
+ strbuf_append_mem(json, "true", 4);
675
+ else
676
+ strbuf_append_mem(json, "false", 5);
677
+ break;
678
+ case LUA_TTABLE:
679
+ current_depth++;
680
+ json_check_encode_depth(l, cfg, current_depth, json);
681
+ len = lua_array_length(l, cfg, json);
682
+ if (len > 0)
683
+ json_append_array(l, cfg, current_depth, json, len);
684
+ else
685
+ json_append_object(l, cfg, current_depth, json);
686
+ break;
687
+ case LUA_TNIL:
688
+ strbuf_append_mem(json, "null", 4);
689
+ break;
690
+ case LUA_TLIGHTUSERDATA:
691
+ if (lua_touserdata(l, -1) == NULL) {
692
+ strbuf_append_mem(json, "null", 4);
693
+ break;
694
+ }
695
+ default:
696
+ /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,
697
+ * and LUA_TLIGHTUSERDATA) cannot be serialised */
698
+ json_encode_exception(l, cfg, json, -1, "type not supported");
699
+ /* never returns */
700
+ }
701
+ }
702
+
703
+ static int json_encode(lua_State *l)
704
+ {
705
+ json_config_t *cfg = json_fetch_config(l);
706
+ strbuf_t local_encode_buf;
707
+ strbuf_t *encode_buf;
708
+ char *json;
709
+ int len;
710
+
711
+ luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
712
+
713
+ if (!cfg->encode_keep_buffer) {
714
+ /* Use private buffer */
715
+ encode_buf = &local_encode_buf;
716
+ strbuf_init(encode_buf, 0);
717
+ } else {
718
+ /* Reuse existing buffer */
719
+ encode_buf = &cfg->encode_buf;
720
+ strbuf_reset(encode_buf);
721
+ }
722
+
723
+ json_append_data(l, cfg, 0, encode_buf);
724
+ json = strbuf_string(encode_buf, &len);
725
+
726
+ lua_pushlstring(l, json, len);
727
+
728
+ if (!cfg->encode_keep_buffer)
729
+ strbuf_free(encode_buf);
730
+
731
+ return 1;
732
+ }
733
+
734
+ /* ===== DECODING ===== */
735
+
736
+ static void json_process_value(lua_State *l, json_parse_t *json,
737
+ json_token_t *token);
738
+
739
+ static int hexdigit2int(char hex)
740
+ {
741
+ if ('0' <= hex && hex <= '9')
742
+ return hex - '0';
743
+
744
+ /* Force lowercase */
745
+ hex |= 0x20;
746
+ if ('a' <= hex && hex <= 'f')
747
+ return 10 + hex - 'a';
748
+
749
+ return -1;
750
+ }
751
+
752
+ static int decode_hex4(const char *hex)
753
+ {
754
+ int digit[4];
755
+ int i;
756
+
757
+ /* Convert ASCII hex digit to numeric digit
758
+ * Note: this returns an error for invalid hex digits, including
759
+ * NULL */
760
+ for (i = 0; i < 4; i++) {
761
+ digit[i] = hexdigit2int(hex[i]);
762
+ if (digit[i] < 0) {
763
+ return -1;
764
+ }
765
+ }
766
+
767
+ return (digit[0] << 12) +
768
+ (digit[1] << 8) +
769
+ (digit[2] << 4) +
770
+ digit[3];
771
+ }
772
+
773
+ /* Converts a Unicode codepoint to UTF-8.
774
+ * Returns UTF-8 string length, and up to 4 bytes in *utf8 */
775
+ static int codepoint_to_utf8(char *utf8, int codepoint)
776
+ {
777
+ /* 0xxxxxxx */
778
+ if (codepoint <= 0x7F) {
779
+ utf8[0] = codepoint;
780
+ return 1;
781
+ }
782
+
783
+ /* 110xxxxx 10xxxxxx */
784
+ if (codepoint <= 0x7FF) {
785
+ utf8[0] = (codepoint >> 6) | 0xC0;
786
+ utf8[1] = (codepoint & 0x3F) | 0x80;
787
+ return 2;
788
+ }
789
+
790
+ /* 1110xxxx 10xxxxxx 10xxxxxx */
791
+ if (codepoint <= 0xFFFF) {
792
+ utf8[0] = (codepoint >> 12) | 0xE0;
793
+ utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80;
794
+ utf8[2] = (codepoint & 0x3F) | 0x80;
795
+ return 3;
796
+ }
797
+
798
+ /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
799
+ if (codepoint <= 0x1FFFFF) {
800
+ utf8[0] = (codepoint >> 18) | 0xF0;
801
+ utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80;
802
+ utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80;
803
+ utf8[3] = (codepoint & 0x3F) | 0x80;
804
+ return 4;
805
+ }
806
+
807
+ return 0;
808
+ }
809
+
810
+
811
+ /* Called when index pointing to beginning of UTF-16 code escape: \uXXXX
812
+ * \u is guaranteed to exist, but the remaining hex characters may be
813
+ * missing.
814
+ * Translate to UTF-8 and append to temporary token string.
815
+ * Must advance index to the next character to be processed.
816
+ * Returns: 0 success
817
+ * -1 error
818
+ */
819
+ static int json_append_unicode_escape(json_parse_t *json)
820
+ {
821
+ char utf8[4]; /* Surrogate pairs require 4 UTF-8 bytes */
822
+ int codepoint;
823
+ int surrogate_low;
824
+ int len;
825
+ int escape_len = 6;
826
+
827
+ /* Fetch UTF-16 code unit */
828
+ codepoint = decode_hex4(json->ptr + 2);
829
+ if (codepoint < 0)
830
+ return -1;
831
+
832
+ /* UTF-16 surrogate pairs take the following 2 byte form:
833
+ * 11011 x yyyyyyyyyy
834
+ * When x = 0: y is the high 10 bits of the codepoint
835
+ * x = 1: y is the low 10 bits of the codepoint
836
+ *
837
+ * Check for a surrogate pair (high or low) */
838
+ if ((codepoint & 0xF800) == 0xD800) {
839
+ /* Error if the 1st surrogate is not high */
840
+ if (codepoint & 0x400)
841
+ return -1;
842
+
843
+ /* Ensure the next code is a unicode escape */
844
+ if (*(json->ptr + escape_len) != '\\' ||
845
+ *(json->ptr + escape_len + 1) != 'u') {
846
+ return -1;
847
+ }
848
+
849
+ /* Fetch the next codepoint */
850
+ surrogate_low = decode_hex4(json->ptr + 2 + escape_len);
851
+ if (surrogate_low < 0)
852
+ return -1;
853
+
854
+ /* Error if the 2nd code is not a low surrogate */
855
+ if ((surrogate_low & 0xFC00) != 0xDC00)
856
+ return -1;
857
+
858
+ /* Calculate Unicode codepoint */
859
+ codepoint = (codepoint & 0x3FF) << 10;
860
+ surrogate_low &= 0x3FF;
861
+ codepoint = (codepoint | surrogate_low) + 0x10000;
862
+ escape_len = 12;
863
+ }
864
+
865
+ /* Convert codepoint to UTF-8 */
866
+ len = codepoint_to_utf8(utf8, codepoint);
867
+ if (!len)
868
+ return -1;
869
+
870
+ /* Append bytes and advance parse index */
871
+ strbuf_append_mem_unsafe(json->tmp, utf8, len);
872
+ json->ptr += escape_len;
873
+
874
+ return 0;
875
+ }
876
+
877
+ static void json_set_token_error(json_token_t *token, json_parse_t *json,
878
+ const char *errtype)
879
+ {
880
+ token->type = T_ERROR;
881
+ token->index = json->ptr - json->data;
882
+ token->value.string = errtype;
883
+ }
884
+
885
+ static void json_next_string_token(json_parse_t *json, json_token_t *token)
886
+ {
887
+ char *escape2char = json->cfg->escape2char;
888
+ char ch;
889
+
890
+ /* Caller must ensure a string is next */
891
+ assert(*json->ptr == '"');
892
+
893
+ /* Skip " */
894
+ json->ptr++;
895
+
896
+ /* json->tmp is the temporary strbuf used to accumulate the
897
+ * decoded string value.
898
+ * json->tmp is sized to handle JSON containing only a string value.
899
+ */
900
+ strbuf_reset(json->tmp);
901
+
902
+ while ((ch = *json->ptr) != '"') {
903
+ if (!ch) {
904
+ /* Premature end of the string */
905
+ json_set_token_error(token, json, "unexpected end of string");
906
+ return;
907
+ }
908
+
909
+ /* Handle escapes */
910
+ if (ch == '\\') {
911
+ /* Fetch escape character */
912
+ ch = *(json->ptr + 1);
913
+
914
+ /* Translate escape code and append to tmp string */
915
+ ch = escape2char[(unsigned char)ch];
916
+ if (ch == 'u') {
917
+ if (json_append_unicode_escape(json) == 0)
918
+ continue;
919
+
920
+ json_set_token_error(token, json,
921
+ "invalid unicode escape code");
922
+ return;
923
+ }
924
+ if (!ch) {
925
+ json_set_token_error(token, json, "invalid escape code");
926
+ return;
927
+ }
928
+
929
+ /* Skip '\' */
930
+ json->ptr++;
931
+ }
932
+ /* Append normal character or translated single character
933
+ * Unicode escapes are handled above */
934
+ strbuf_append_char_unsafe(json->tmp, ch);
935
+ json->ptr++;
936
+ }
937
+ json->ptr++; /* Eat final quote (") */
938
+
939
+ strbuf_ensure_null(json->tmp);
940
+
941
+ token->type = T_STRING;
942
+ token->value.string = strbuf_string(json->tmp, &token->string_len);
943
+ }
944
+
945
+ /* JSON numbers should take the following form:
946
+ * -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)?
947
+ *
948
+ * json_next_number_token() uses strtod() which allows other forms:
949
+ * - numbers starting with '+'
950
+ * - NaN, -NaN, infinity, -infinity
951
+ * - hexadecimal numbers
952
+ * - numbers with leading zeros
953
+ *
954
+ * json_is_invalid_number() detects "numbers" which may pass strtod()'s
955
+ * error checking, but should not be allowed with strict JSON.
956
+ *
957
+ * json_is_invalid_number() may pass numbers which cause strtod()
958
+ * to generate an error.
959
+ */
960
+ static int json_is_invalid_number(json_parse_t *json)
961
+ {
962
+ const char *p = json->ptr;
963
+
964
+ /* Reject numbers starting with + */
965
+ if (*p == '+')
966
+ return 1;
967
+
968
+ /* Skip minus sign if it exists */
969
+ if (*p == '-')
970
+ p++;
971
+
972
+ /* Reject numbers starting with 0x, or leading zeros */
973
+ if (*p == '0') {
974
+ int ch2 = *(p + 1);
975
+
976
+ if ((ch2 | 0x20) == 'x' || /* Hex */
977
+ ('0' <= ch2 && ch2 <= '9')) /* Leading zero */
978
+ return 1;
979
+
980
+ return 0;
981
+ } else if (*p <= '9') {
982
+ return 0; /* Ordinary number */
983
+ }
984
+
985
+ /* Reject inf/nan */
986
+ if (!strncasecmp(p, "inf", 3))
987
+ return 1;
988
+ if (!strncasecmp(p, "nan", 3))
989
+ return 1;
990
+
991
+ /* Pass all other numbers which may still be invalid, but
992
+ * strtod() will catch them. */
993
+ return 0;
994
+ }
995
+
996
+ static void json_next_number_token(json_parse_t *json, json_token_t *token)
997
+ {
998
+ char *endptr;
999
+
1000
+ token->type = T_NUMBER;
1001
+ token->value.number = fpconv_strtod(json->ptr, &endptr);
1002
+ if (json->ptr == endptr)
1003
+ json_set_token_error(token, json, "invalid number");
1004
+ else
1005
+ json->ptr = endptr; /* Skip the processed number */
1006
+
1007
+ return;
1008
+ }
1009
+
1010
+ /* Fills in the token struct.
1011
+ * T_STRING will return a pointer to the json_parse_t temporary string
1012
+ * T_ERROR will leave the json->ptr pointer at the error.
1013
+ */
1014
+ static void json_next_token(json_parse_t *json, json_token_t *token)
1015
+ {
1016
+ const json_token_type_t *ch2token = json->cfg->ch2token;
1017
+ int ch;
1018
+
1019
+ /* Eat whitespace. */
1020
+ while (1) {
1021
+ ch = (unsigned char)*(json->ptr);
1022
+ token->type = ch2token[ch];
1023
+ if (token->type != T_WHITESPACE)
1024
+ break;
1025
+ json->ptr++;
1026
+ }
1027
+
1028
+ /* Store location of new token. Required when throwing errors
1029
+ * for unexpected tokens (syntax errors). */
1030
+ token->index = json->ptr - json->data;
1031
+
1032
+ /* Don't advance the pointer for an error or the end */
1033
+ if (token->type == T_ERROR) {
1034
+ json_set_token_error(token, json, "invalid token");
1035
+ return;
1036
+ }
1037
+
1038
+ if (token->type == T_END) {
1039
+ return;
1040
+ }
1041
+
1042
+ /* Found a known single character token, advance index and return */
1043
+ if (token->type != T_UNKNOWN) {
1044
+ json->ptr++;
1045
+ return;
1046
+ }
1047
+
1048
+ /* Process characters which triggered T_UNKNOWN
1049
+ *
1050
+ * Must use strncmp() to match the front of the JSON string.
1051
+ * JSON identifier must be lowercase.
1052
+ * When strict_numbers if disabled, either case is allowed for
1053
+ * Infinity/NaN (since we are no longer following the spec..) */
1054
+ if (ch == '"') {
1055
+ json_next_string_token(json, token);
1056
+ return;
1057
+ } else if (ch == '-' || ('0' <= ch && ch <= '9')) {
1058
+ if (!json->cfg->decode_invalid_numbers && json_is_invalid_number(json)) {
1059
+ json_set_token_error(token, json, "invalid number");
1060
+ return;
1061
+ }
1062
+ json_next_number_token(json, token);
1063
+ return;
1064
+ } else if (!strncmp(json->ptr, "true", 4)) {
1065
+ token->type = T_BOOLEAN;
1066
+ token->value.boolean = 1;
1067
+ json->ptr += 4;
1068
+ return;
1069
+ } else if (!strncmp(json->ptr, "false", 5)) {
1070
+ token->type = T_BOOLEAN;
1071
+ token->value.boolean = 0;
1072
+ json->ptr += 5;
1073
+ return;
1074
+ } else if (!strncmp(json->ptr, "null", 4)) {
1075
+ token->type = T_NULL;
1076
+ json->ptr += 4;
1077
+ return;
1078
+ } else if (json->cfg->decode_invalid_numbers &&
1079
+ json_is_invalid_number(json)) {
1080
+ /* When decode_invalid_numbers is enabled, only attempt to process
1081
+ * numbers we know are invalid JSON (Inf, NaN, hex)
1082
+ * This is required to generate an appropriate token error,
1083
+ * otherwise all bad tokens will register as "invalid number"
1084
+ */
1085
+ json_next_number_token(json, token);
1086
+ return;
1087
+ }
1088
+
1089
+ /* Token starts with t/f/n but isn't recognised above. */
1090
+ json_set_token_error(token, json, "invalid token");
1091
+ }
1092
+
1093
+ /* This function does not return.
1094
+ * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED.
1095
+ * The only supported exception is the temporary parser string
1096
+ * json->tmp struct.
1097
+ * json and token should exist on the stack somewhere.
1098
+ * luaL_error() will long_jmp and release the stack */
1099
+ static void json_throw_parse_error(lua_State *l, json_parse_t *json,
1100
+ const char *exp, json_token_t *token)
1101
+ {
1102
+ const char *found;
1103
+
1104
+ strbuf_free(json->tmp);
1105
+
1106
+ if (token->type == T_ERROR)
1107
+ found = token->value.string;
1108
+ else
1109
+ found = json_token_type_name[token->type];
1110
+
1111
+ /* Note: token->index is 0 based, display starting from 1 */
1112
+ luaL_error(l, "Expected %s but found %s at character %d",
1113
+ exp, found, token->index + 1);
1114
+ }
1115
+
1116
+ static inline void json_decode_ascend(json_parse_t *json)
1117
+ {
1118
+ json->current_depth--;
1119
+ }
1120
+
1121
+ static void json_decode_descend(lua_State *l, json_parse_t *json, int slots)
1122
+ {
1123
+ json->current_depth++;
1124
+
1125
+ if (json->current_depth <= json->cfg->decode_max_depth &&
1126
+ lua_checkstack(l, slots)) {
1127
+ return;
1128
+ }
1129
+
1130
+ strbuf_free(json->tmp);
1131
+ luaL_error(l, "Found too many nested data structures (%d) at character %d",
1132
+ json->current_depth, json->ptr - json->data);
1133
+ }
1134
+
1135
+ static void json_parse_object_context(lua_State *l, json_parse_t *json)
1136
+ {
1137
+ json_token_t token;
1138
+
1139
+ /* 3 slots required:
1140
+ * .., table, key, value */
1141
+ json_decode_descend(l, json, 3);
1142
+
1143
+ lua_newtable(l);
1144
+
1145
+ json_next_token(json, &token);
1146
+
1147
+ /* Handle empty objects */
1148
+ if (token.type == T_OBJ_END) {
1149
+ json_decode_ascend(json);
1150
+ return;
1151
+ }
1152
+
1153
+ while (1) {
1154
+ if (token.type != T_STRING)
1155
+ json_throw_parse_error(l, json, "object key string", &token);
1156
+
1157
+ /* Push key */
1158
+ lua_pushlstring(l, token.value.string, token.string_len);
1159
+
1160
+ json_next_token(json, &token);
1161
+ if (token.type != T_COLON)
1162
+ json_throw_parse_error(l, json, "colon", &token);
1163
+
1164
+ /* Fetch value */
1165
+ json_next_token(json, &token);
1166
+ json_process_value(l, json, &token);
1167
+
1168
+ /* Set key = value */
1169
+ lua_rawset(l, -3);
1170
+
1171
+ json_next_token(json, &token);
1172
+
1173
+ if (token.type == T_OBJ_END) {
1174
+ json_decode_ascend(json);
1175
+ return;
1176
+ }
1177
+
1178
+ if (token.type != T_COMMA)
1179
+ json_throw_parse_error(l, json, "comma or object end", &token);
1180
+
1181
+ json_next_token(json, &token);
1182
+ }
1183
+ }
1184
+
1185
+ /* Handle the array context */
1186
+ static void json_parse_array_context(lua_State *l, json_parse_t *json)
1187
+ {
1188
+ json_token_t token;
1189
+ int i;
1190
+
1191
+ /* 2 slots required:
1192
+ * .., table, value */
1193
+ json_decode_descend(l, json, 2);
1194
+
1195
+ lua_newtable(l);
1196
+
1197
+ json_next_token(json, &token);
1198
+
1199
+ /* Handle empty arrays */
1200
+ if (token.type == T_ARR_END) {
1201
+ json_decode_ascend(json);
1202
+ return;
1203
+ }
1204
+
1205
+ for (i = 1; ; i++) {
1206
+ json_process_value(l, json, &token);
1207
+ lua_rawseti(l, -2, i); /* arr[i] = value */
1208
+
1209
+ json_next_token(json, &token);
1210
+
1211
+ if (token.type == T_ARR_END) {
1212
+ json_decode_ascend(json);
1213
+ return;
1214
+ }
1215
+
1216
+ if (token.type != T_COMMA)
1217
+ json_throw_parse_error(l, json, "comma or array end", &token);
1218
+
1219
+ json_next_token(json, &token);
1220
+ }
1221
+ }
1222
+
1223
+ /* Handle the "value" context */
1224
+ static void json_process_value(lua_State *l, json_parse_t *json,
1225
+ json_token_t *token)
1226
+ {
1227
+ switch (token->type) {
1228
+ case T_STRING:
1229
+ lua_pushlstring(l, token->value.string, token->string_len);
1230
+ break;;
1231
+ case T_NUMBER:
1232
+ lua_pushnumber(l, token->value.number);
1233
+ break;;
1234
+ case T_BOOLEAN:
1235
+ lua_pushboolean(l, token->value.boolean);
1236
+ break;;
1237
+ case T_OBJ_BEGIN:
1238
+ json_parse_object_context(l, json);
1239
+ break;;
1240
+ case T_ARR_BEGIN:
1241
+ json_parse_array_context(l, json);
1242
+ break;;
1243
+ case T_NULL:
1244
+ /* In Lua, setting "t[k] = nil" will delete k from the table.
1245
+ * Hence a NULL pointer lightuserdata object is used instead */
1246
+ lua_pushlightuserdata(l, NULL);
1247
+ break;;
1248
+ default:
1249
+ json_throw_parse_error(l, json, "value", token);
1250
+ }
1251
+ }
1252
+
1253
+ static int json_decode(lua_State *l)
1254
+ {
1255
+ json_parse_t json;
1256
+ json_token_t token;
1257
+ size_t json_len;
1258
+
1259
+ luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
1260
+
1261
+ json.cfg = json_fetch_config(l);
1262
+ json.data = luaL_checklstring(l, 1, &json_len);
1263
+ json.current_depth = 0;
1264
+ json.ptr = json.data;
1265
+
1266
+ /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)
1267
+ *
1268
+ * CJSON can support any simple data type, hence only the first
1269
+ * character is guaranteed to be ASCII (at worst: '"'). This is
1270
+ * still enough to detect whether the wrong encoding is in use. */
1271
+ if (json_len >= 2 && (!json.data[0] || !json.data[1]))
1272
+ luaL_error(l, "JSON parser does not support UTF-16 or UTF-32");
1273
+
1274
+ /* Ensure the temporary buffer can hold the entire string.
1275
+ * This means we no longer need to do length checks since the decoded
1276
+ * string must be smaller than the entire json string */
1277
+ json.tmp = strbuf_new(json_len);
1278
+
1279
+ json_next_token(&json, &token);
1280
+ json_process_value(l, &json, &token);
1281
+
1282
+ /* Ensure there is no more input left */
1283
+ json_next_token(&json, &token);
1284
+
1285
+ if (token.type != T_END)
1286
+ json_throw_parse_error(l, &json, "the end", &token);
1287
+
1288
+ strbuf_free(json.tmp);
1289
+
1290
+ return 1;
1291
+ }
1292
+
1293
+ /* ===== INITIALISATION ===== */
1294
+
1295
+ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
1296
+ /* Compatibility for Lua 5.1.
1297
+ *
1298
+ * luaL_setfuncs() is used to create a module table where the functions have
1299
+ * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */
1300
+ static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)
1301
+ {
1302
+ int i;
1303
+
1304
+ luaL_checkstack(l, nup, "too many upvalues");
1305
+ for (; reg->name != NULL; reg++) { /* fill the table with given functions */
1306
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
1307
+ lua_pushvalue(l, -nup);
1308
+ lua_pushcclosure(l, reg->func, nup); /* closure with those upvalues */
1309
+ lua_setfield(l, -(nup + 2), reg->name);
1310
+ }
1311
+ lua_pop(l, nup); /* remove upvalues */
1312
+ }
1313
+ #endif
1314
+
1315
+ /* Call target function in protected mode with all supplied args.
1316
+ * Assumes target function only returns a single non-nil value.
1317
+ * Convert and return thrown errors as: nil, "error message" */
1318
+ static int json_protect_conversion(lua_State *l)
1319
+ {
1320
+ int err;
1321
+
1322
+ /* Deliberately throw an error for invalid arguments */
1323
+ luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
1324
+
1325
+ /* pcall() the function stored as upvalue(1) */
1326
+ lua_pushvalue(l, lua_upvalueindex(1));
1327
+ lua_insert(l, 1);
1328
+ err = lua_pcall(l, 1, 1, 0);
1329
+ if (!err)
1330
+ return 1;
1331
+
1332
+ if (err == LUA_ERRRUN) {
1333
+ lua_pushnil(l);
1334
+ lua_insert(l, -2);
1335
+ return 2;
1336
+ }
1337
+
1338
+ /* Since we are not using a custom error handler, the only remaining
1339
+ * errors are memory related */
1340
+ return luaL_error(l, "Memory allocation error in CJSON protected call");
1341
+ }
1342
+
1343
+ /* Return cjson module table */
1344
+ static int lua_cjson_new(lua_State *l)
1345
+ {
1346
+ luaL_Reg reg[] = {
1347
+ { "encode", json_encode },
1348
+ { "decode", json_decode },
1349
+ { "encode_sparse_array", json_cfg_encode_sparse_array },
1350
+ { "encode_max_depth", json_cfg_encode_max_depth },
1351
+ { "decode_max_depth", json_cfg_decode_max_depth },
1352
+ { "encode_number_precision", json_cfg_encode_number_precision },
1353
+ { "encode_keep_buffer", json_cfg_encode_keep_buffer },
1354
+ { "encode_invalid_numbers", json_cfg_encode_invalid_numbers },
1355
+ { "decode_invalid_numbers", json_cfg_decode_invalid_numbers },
1356
+ { "new", lua_cjson_new },
1357
+ { NULL, NULL }
1358
+ };
1359
+
1360
+ /* Initialise number conversions */
1361
+ fpconv_init();
1362
+
1363
+ /* cjson module table */
1364
+ lua_newtable(l);
1365
+
1366
+ /* Register functions with config data as upvalue */
1367
+ json_create_config(l);
1368
+ luaL_setfuncs(l, reg, 1);
1369
+
1370
+ /* Set cjson.null */
1371
+ lua_pushlightuserdata(l, NULL);
1372
+ lua_setfield(l, -2, "null");
1373
+
1374
+ /* Set module name / version fields */
1375
+ lua_pushliteral(l, CJSON_MODNAME);
1376
+ lua_setfield(l, -2, "_NAME");
1377
+ lua_pushliteral(l, CJSON_VERSION);
1378
+ lua_setfield(l, -2, "_VERSION");
1379
+
1380
+ return 1;
1381
+ }
1382
+
1383
+ /* Return cjson.safe module table */
1384
+ static int lua_cjson_safe_new(lua_State *l)
1385
+ {
1386
+ const char *func[] = { "decode", "encode", NULL };
1387
+ int i;
1388
+
1389
+ lua_cjson_new(l);
1390
+
1391
+ /* Fix new() method */
1392
+ lua_pushcfunction(l, lua_cjson_safe_new);
1393
+ lua_setfield(l, -2, "new");
1394
+
1395
+ for (i = 0; func[i]; i++) {
1396
+ lua_getfield(l, -1, func[i]);
1397
+ lua_pushcclosure(l, json_protect_conversion, 1);
1398
+ lua_setfield(l, -2, func[i]);
1399
+ }
1400
+
1401
+ return 1;
1402
+ }
1403
+
1404
+ int luaopen_cjson(lua_State *l)
1405
+ {
1406
+ lua_cjson_new(l);
1407
+
1408
+ #ifdef ENABLE_CJSON_GLOBAL
1409
+ /* Register a global "cjson" table. */
1410
+ lua_pushvalue(l, -1);
1411
+ lua_setglobal(l, CJSON_MODNAME);
1412
+ #endif
1413
+
1414
+ /* Return cjson table */
1415
+ return 1;
1416
+ }
1417
+
1418
+ int luaopen_cjson_safe(lua_State *l)
1419
+ {
1420
+ lua_cjson_safe_new(l);
1421
+
1422
+ /* Return cjson.safe table */
1423
+ return 1;
1424
+ }
1425
+
1426
+ /* vi:ai et sw=4 ts=4:
1427
+ */