rev |
line source |
jbe@121
|
1 #include <lua.h>
|
jbe@121
|
2 #include <lauxlib.h>
|
jbe@122
|
3 #include <stdlib.h>
|
jbe@121
|
4 #include <string.h>
|
jbe@121
|
5
|
jbe@130
|
6 #define JSON_UPVAL_NULLMARK lua_upvalueindex(1)
|
jbe@130
|
7 #define JSON_UPVAL_SHADOWTBL lua_upvalueindex(2)
|
jbe@130
|
8 #define JSON_UPVAL_TYPES lua_upvalueindex(3)
|
jbe@130
|
9 #define JSON_UPVAL_METATABLE lua_upvalueindex(4)
|
jbe@135
|
10 #define JSON_UPVAL_PAIRS_ITERFUNC lua_upvalueindex(5)
|
jbe@135
|
11 #define JSON_UPVAL_IPAIRS_ITERFUNC lua_upvalueindex(6)
|
jbe@123
|
12
|
jbe@124
|
13 #define JSON_STATE_VALUE 0
|
jbe@124
|
14 #define JSON_STATE_OBJECT_KEY 1
|
jbe@124
|
15 #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
|
jbe@124
|
16 #define JSON_STATE_OBJECT_VALUE 3
|
jbe@124
|
17 #define JSON_STATE_OBJECT_SEPARATOR 4
|
jbe@124
|
18 #define JSON_STATE_ARRAY_VALUE 5
|
jbe@124
|
19 #define JSON_STATE_ARRAY_SEPARATOR 6
|
jbe@124
|
20 #define JSON_STATE_END 7
|
jbe@121
|
21
|
jbe@133
|
22 static int json_object(lua_State *L) {
|
jbe@133
|
23 lua_settop(L, 1);
|
jbe@133
|
24 if (lua_isnil(L, 1)) {
|
jbe@133
|
25 lua_settop(L, 0);
|
jbe@133
|
26 lua_newtable(L);
|
jbe@133
|
27 }
|
jbe@133
|
28 lua_pushvalue(L, JSON_UPVAL_METATABLE);
|
jbe@133
|
29 lua_setmetatable(L, 1);
|
jbe@133
|
30 lua_pushvalue(L, 1);
|
jbe@133
|
31 lua_newtable(L); // internal shadow table
|
jbe@133
|
32 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
|
jbe@133
|
33 lua_pushvalue(L, 1);
|
jbe@133
|
34 lua_pushliteral(L, "object");
|
jbe@133
|
35 lua_rawset(L, JSON_UPVAL_TYPES);
|
jbe@133
|
36 return 1;
|
jbe@133
|
37 }
|
jbe@133
|
38
|
jbe@133
|
39 static int json_array(lua_State *L) {
|
jbe@133
|
40 lua_settop(L, 1);
|
jbe@133
|
41 if (lua_isnil(L, 1)) {
|
jbe@133
|
42 lua_settop(L, 0);
|
jbe@133
|
43 lua_newtable(L);
|
jbe@133
|
44 }
|
jbe@133
|
45 lua_pushvalue(L, JSON_UPVAL_METATABLE);
|
jbe@133
|
46 lua_setmetatable(L, 1);
|
jbe@133
|
47 lua_pushvalue(L, 1);
|
jbe@133
|
48 lua_newtable(L); // internal shadow table
|
jbe@133
|
49 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
|
jbe@133
|
50 lua_pushvalue(L, 1);
|
jbe@133
|
51 lua_pushliteral(L, "array");
|
jbe@133
|
52 lua_rawset(L, JSON_UPVAL_TYPES);
|
jbe@133
|
53 return 1;
|
jbe@133
|
54 }
|
jbe@133
|
55
|
jbe@121
|
56 static int json_import(lua_State *L) {
|
jbe@121
|
57 const char *str;
|
jbe@121
|
58 size_t total;
|
jbe@121
|
59 size_t pos = 0;
|
jbe@121
|
60 size_t level = 0;
|
jbe@124
|
61 int mode = JSON_STATE_VALUE;
|
jbe@121
|
62 char c;
|
jbe@121
|
63 luaL_Buffer luabuf;
|
jbe@121
|
64 char *cbuf;
|
jbe@121
|
65 size_t writepos;
|
jbe@121
|
66 lua_settop(L, 1);
|
jbe@121
|
67 str = lua_tostring(L, 1);
|
jbe@121
|
68 total = strlen(str);
|
jbe@121
|
69 json_import_loop:
|
jbe@121
|
70 while (c = str[pos], c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f') pos++;
|
jbe@121
|
71 switch (c) {
|
jbe@121
|
72 case 0:
|
jbe@124
|
73 if (mode == JSON_STATE_END) return 1;
|
jbe@121
|
74 json_import_unexpected_eof:
|
jbe@121
|
75 lua_pushnil(L);
|
jbe@121
|
76 if (level == 0) lua_pushliteral(L, "Empty string");
|
jbe@121
|
77 else lua_pushliteral(L, "Unexpected end of JSON document");
|
jbe@121
|
78 return 2;
|
jbe@121
|
79 case '{':
|
jbe@124
|
80 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
|
jbe@121
|
81 goto json_import_syntax_error;
|
jbe@121
|
82 pos++;
|
jbe@130
|
83 lua_newtable(L); // the external JSON object representation
|
jbe@125
|
84 lua_pushvalue(L, JSON_UPVAL_METATABLE);
|
jbe@125
|
85 lua_setmetatable(L, -2);
|
jbe@127
|
86 lua_pushvalue(L, -1);
|
jbe@127
|
87 lua_pushliteral(L, "object");
|
jbe@127
|
88 lua_rawset(L, JSON_UPVAL_TYPES);
|
jbe@130
|
89 lua_newtable(L); // the internal shadow table
|
jbe@123
|
90 lua_pushvalue(L, -2);
|
jbe@123
|
91 lua_pushvalue(L, -2);
|
jbe@130
|
92 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
|
jbe@124
|
93 mode = JSON_STATE_OBJECT_KEY;
|
jbe@121
|
94 level++;
|
jbe@121
|
95 goto json_import_loop;
|
jbe@121
|
96 case '[':
|
jbe@124
|
97 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
|
jbe@121
|
98 goto json_import_syntax_error;
|
jbe@121
|
99 pos++;
|
jbe@130
|
100 lua_newtable(L); // the external JSON array representation
|
jbe@125
|
101 lua_pushvalue(L, JSON_UPVAL_METATABLE);
|
jbe@125
|
102 lua_setmetatable(L, -2);
|
jbe@127
|
103 lua_pushvalue(L, -1);
|
jbe@127
|
104 lua_pushliteral(L, "array");
|
jbe@127
|
105 lua_rawset(L, JSON_UPVAL_TYPES);
|
jbe@130
|
106 lua_newtable(L); // the internal shadow table
|
jbe@123
|
107 lua_pushvalue(L, -2);
|
jbe@123
|
108 lua_pushvalue(L, -2);
|
jbe@130
|
109 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
|
jbe@130
|
110 lua_pushinteger(L, 0); // magic integer to indicate an array
|
jbe@124
|
111 mode = JSON_STATE_ARRAY_VALUE;
|
jbe@121
|
112 level++;
|
jbe@121
|
113 goto json_import_loop;
|
jbe@121
|
114 case '}':
|
jbe@124
|
115 if (mode != JSON_STATE_OBJECT_KEY && mode != JSON_STATE_OBJECT_SEPARATOR)
|
jbe@121
|
116 goto json_import_syntax_error;
|
jbe@121
|
117 goto json_import_close;
|
jbe@121
|
118 case ']':
|
jbe@124
|
119 if (mode != JSON_STATE_ARRAY_VALUE && mode != JSON_STATE_ARRAY_SEPARATOR)
|
jbe@121
|
120 goto json_import_syntax_error;
|
jbe@130
|
121 lua_pop(L, 1); // pop magic integer
|
jbe@121
|
122 json_import_close:
|
jbe@121
|
123 pos++;
|
jbe@130
|
124 lua_pop(L, 1); // pop shadow table
|
jbe@121
|
125 if (--level) {
|
jbe@121
|
126 if (lua_type(L, -2) == LUA_TNUMBER) {
|
jbe@124
|
127 mode = JSON_STATE_ARRAY_VALUE;
|
jbe@121
|
128 } else {
|
jbe@124
|
129 mode = JSON_STATE_OBJECT_VALUE;
|
jbe@121
|
130 }
|
jbe@121
|
131 goto json_import_process_value;
|
jbe@121
|
132 } else {
|
jbe@124
|
133 mode = JSON_STATE_END;
|
jbe@121
|
134 }
|
jbe@121
|
135 goto json_import_loop;
|
jbe@121
|
136 case ':':
|
jbe@124
|
137 if (mode != JSON_STATE_OBJECT_KEY_TERMINATOR)
|
jbe@121
|
138 goto json_import_syntax_error;
|
jbe@121
|
139 pos++;
|
jbe@124
|
140 mode = JSON_STATE_OBJECT_VALUE;
|
jbe@121
|
141 goto json_import_loop;
|
jbe@121
|
142 case ',':
|
jbe@124
|
143 if (mode == JSON_STATE_OBJECT_SEPARATOR) {
|
jbe@124
|
144 mode = JSON_STATE_OBJECT_KEY;
|
jbe@124
|
145 } else if (mode == JSON_STATE_ARRAY_SEPARATOR) {
|
jbe@124
|
146 mode = JSON_STATE_ARRAY_VALUE;
|
jbe@121
|
147 } else {
|
jbe@121
|
148 goto json_import_syntax_error;
|
jbe@121
|
149 }
|
jbe@121
|
150 pos++;
|
jbe@121
|
151 goto json_import_loop;
|
jbe@121
|
152 case '"':
|
jbe@121
|
153 cbuf = luaL_buffinitsize(L, &luabuf, total-pos);
|
jbe@121
|
154 writepos = 0;
|
jbe@121
|
155 pos++;
|
jbe@121
|
156 while ((c = str[pos++]) != '"') {
|
jbe@121
|
157 if (c == 0) {
|
jbe@121
|
158 goto json_import_unexpected_eof;
|
jbe@121
|
159 } else if (c < 32 || c == 127) {
|
jbe@121
|
160 lua_pushnil(L);
|
jbe@121
|
161 lua_pushliteral(L, "Unexpected control character in JSON string");
|
jbe@121
|
162 return 2;
|
jbe@121
|
163 } else if (c == '\\') {
|
jbe@121
|
164 c = str[pos++];
|
jbe@121
|
165 switch (c) {
|
jbe@121
|
166 case 0:
|
jbe@121
|
167 goto json_import_unexpected_eof;
|
jbe@121
|
168 case '"':
|
jbe@121
|
169 case '/':
|
jbe@121
|
170 case '\\':
|
jbe@121
|
171 cbuf[writepos++] = c;
|
jbe@121
|
172 break;
|
jbe@121
|
173 case 'b':
|
jbe@121
|
174 cbuf[writepos++] = '\b';
|
jbe@121
|
175 break;
|
jbe@121
|
176 case 'f':
|
jbe@121
|
177 cbuf[writepos++] = '\f';
|
jbe@121
|
178 break;
|
jbe@121
|
179 case 'n':
|
jbe@121
|
180 cbuf[writepos++] = '\n';
|
jbe@121
|
181 break;
|
jbe@121
|
182 case 'r':
|
jbe@121
|
183 cbuf[writepos++] = '\r';
|
jbe@121
|
184 break;
|
jbe@121
|
185 case 't':
|
jbe@121
|
186 cbuf[writepos++] = '\t';
|
jbe@121
|
187 break;
|
jbe@121
|
188 case 'u':
|
jbe@121
|
189 lua_pushnil(L);
|
jbe@121
|
190 lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO
|
jbe@121
|
191 return 2;
|
jbe@121
|
192 default:
|
jbe@121
|
193 lua_pushnil(L);
|
jbe@121
|
194 lua_pushliteral(L, "Unexpected string escape sequence in JSON document");
|
jbe@121
|
195 return 2;
|
jbe@121
|
196 }
|
jbe@121
|
197 } else {
|
jbe@121
|
198 cbuf[writepos++] = c;
|
jbe@121
|
199 }
|
jbe@121
|
200 }
|
jbe@121
|
201 if (!c) goto json_import_unexpected_eof;
|
jbe@121
|
202 luaL_pushresultsize(&luabuf, writepos);
|
jbe@121
|
203 goto json_import_process_value;
|
jbe@121
|
204 }
|
jbe@122
|
205 if (c == '-' || (c >= '0' && c <= '9')) {
|
jbe@122
|
206 char *endptr;
|
jbe@122
|
207 double numval;
|
jbe@122
|
208 numval = strtod(str+pos, &endptr);
|
jbe@122
|
209 if (endptr == str+pos) goto json_import_syntax_error;
|
jbe@122
|
210 pos += endptr - (str+pos);
|
jbe@122
|
211 lua_pushnumber(L, numval);
|
jbe@122
|
212 } else if (!strncmp(str+pos, "true", 4)) {
|
jbe@121
|
213 lua_pushboolean(L, 1);
|
jbe@121
|
214 pos += 4;
|
jbe@121
|
215 } else if (!strncmp(str+pos, "false", 5)) {
|
jbe@121
|
216 lua_pushboolean(L, 0);
|
jbe@121
|
217 pos += 5;
|
jbe@121
|
218 } else if (!strncmp(str+pos, "null", 4)) {
|
jbe@130
|
219 lua_pushvalue(L, JSON_UPVAL_NULLMARK);
|
jbe@121
|
220 pos += 4;
|
jbe@121
|
221 } else {
|
jbe@121
|
222 goto json_import_syntax_error;
|
jbe@121
|
223 }
|
jbe@121
|
224 json_import_process_value:
|
jbe@121
|
225 switch (mode) {
|
jbe@124
|
226 case JSON_STATE_OBJECT_KEY:
|
jbe@121
|
227 if (lua_type(L, -1) != LUA_TSTRING) goto json_import_syntax_error;
|
jbe@124
|
228 mode = JSON_STATE_OBJECT_KEY_TERMINATOR;
|
jbe@121
|
229 goto json_import_loop;
|
jbe@124
|
230 case JSON_STATE_OBJECT_VALUE:
|
jbe@130
|
231 lua_rawset(L, -3);
|
jbe@124
|
232 mode = JSON_STATE_OBJECT_SEPARATOR;
|
jbe@121
|
233 goto json_import_loop;
|
jbe@124
|
234 case JSON_STATE_ARRAY_VALUE:
|
jbe@130
|
235 lua_rawseti(L, -3, lua_rawlen(L, -3) + 1);
|
jbe@124
|
236 mode = JSON_STATE_ARRAY_SEPARATOR;
|
jbe@121
|
237 goto json_import_loop;
|
jbe@124
|
238 case JSON_STATE_VALUE:
|
jbe@124
|
239 mode = JSON_STATE_END;
|
jbe@121
|
240 goto json_import_loop;
|
jbe@121
|
241 }
|
jbe@121
|
242 json_import_syntax_error:
|
jbe@121
|
243 lua_pushnil(L);
|
jbe@121
|
244 lua_pushliteral(L, "Syntax error in JSON document");
|
jbe@121
|
245 return 2;
|
jbe@121
|
246 }
|
jbe@121
|
247
|
jbe@130
|
248 #define JSON_PATH_GET 1
|
jbe@130
|
249 #define JSON_PATH_TYPE 2
|
jbe@130
|
250 #define JSON_PATH_ISNULL 3
|
jbe@130
|
251
|
jbe@130
|
252 static int json_path(lua_State *L, int mode) {
|
jbe@130
|
253 int argc;
|
jbe@130
|
254 int idx = 2;
|
jbe@130
|
255 argc = lua_gettop(L);
|
jbe@126
|
256 lua_pushvalue(L, 1);
|
jbe@130
|
257 while (idx <= argc) {
|
jbe@132
|
258 if (lua_isnil(L, -1)) {
|
jbe@132
|
259 if (mode == JSON_PATH_ISNULL) lua_pushboolean(L, 0);
|
jbe@132
|
260 return 1;
|
jbe@132
|
261 }
|
jbe@130
|
262 lua_pushvalue(L, -1);
|
jbe@130
|
263 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@126
|
264 if (lua_isnil(L, -1)) {
|
jbe@126
|
265 lua_pop(L, 1);
|
jbe@130
|
266 if (lua_type(L, -1) == LUA_TTABLE) {
|
jbe@130
|
267 lua_pushvalue(L, idx++);
|
jbe@130
|
268 lua_gettable(L, -2);
|
jbe@130
|
269 } else {
|
jbe@130
|
270 lua_pushnil(L);
|
jbe@130
|
271 }
|
jbe@130
|
272 } else {
|
jbe@130
|
273 lua_replace(L, -2);
|
jbe@130
|
274 lua_pushvalue(L, idx++);
|
jbe@130
|
275 lua_rawget(L, -2);
|
jbe@126
|
276 }
|
jbe@130
|
277 lua_replace(L, -2);
|
jbe@126
|
278 }
|
jbe@130
|
279 switch (mode) {
|
jbe@130
|
280 case JSON_PATH_GET:
|
jbe@130
|
281 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
|
jbe@130
|
282 return 1;
|
jbe@130
|
283 case JSON_PATH_TYPE:
|
jbe@130
|
284 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) {
|
jbe@130
|
285 lua_pushliteral(L, "null");
|
jbe@130
|
286 return 1;
|
jbe@126
|
287 }
|
jbe@130
|
288 lua_pushvalue(L, -1);
|
jbe@130
|
289 lua_rawget(L, JSON_UPVAL_TYPES);
|
jbe@130
|
290 if (lua_isnil(L, -1)) lua_pushstring(L, lua_typename(L, lua_type(L, -2)));
|
jbe@130
|
291 return 1;
|
jbe@130
|
292 case JSON_PATH_ISNULL:
|
jbe@130
|
293 lua_pushboolean(L, lua_rawequal(L, -1, JSON_UPVAL_NULLMARK));
|
jbe@130
|
294 return 1;
|
jbe@126
|
295 }
|
jbe@130
|
296 return 0;
|
jbe@130
|
297 }
|
jbe@130
|
298
|
jbe@130
|
299 static int json_get(lua_State *L) {
|
jbe@130
|
300 return json_path(L, JSON_PATH_GET);
|
jbe@130
|
301 }
|
jbe@130
|
302
|
jbe@130
|
303 static int json_type(lua_State *L) {
|
jbe@130
|
304 return json_path(L, JSON_PATH_TYPE);
|
jbe@130
|
305 }
|
jbe@130
|
306
|
jbe@130
|
307 static int json_isnull(lua_State *L) {
|
jbe@130
|
308 return json_path(L, JSON_PATH_ISNULL);
|
jbe@130
|
309 }
|
jbe@130
|
310
|
jbe@131
|
311 static int json_setnull(lua_State *L) {
|
jbe@131
|
312 lua_settop(L, 2);
|
jbe@131
|
313 lua_pushvalue(L, JSON_UPVAL_METATABLE);
|
jbe@131
|
314 lua_setmetatable(L, 1);
|
jbe@131
|
315 lua_pushvalue(L, 1);
|
jbe@131
|
316 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@131
|
317 if (lua_isnil(L, -1)) {
|
jbe@131
|
318 lua_newtable(L);
|
jbe@131
|
319 lua_pushvalue(L, 1);
|
jbe@131
|
320 lua_pushvalue(L, -2);
|
jbe@131
|
321 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
|
jbe@131
|
322 }
|
jbe@131
|
323 lua_pushvalue(L, 2);
|
jbe@131
|
324 lua_pushvalue(L, JSON_UPVAL_NULLMARK);
|
jbe@131
|
325 lua_rawset(L, -3);
|
jbe@131
|
326 return 0;
|
jbe@131
|
327 }
|
jbe@131
|
328
|
jbe@130
|
329 static int json_len(lua_State *L) {
|
jbe@130
|
330 lua_settop(L, 1);
|
jbe@130
|
331 lua_pushvalue(L, 1);
|
jbe@130
|
332 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@130
|
333 if (lua_isnil(L, -1)) lua_pop(L, 1);
|
jbe@130
|
334 lua_pushinteger(L, lua_rawlen(L, -1));
|
jbe@123
|
335 return 1;
|
jbe@123
|
336 }
|
jbe@123
|
337
|
jbe@130
|
338 static int json_index(lua_State *L) {
|
jbe@130
|
339 lua_settop(L, 2);
|
jbe@130
|
340 lua_pushvalue(L, 1);
|
jbe@130
|
341 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@130
|
342 if (lua_isnil(L, -1)) return 1;
|
jbe@130
|
343 lua_pushvalue(L, 2);
|
jbe@130
|
344 lua_rawget(L, -2);
|
jbe@130
|
345 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
|
jbe@127
|
346 return 1;
|
jbe@127
|
347 }
|
jbe@127
|
348
|
jbe@130
|
349 static int json_newindex(lua_State *L) {
|
jbe@130
|
350 lua_settop(L, 3);
|
jbe@123
|
351 lua_pushvalue(L, 1);
|
jbe@130
|
352 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@130
|
353 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
|
jbe@130
|
354 lua_replace(L, 1);
|
jbe@130
|
355 lua_rawset(L, 1);
|
jbe@121
|
356 return 1;
|
jbe@121
|
357 }
|
jbe@121
|
358
|
jbe@135
|
359 static int json_pairs_iterfunc(lua_State *L) {
|
jbe@135
|
360 lua_settop(L, 2);
|
jbe@135
|
361 lua_pushvalue(L, 1);
|
jbe@135
|
362 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@135
|
363 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
|
jbe@135
|
364 lua_pushvalue(L, 2);
|
jbe@135
|
365 if (!lua_next(L, -2)) return 0;
|
jbe@135
|
366 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) {
|
jbe@135
|
367 lua_pop(L, 1);
|
jbe@135
|
368 lua_pushnil(L);
|
jbe@135
|
369 }
|
jbe@135
|
370 return 2;
|
jbe@135
|
371 }
|
jbe@135
|
372
|
jbe@135
|
373 static int json_pairs(lua_State *L) {
|
jbe@135
|
374 lua_pushvalue(L, JSON_UPVAL_PAIRS_ITERFUNC);
|
jbe@135
|
375 lua_pushvalue(L, 1);
|
jbe@135
|
376 lua_pushnil(L);
|
jbe@135
|
377 return 3;
|
jbe@135
|
378 }
|
jbe@135
|
379
|
jbe@134
|
380 static int json_ipairs_iterfunc(lua_State *L) {
|
jbe@134
|
381 int idx;
|
jbe@134
|
382 lua_settop(L, 2);
|
jbe@134
|
383 idx = lua_tointeger(L, 2) + 1;
|
jbe@134
|
384 lua_pushvalue(L, 1);
|
jbe@134
|
385 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
|
jbe@134
|
386 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
|
jbe@134
|
387 lua_rawgeti(L, -1, idx);
|
jbe@134
|
388 if (lua_isnil(L, -1)) return 0;
|
jbe@134
|
389 lua_pushinteger(L, idx);
|
jbe@134
|
390 if (lua_rawequal(L, -2, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
|
jbe@134
|
391 else lua_pushvalue(L, -2);
|
jbe@134
|
392 return 2;
|
jbe@134
|
393 }
|
jbe@134
|
394
|
jbe@134
|
395 static int json_ipairs(lua_State *L) {
|
jbe@134
|
396 lua_pushvalue(L, JSON_UPVAL_IPAIRS_ITERFUNC);
|
jbe@134
|
397 lua_pushvalue(L, 1);
|
jbe@134
|
398 lua_pushinteger(L, 0);
|
jbe@134
|
399 return 3;
|
jbe@134
|
400 }
|
jbe@134
|
401
|
jbe@121
|
402 static const struct luaL_Reg json_module_functions[] = {
|
jbe@133
|
403 {"object", json_object},
|
jbe@133
|
404 {"array", json_array},
|
jbe@121
|
405 {"import", json_import},
|
jbe@130
|
406 {"get", json_get},
|
jbe@127
|
407 {"type", json_type},
|
jbe@123
|
408 {"isnull", json_isnull},
|
jbe@131
|
409 {"setnull", json_setnull},
|
jbe@121
|
410 {NULL, NULL}
|
jbe@121
|
411 };
|
jbe@121
|
412
|
jbe@126
|
413 static const struct luaL_Reg json_metatable_functions[] = {
|
jbe@130
|
414 {"__len", json_len},
|
jbe@130
|
415 {"__index", json_index},
|
jbe@130
|
416 {"__newindex", json_newindex},
|
jbe@135
|
417 {"__pairs", json_pairs},
|
jbe@134
|
418 {"__ipairs", json_ipairs},
|
jbe@126
|
419 {NULL, NULL}
|
jbe@126
|
420 };
|
jbe@126
|
421
|
jbe@121
|
422 int luaopen_json(lua_State *L) {
|
jbe@126
|
423 lua_settop(L, 0);
|
jbe@126
|
424 lua_newtable(L); // 1: library table on stack position
|
jbe@130
|
425 lua_newtable(L); // 2: table used as JSON NULL value in internal shadow tables
|
jbe@130
|
426 lua_newtable(L); // 3: ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil
|
jbe@130
|
427 lua_newtable(L); // 4: ephemeron table to store the type of the JSON object/array
|
jbe@130
|
428 lua_newtable(L); // 5: metatable for ephemeron tables
|
jbe@121
|
429 lua_pushliteral(L, "__mode");
|
jbe@121
|
430 lua_pushliteral(L, "k");
|
jbe@130
|
431 lua_rawset(L, 5);
|
jbe@130
|
432 lua_pushvalue(L, 5); // 6: cloned metatable reference
|
jbe@127
|
433 lua_setmetatable(L, 3);
|
jbe@130
|
434 lua_setmetatable(L, 4);
|
jbe@130
|
435 lua_newtable(L); // 5: metatable for JSON objects and JSON arrays
|
jbe@126
|
436 lua_pushvalue(L, 2);
|
jbe@126
|
437 lua_pushvalue(L, 3);
|
jbe@127
|
438 lua_pushvalue(L, 4);
|
jbe@130
|
439 lua_pushvalue(L, 5);
|
jbe@135
|
440 lua_pushcclosure(L, json_pairs_iterfunc, 4); // 6: iteration function for pairs
|
jbe@135
|
441 lua_pushvalue(L, 2);
|
jbe@135
|
442 lua_pushvalue(L, 3);
|
jbe@135
|
443 lua_pushvalue(L, 4);
|
jbe@135
|
444 lua_pushvalue(L, 5);
|
jbe@135
|
445 lua_pushcclosure(L, json_ipairs_iterfunc, 4); // 7: iteration function for ipairs
|
jbe@134
|
446 lua_pushvalue(L, 5);
|
jbe@134
|
447 lua_pushvalue(L, 2);
|
jbe@134
|
448 lua_pushvalue(L, 3);
|
jbe@134
|
449 lua_pushvalue(L, 4);
|
jbe@134
|
450 lua_pushvalue(L, 5);
|
jbe@134
|
451 lua_pushvalue(L, 6);
|
jbe@135
|
452 lua_pushvalue(L, 7);
|
jbe@135
|
453 luaL_setfuncs(L, json_metatable_functions, 6);
|
jbe@135
|
454 lua_setfield(L, 1, "metatable");
|
jbe@135
|
455 luaL_setfuncs(L, json_module_functions, 6);
|
jbe@121
|
456 return 1;
|
jbe@121
|
457 }
|