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