webmcp

view libraries/json/json.c @ 141:ca27aae3f1a1

Finished removing all upvalues from JSON library
author jbe
date Wed Jul 30 01:47:01 2014 +0200 (2014-07-30)
parents 641619d3fcb1
children a686ed2ce967
line source
1 #include <lua.h>
2 #include <lauxlib.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #define JSON_REGENT static char
7 #define JSON_REGREF void *
9 JSON_REGENT json_nullmark;
10 JSON_REGENT json_shadowtbl;
11 JSON_REGENT json_unknownmt;
12 JSON_REGENT json_objectmt;
13 JSON_REGENT json_arraymt;
15 #define json_regfetch(L, x) (lua_pushlightuserdata((L), &(x)), lua_rawget((L), LUA_REGISTRYINDEX))
17 #define json_regstore(L, x) (lua_pushlightuserdata(L, &(x)), lua_pushvalue(L, -2), lua_rawset(L, LUA_REGISTRYINDEX));
19 // marks a table as JSON object or JSON array:
20 // (returns its modified argument or a new table if argument is nil)
21 static int json_mark(lua_State *L, JSON_REGREF mt) {
22 // if argument is nil, then create new table:
23 if (lua_isnoneornil(L, 1)) {
24 lua_settop(L, 0);
25 lua_newtable(L);
26 // skip testing of existing shadow table:
27 goto json_object_create_shadow_table;
28 }
29 // check if shadow table already exists:
30 json_regfetch(L, json_shadowtbl);
31 lua_pushvalue(L, 1);
32 lua_rawget(L, -2);
33 if (lua_isnil(L, -1)) {
34 json_object_create_shadow_table:
35 // set shadow table:
36 lua_pushvalue(L, 1);
37 lua_newtable(L);
38 lua_rawset(L, -4);
39 }
40 // discard everything but table to return:
41 lua_settop(L, 1);
42 // set metatable:
43 json_regfetch(L, mt);
44 lua_setmetatable(L, 1);
45 // return table:
46 return 1;
47 }
49 // marks a table as JSON object:
50 // (returns its modified argument or a new table if argument is nil)
51 static int json_object(lua_State *L) {
52 return json_mark(L, &json_objectmt);
53 }
55 // marks a table as JSON array:
56 // (returns its modified argument or a new table if argument is nil)
57 static int json_array(lua_State *L) {
58 return json_mark(L, &json_arraymt);
59 }
61 #define JSON_STATE_VALUE 0
62 #define JSON_STATE_OBJECT_KEY 1
63 #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
64 #define JSON_STATE_OBJECT_VALUE 3
65 #define JSON_STATE_OBJECT_SEPARATOR 4
66 #define JSON_STATE_ARRAY_VALUE 5
67 #define JSON_STATE_ARRAY_SEPARATOR 6
68 #define JSON_STATE_END 7
70 #define json_import_objectmt_idx 2
71 #define json_import_arraymt_idx 3
72 #define json_import_shadowtbl_idx 4
73 #define json_import_nullmark_idx 5
75 // decodes a JSON document:
76 static int json_import(lua_State *L) {
77 const char *str; // string to parse
78 size_t total; // total length of string to parse
79 size_t pos = 0; // current position in string to parse
80 size_t level = 0; // nested levels of objects/arrays currently being processed
81 int mode = JSON_STATE_VALUE; // state of parser
82 char c; // variable to store a single character to be processed
83 luaL_Buffer luabuf; // Lua buffer to decode (possibly escaped) strings
84 char *cbuf; // C buffer to decode (possibly escaped) strings
85 size_t writepos; // write position of decoded strings in C buffer
86 // limit stack to 1 element:
87 lua_settop(L, 1);
88 // push json_objectmt on stack position 2:
89 json_regfetch(L, json_objectmt);
90 // push json_arraymt on stack position 3:
91 json_regfetch(L, json_arraymt);
92 // push json_shadowtbl on stack position 4:
93 json_regfetch(L, json_shadowtbl);
94 // push json_nullmark on stack position 5:
95 json_regfetch(L, json_nullmark);
96 // require string as first argument:
97 str = luaL_checklstring(L, 1, &total);
98 // if string contains a NULL byte, this is a syntax error
99 if (strlen(str) != total) goto json_import_syntax_error;
100 // main loop of parser:
101 json_import_loop:
102 // skip whitespace and store next character in variable 'c':
103 while (c = str[pos], c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f') pos++;
104 // switch statement to handle certain (single) characters:
105 switch (c) {
106 // handle end of JSON document:
107 case 0:
108 // if end of JSON document was expected, then return top element of stack as result:
109 if (mode == JSON_STATE_END) return 1;
110 // otherwise, the JSON document was malformed:
111 json_import_unexpected_eof:
112 lua_pushnil(L);
113 if (level == 0) lua_pushliteral(L, "Empty string");
114 else lua_pushliteral(L, "Unexpected end of JSON document");
115 return 2;
116 // new JSON object:
117 case '{':
118 // if a JSON object is not expected here, then return an error:
119 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
120 goto json_import_syntax_error;
121 // consume input character:
122 pos++;
123 // create JSON object on stack:
124 lua_newtable(L);
125 // set metatable of JSON object:
126 lua_pushvalue(L, json_import_objectmt_idx);
127 lua_setmetatable(L, -2);
128 // create internal shadow table on stack:
129 lua_newtable(L);
130 // register internal shadow table (and cleanup stack afterwards):
131 lua_pushvalue(L, -2);
132 lua_pushvalue(L, -2);
133 lua_rawset(L, json_import_shadowtbl_idx);
134 // increment level:
135 level++;
136 // expect object key (or end of object) and continue with loop:
137 mode = JSON_STATE_OBJECT_KEY;
138 goto json_import_loop;
139 // new JSON array:
140 case '[':
141 // if a JSON array is not expected here, then return an error:
142 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
143 goto json_import_syntax_error;
144 // consume input character:
145 pos++;
146 // create JSON array on stack:
147 lua_newtable(L);
148 // set metatable of JSON array:
149 lua_pushvalue(L, json_import_arraymt_idx);
150 lua_setmetatable(L, -2);
151 // create internal shadow table on stack:
152 lua_newtable(L);
153 // register internal shadow table (and cleanup stack afterwards):
154 lua_pushvalue(L, -2);
155 lua_pushvalue(L, -2);
156 lua_rawset(L, json_import_shadowtbl_idx);
157 // add nil as key (needed to keep stack balance) and as magic to detect arrays:
158 lua_pushnil(L);
159 // increment level:
160 level++;
161 // expect array value (or end of array) and continue with loop:
162 mode = JSON_STATE_ARRAY_VALUE;
163 goto json_import_loop;
164 // end of JSON object:
165 case '}':
166 // if end of JSON object is not expected here, then return an error:
167 if (mode != JSON_STATE_OBJECT_KEY && mode != JSON_STATE_OBJECT_SEPARATOR)
168 goto json_import_syntax_error;
169 // jump to common code for end of JSON object and JSON array:
170 goto json_import_close;
171 // end of JSON array:
172 case ']':
173 // if end of JSON array is not expected here, then return an error:
174 if (mode != JSON_STATE_ARRAY_VALUE && mode != JSON_STATE_ARRAY_SEPARATOR)
175 goto json_import_syntax_error;
176 // pop nil key/magic:
177 lua_pop(L, 1);
178 // continue with common code for end of JSON object and JSON array:
179 // common code for end of JSON object or JSON array:
180 json_import_close:
181 // consume input character:
182 pos++;
183 // pop shadow table:
184 lua_pop(L, 1);
185 // check if nested:
186 if (--level) {
187 // if nested, then check if outer(!) structure is an array or object:
188 if (lua_isnil(L, -2)) {
189 // select array value processing:
190 mode = JSON_STATE_ARRAY_VALUE;
191 } else {
192 // select object value processing:
193 mode = JSON_STATE_OBJECT_VALUE;
194 }
195 // store value in outer structure:
196 goto json_import_process_value;
197 }
198 // if not nested, then expect end of JSON document and continue with loop:
199 mode = JSON_STATE_END;
200 goto json_import_loop;
201 // key terminator:
202 case ':':
203 // if key terminator is not expected here, then return an error:
204 if (mode != JSON_STATE_OBJECT_KEY_TERMINATOR)
205 goto json_import_syntax_error;
206 // consume input character:
207 pos++;
208 // set state of parser and continue with loop:
209 mode = JSON_STATE_OBJECT_VALUE;
210 goto json_import_loop;
211 // value terminator (NOTE: trailing comma at end of value or key-value list is tolerated by this parser)
212 case ',':
213 // change parser state accordingly:
214 if (mode == JSON_STATE_OBJECT_SEPARATOR) {
215 mode = JSON_STATE_OBJECT_KEY;
216 } else if (mode == JSON_STATE_ARRAY_SEPARATOR) {
217 mode = JSON_STATE_ARRAY_VALUE;
218 } else {
219 // if value terminator is not expected here, then return an error:
220 goto json_import_syntax_error;
221 }
222 // consume input character:
223 pos++;
224 // continue with loop:
225 goto json_import_loop;
226 // string literal:
227 case '"':
228 // prepare buffer to decode string (with maximum possible length) and set write position to zero:
229 cbuf = luaL_buffinitsize(L, &luabuf, total-pos);
230 writepos = 0;
231 // consume quote character:
232 pos++;
233 // read next character until encountering end quote:
234 while ((c = str[pos++]) != '"') {
235 if (c == 0) {
236 // handle unexpected end-of-string:
237 goto json_import_unexpected_eof;
238 } else if (c < 32 || c == 127) {
239 // do not allow ASCII control characters:
240 // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized
241 // by this parser to allow different encodings than Unicode
242 lua_pushnil(L);
243 lua_pushliteral(L, "Unexpected control character in JSON string");
244 return 2;
245 } else if (c == '\\') {
246 // read next char after backslash escape:
247 c = str[pos++];
248 switch (c) {
249 // unexpected end-of-string:
250 case 0:
251 goto json_import_unexpected_eof;
252 // unescaping of quotation mark, slash, and backslash:
253 case '"':
254 case '/':
255 case '\\':
256 cbuf[writepos++] = c;
257 break;
258 // unescaping of backspace:
259 case 'b':
260 cbuf[writepos++] = '\b';
261 break;
262 // unescaping of form-feed:
263 case 'f':
264 cbuf[writepos++] = '\f';
265 break;
266 // unescaping of new-line:
267 case 'n':
268 cbuf[writepos++] = '\n';
269 break;
270 // unescaping of carriage-return:
271 case 'r':
272 cbuf[writepos++] = '\r';
273 break;
274 // unescaping of tabulator:
275 case 't':
276 cbuf[writepos++] = '\t';
277 break;
278 // unescaping of UTF-16 characters
279 case 'u':
280 lua_pushnil(L);
281 lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO
282 return 2;
283 // unexpected escape sequence:
284 default:
285 lua_pushnil(L);
286 lua_pushliteral(L, "Unexpected string escape sequence in JSON document");
287 return 2;
288 }
289 } else {
290 // normal character:
291 cbuf[writepos++] = c;
292 }
293 }
294 // process buffer to Lua string:
295 luaL_pushresultsize(&luabuf, writepos);
296 // continue with processing of decoded string:
297 goto json_import_process_value;
298 }
299 // process values whose type is is not deducible from a single character:
300 if ((c >= '0' && c <= '9') || c == '-' || c == '+') {
301 // numbers:
302 char *endptr;
303 double numval;
304 numval = strtod(str+pos, &endptr);
305 if (endptr == str+pos) goto json_import_syntax_error;
306 pos += endptr - (str+pos);
307 lua_pushnumber(L, numval);
308 } else if (!strncmp(str+pos, "true", 4)) {
309 // consume 4 input characters for "true":
310 pos += 4;
311 // put Lua true value on stack:
312 lua_pushboolean(L, 1);
313 } else if (!strncmp(str+pos, "false", 5)) {
314 // consume 5 input characters for "false":
315 pos += 5;
316 // put Lua false value on stack:
317 lua_pushboolean(L, 0);
318 } else if (!strncmp(str+pos, "null", 4)) {
319 // consume 4 input characters for "null":
320 pos += 4;
321 // put special null-marker on stack:
322 lua_pushvalue(L, json_import_nullmark_idx);
323 } else {
324 // all other cases are a syntax error:
325 goto json_import_syntax_error;
326 }
327 // process a decoded value or key value pair (expected on top of Lua stack):
328 json_import_process_value:
329 switch (mode) {
330 // an object key has been read:
331 case JSON_STATE_OBJECT_KEY:
332 // if an object key is not a string, then this is a syntax error:
333 if (lua_type(L, -1) != LUA_TSTRING) goto json_import_syntax_error;
334 // expect key terminator and continue with loop:
335 mode = JSON_STATE_OBJECT_KEY_TERMINATOR;
336 goto json_import_loop;
337 // a key value pair has been read:
338 case JSON_STATE_OBJECT_VALUE:
339 // store key value pair in outer shadow table:
340 lua_rawset(L, -3);
341 // expect value terminator (or end of object) and continue with loop:
342 mode = JSON_STATE_OBJECT_SEPARATOR;
343 goto json_import_loop;
344 // an array value has been read:
345 case JSON_STATE_ARRAY_VALUE:
346 // store value in outer shadow table:
347 lua_rawseti(L, -3, lua_rawlen(L, -3) + 1);
348 // expect value terminator (or end of object) and continue with loop:
349 mode = JSON_STATE_ARRAY_SEPARATOR;
350 goto json_import_loop;
351 // a single value has been read:
352 case JSON_STATE_VALUE:
353 // leave value on top of stack, expect end of JSON document, and continue with loop:
354 mode = JSON_STATE_END;
355 goto json_import_loop;
356 }
357 // syntax error handling (only reachable by goto statement):
358 json_import_syntax_error:
359 lua_pushnil(L);
360 lua_pushliteral(L, "Syntax error in JSON document");
361 return 2;
362 }
364 #define json_path_shadowtbl_idx 1
365 #define json_path_nullmark_idx 2
366 #define json_path_idxshift 2
368 // gets a value or its type from a JSON document (first argument)
369 // optionally using a path (variable number of keys after first argument):
370 static int json_path(lua_State *L, int type_mode) {
371 int stacktop;
372 int idx = 2 + json_path_idxshift;
373 // insert json_shadowtbl on stack at position 1:
374 json_regfetch(L, json_shadowtbl);
375 lua_insert(L, 1);
376 // insert json_nullmark on stack at position 2:
377 json_regfetch(L, json_nullmark);
378 lua_insert(L, 2);
379 // store number of arguments:
380 stacktop = lua_gettop(L);
381 // follow path, starting with first argument as "current value":
382 lua_pushvalue(L, 1 + json_path_idxshift);
383 // process each "path key":
384 while (idx <= stacktop) {
385 // if "current value" is nil, then the path cannot be walked and nil is returned:
386 if (lua_isnil(L, -1)) return 1;
387 // try to get shadow table of "current value":
388 lua_pushvalue(L, -1);
389 lua_rawget(L, json_path_shadowtbl_idx);
390 if (lua_isnil(L, -1)) {
391 // if no shadow table is found,
392 // drop nil from stack:
393 lua_pop(L, 1);
394 if (lua_type(L, -1) == LUA_TTABLE) {
395 // if "current value" is a table,
396 // get "next value" using the "path key":
397 lua_pushvalue(L, idx++);
398 lua_gettable(L, -2);
399 } else {
400 // if "current value" is not a table,
401 // then the path cannot be walked and nil is returned:
402 lua_pushnil(L);
403 return 1;
404 }
405 } else {
406 // if a shadow table is found,
407 // set "current value" to its shadow table:
408 lua_replace(L, -2);
409 // get "next value" using the "path key":
410 lua_pushvalue(L, idx++);
411 lua_rawget(L, -2);
412 }
413 // the "next value" replaces the "current value":
414 lua_replace(L, -2);
415 }
416 if (!type_mode) {
417 // if a value (and not its type) was requested,
418 // check if value is the null-marker, and store nil on top of Lua stack in that case:
419 if (lua_rawequal(L, -1, json_path_nullmark_idx)) lua_pushnil(L);
420 } else {
421 // if the type was requested,
422 // check if value is the null-marker:
423 if (lua_rawequal(L, -1, json_path_nullmark_idx)) {
424 // if yes, store string "null" on top of Lua stack:
425 lua_pushliteral(L, "null");
426 } else {
427 // otherwise,
428 // check if metatable indicates "object" or "array":
429 if (lua_getmetatable(L, -1)) {
430 json_regfetch(L, json_objectmt);
431 if (lua_rawequal(L, -2, -1)) {
432 // return string "object":
433 lua_pushliteral(L, "object");
434 return 1;
435 }
436 json_regfetch(L, json_arraymt);
437 if (lua_rawequal(L, -3, -1)) {
438 // return string "array":
439 lua_pushliteral(L, "array");
440 return 1;
441 }
442 lua_pop(L, 3);
443 }
444 // otherwise, get the Lua type:
445 lua_pushstring(L, lua_typename(L, lua_type(L, -1)));
446 }
447 }
448 // return the top most value on the Lua stack:
449 return 1;
450 }
452 // gets a value from a JSON document (first argument)
453 // optionally using a path (variable number of keys after first argument):
454 static int json_get(lua_State *L) {
455 return json_path(L, 0);
456 }
458 // gets a value's type from a JSON document (first argument)
459 // optionally using a path (variable number of keys after first argument):
460 static int json_type(lua_State *L) {
461 return json_path(L, 1);
462 }
464 // checks if a value in a JSON document (first argument) is null:
465 static int json_isnull(lua_State *L) {
466 const char *jsontype;
467 lua_pushcfunction(L, json_type);
468 lua_insert(L, 1);
469 lua_call(L, lua_gettop(L) - 1, 1);
470 jsontype = lua_tostring(L, -1);
471 if (jsontype && !strcmp(jsontype, "null")) lua_pushboolean(L, 1);
472 else lua_pushboolean(L, 0);
473 return 1;
474 }
476 #define json_setnull_unknownmt_idx 3
477 #define json_setnull_objectmt_idx 4
478 #define json_setnull_arraymt_idx 5
479 #define json_setnull_shadowtbl_idx 6
481 static int json_setnull(lua_State *L) {
482 // truncate stack to two elements:
483 lua_settop(L, 2);
484 // push json_unknownmt to stack position 3:
485 json_regfetch(L, json_unknownmt);
486 // push json_objectmt to stack position 4:
487 json_regfetch(L, json_objectmt);
488 // push json_arraymt to stack position 5:
489 json_regfetch(L, json_arraymt);
490 // push json_shadowtbl to stack position 6:
491 json_regfetch(L, json_shadowtbl);
492 //
493 lua_getmetatable(L, 1);
494 if (
495 !lua_rawequal(L, -1, json_setnull_unknownmt_idx) &&
496 !lua_rawequal(L, -1, json_setnull_objectmt_idx) &&
497 !lua_rawequal(L, -1, json_setnull_arraymt_idx)
498 ) {
499 lua_pushvalue(L, json_setnull_unknownmt_idx);
500 lua_setmetatable(L, 1);
501 }
502 lua_pushvalue(L, 1);
503 lua_rawget(L, json_setnull_shadowtbl_idx);
504 if (lua_isnil(L, -1)) {
505 lua_newtable(L);
506 lua_pushvalue(L, 1);
507 lua_pushvalue(L, -2);
508 lua_rawset(L, json_setnull_shadowtbl_idx);
509 }
510 lua_pushvalue(L, 2);
511 json_regfetch(L, json_nullmark);
512 lua_rawset(L, -3);
513 return 0;
514 }
516 static int json_len(lua_State *L) {
517 lua_settop(L, 1);
518 json_regfetch(L, json_shadowtbl);
519 lua_pushvalue(L, 1);
520 lua_rawget(L, -2);
521 lua_pushinteger(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1));
522 return 1;
523 }
525 #define json_index_nullmark_idx 3
526 #define json_index_shadowtbl_idx 4
528 static int json_index(lua_State *L) {
529 lua_settop(L, 2);
530 json_regfetch(L, json_nullmark); // on stack position 3
531 json_regfetch(L, json_shadowtbl);
532 lua_pushvalue(L, 1);
533 lua_rawget(L, json_index_shadowtbl_idx);
534 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
535 lua_pushvalue(L, 2);
536 lua_rawget(L, -2);
537 if (lua_rawequal(L, -1, json_index_nullmark_idx)) lua_pushnil(L);
538 return 1;
539 }
541 static int json_newindex(lua_State *L) {
542 lua_settop(L, 3);
543 json_regfetch(L, json_shadowtbl);
544 lua_pushvalue(L, 1);
545 lua_rawget(L, -1);
546 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
547 lua_replace(L, 1);
548 lua_settop(L, 3);
549 lua_rawset(L, 1);
550 return 1;
551 }
553 #define json_pairs_iterfunc_nullmark_idx 3
554 #define json_pairs_iterfunc_shadowtbl_idx 4
556 static int json_pairs_iterfunc(lua_State *L) {
557 lua_settop(L, 2);
558 json_regfetch(L, json_nullmark); // on stack position 3
559 json_regfetch(L, json_shadowtbl);
560 lua_pushvalue(L, 1);
561 lua_rawget(L, json_pairs_iterfunc_shadowtbl_idx);
562 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
563 lua_pushvalue(L, 2);
564 if (!lua_next(L, -2)) return 0;
565 if (lua_rawequal(L, -1, json_pairs_iterfunc_nullmark_idx)) {
566 lua_pop(L, 1);
567 lua_pushnil(L);
568 }
569 return 2;
570 }
572 static int json_pairs(lua_State *L) {
573 lua_pushcfunction(L, json_pairs_iterfunc);
574 lua_pushvalue(L, 1);
575 lua_pushnil(L);
576 return 3;
577 }
579 #define json_ipairs_iterfunc_nullmark_idx 3
580 #define json_ipairs_iterfunc_shadowtbl_idx 4
582 static int json_ipairs_iterfunc(lua_State *L) {
583 int idx;
584 lua_settop(L, 2);
585 json_regfetch(L, json_nullmark); // on stack position 3
586 json_regfetch(L, json_shadowtbl);
587 idx = lua_tointeger(L, 2) + 1;
588 lua_pushvalue(L, 1);
589 lua_rawget(L, json_ipairs_iterfunc_shadowtbl_idx);
590 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
591 lua_rawgeti(L, -1, idx);
592 if (lua_isnil(L, -1)) return 0;
593 lua_pushinteger(L, idx);
594 if (lua_rawequal(L, -2, json_ipairs_iterfunc_nullmark_idx)) lua_pushnil(L);
595 else lua_pushvalue(L, -2);
596 return 2;
597 }
599 static int json_ipairs(lua_State *L) {
600 lua_pushcfunction(L, json_ipairs_iterfunc);
601 lua_pushvalue(L, 1);
602 lua_pushinteger(L, 0);
603 return 3;
604 }
606 static const struct luaL_Reg json_module_functions[] = {
607 {"object", json_object},
608 {"array", json_array},
609 {"import", json_import},
610 {"get", json_get},
611 {"type", json_type},
612 {"isnull", json_isnull},
613 {"setnull", json_setnull},
614 {NULL, NULL}
615 };
617 static const struct luaL_Reg json_metatable_functions[] = {
618 {"__len", json_len},
619 {"__index", json_index},
620 {"__newindex", json_newindex},
621 {"__pairs", json_pairs},
622 {"__ipairs", json_ipairs},
623 {NULL, NULL}
624 };
626 int luaopen_json(lua_State *L) {
627 lua_settop(L, 0);
628 lua_newtable(L); // library
629 lua_newtable(L);
630 luaL_setfuncs(L, json_metatable_functions, 0);
631 json_regstore(L, json_unknownmt);
632 lua_setfield(L, 1, "ambiguous_mt");
633 lua_newtable(L);
634 luaL_setfuncs(L, json_metatable_functions, 0);
635 json_regstore(L, json_objectmt);
636 lua_setfield(L, 1, "object_mt");
637 lua_newtable(L);
638 luaL_setfuncs(L, json_metatable_functions, 0);
639 json_regstore(L, json_arraymt);
640 lua_setfield(L, 1, "array_mt");
641 lua_newtable(L); // ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil
642 lua_newtable(L); // metatable for ephemeron table
643 lua_pushliteral(L, "__mode");
644 lua_pushliteral(L, "k");
645 lua_rawset(L, -3);
646 lua_setmetatable(L, -2);
647 json_regstore(L, json_shadowtbl);
648 lua_newtable(L);
649 json_regstore(L, json_nullmark);
650 lua_settop(L, 1);
651 luaL_setfuncs(L, json_module_functions, 0);
652 return 1;
653 }

Impressum / About Us