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