webmcp
view libraries/json/json.c @ 172:a83164390355
Allow json.object and json.array functions to convert any Lua value using __pairs and __ipairs metamethods
| author | jbe | 
|---|---|
| date | Fri Aug 01 17:11:59 2014 +0200 (2014-08-01) | 
| parents | ce208edffcc9 | 
| children | f417c4b607ed | 
 line source
     1 #include <lua.h>
     2 #include <lauxlib.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <math.h>
     7 // maximum number of nested JSON values (objects and arrays):
     8 // NOTE: The Lua reference states that the stack may typically contain at least
     9 //       "a few thousand elements". Since every nested level consumes
    10 //       3 elements on the Lua stack (the object/array, its shadow table,
    11 //       a string key or a placeholder), we limit the number of nested levels
    12 //       to 500. If a stack overflow would still happen in the import function,
    13 //       this is detected nevertheless and an error is thrown (instead of
    14 //       returning nil and an error string).
    15 #define JSON_MAXDEPTH 500
    17 // generate dummy memory addresses that represents null values:
    18 char json_nullmark;
    19 #define json_isnullmark(L, i) (lua_touserdata((L), (i)) == &json_nullmark)
    20 #define json_pushnullmark(L) lua_pushlightuserdata((L), &json_nullmark)
    22 // macros for usage of Lua registry:
    23 #define JSON_REGENT char
    24 #define JSON_REGPOINTER void *
    25 #define json_regpointer(x) (&json_registry.x)
    26 #define json_regfetchpointer(L, x) lua_rawgetp((L), LUA_REGISTRYINDEX, (x))
    27 #define json_regfetch(L, x) json_regfetchpointer(L, json_regpointer(x))
    28 #define json_regstore(L, x) lua_rawsetp(L, LUA_REGISTRYINDEX, json_regpointer(x))
    30 // generate dummy memory addresses that represent Lua objects
    31 // via lightuserdata keys and LUA_REGISTRYINDEX:
    32 static struct {
    33   JSON_REGENT shadowtbl;  // ephemeron table that maps tables to their corresponding shadow table
    34   JSON_REGENT objectmt;   // metatable for JSON objects
    35   JSON_REGENT arraymt;    // metatable for JSON arrays
    36 } json_registry;
    38 // returns the string "<JSON null marker>":
    39 static int json_nullmark_tostring(lua_State *L) {
    40   lua_pushliteral(L, "<JSON null marker>");
    41   return 1;
    42 }
    44 #define json_convert_source_idx 1
    45 #define json_convert_iterator_idx 2
    46 #define json_convert_output_idx 3
    47 #define json_convert_shadow_idx 4
    48 #define json_convert_iterfun_idx 5
    49 #define json_convert_itertbl_idx 6
    51 // converts a Lua table to a  JSON object or JSON array:
    52 // (does never modify the argument, returns an empty object or array if argument is nil)
    53 static int json_convert(lua_State *L, int array) {
    54   int arrayidx = 0;
    55   // determine is argument is given:
    56   if (lua_isnoneornil(L, json_convert_source_idx)) {
    57     // if no argument is given (or if argument is nil),
    58     // create table with shadow table, and leave first table on top of stack:
    59     json_regfetch(L, shadowtbl);
    60     lua_newtable(L);
    61     lua_pushvalue(L, -1);
    62     lua_newtable(L);
    63     lua_rawset(L, -4);
    64   } else {
    65     // if an argument was given,
    66     // push its iterator function on stack position 2 if existent,
    67     // else push null for normal tables:
    68     lua_settop(L, 1);
    69     if (lua_getmetatable(L, json_convert_source_idx)) {
    70       lua_getfield(L, -1, array ? "__ipairs" : "__pairs");
    71       if (lua_isnil(L, -1)) luaL_checktype(L, 1, LUA_TTABLE);
    72       else if (lua_type(L, -1) != LUA_TFUNCTION)
    73         return luaL_error(L, "%s metamethod is not a function", array ? "__ipairs" : "__pairs");
    74       lua_replace(L, -2);
    75     } else {
    76       lua_pushnil(L);
    77     }
    78     // create result table on stack position 3:
    79     lua_newtable(L);
    80     // create shadow table on stack position 4:
    81     json_regfetch(L, shadowtbl);
    82     lua_newtable(L);
    83     lua_pushvalue(L, json_convert_output_idx);
    84     lua_pushvalue(L, -2);
    85     lua_rawset(L, -4);
    86     lua_replace(L, -2);
    87     // check if iterator function exists:
    88     if (lua_isnil(L, json_convert_iterator_idx)) {
    89       // if there is no iterator function,
    90       // distinguish between objects and arrays:
    91       if (array == 0) {
    92         // for an object, copy all string key value pairs to shadow table:
    93         for (lua_pushnil(L); lua_next(L, json_convert_source_idx); lua_pop(L, 1)) {
    94           if (lua_type(L, -2) == LUA_TSTRING) {
    95             lua_pushvalue(L, -2);
    96             lua_pushvalue(L, -2);
    97             lua_rawset(L, json_convert_shadow_idx);
    98           }
    99         }
   100       } else {
   101         // for an array, copy consecutive integer value pairs to shadow table:
   102         while (1) {
   103           // TODO: Lua 5.3 may support more elements
   104           if (arrayidx == INT_MAX) {
   105             lua_pushnumber(L, (size_t)INT_MAX+1);
   106             lua_rawget(L, json_convert_source_idx);
   107             if (lua_isnil(L, -1)) break;
   108             return luaL_error(L, "Array exceeded length of %d elements", INT_MAX);
   109           }
   110           arrayidx++;
   111           lua_rawgeti(L, json_convert_source_idx, arrayidx);
   112           if (lua_isnil(L, -1)) break;
   113           lua_rawseti(L, json_convert_shadow_idx, arrayidx);
   114         }
   115       }
   116     } else {
   117       // if there is an iterator function,
   118       // call iterator function with source value (first argument)
   119       // and store 3 result values on stack positions 5 through 7:
   120       lua_pushvalue(L, json_convert_iterator_idx);
   121       lua_pushvalue(L, 1);
   122       lua_call(L, 1, 3);
   123       while (1) {
   124         lua_pushvalue(L, json_convert_iterfun_idx);
   125         lua_pushvalue(L, json_convert_itertbl_idx);
   126         lua_pushvalue(L, -3);
   127         lua_remove(L, -4);
   128         lua_call(L, 2, 2);
   129         if (lua_isnil(L, -2)) break;
   130         if (lua_type(L, -2) == (array ? LUA_TNUMBER : LUA_TSTRING)) {
   131           lua_pushvalue(L, -2);
   132           lua_pushvalue(L, -2);
   133           lua_rawset(L, json_convert_shadow_idx);
   134         }
   135         lua_pop(L, 1);
   136       }
   137     }
   138     // let result table be on top of stack:
   139     lua_settop(L, json_convert_output_idx);
   140   }
   141   // set metatable (for result table on top of stack):
   142   if (array == 0) json_regfetch(L, objectmt);
   143   else json_regfetch(L, arraymt);
   144   lua_setmetatable(L, -2);
   145   // return table on top of stack:
   146   return 1;
   147 }
   149 static int json_object(lua_State *L) {
   150   return json_convert(L, 0);
   151 }
   153 static int json_array(lua_State *L) {
   154   return json_convert(L, 1);
   155 }
   157 // internal states of JSON parser:
   158 #define JSON_STATE_VALUE 0
   159 #define JSON_STATE_OBJECT_KEY 1
   160 #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
   161 #define JSON_STATE_OBJECT_VALUE 3
   162 #define JSON_STATE_OBJECT_SEPARATOR 4
   163 #define JSON_STATE_ARRAY_VALUE 5
   164 #define JSON_STATE_ARRAY_SEPARATOR 6
   165 #define JSON_STATE_END 7
   167 // special Lua stack indicies for json_import function:
   168 #define json_import_objectmt_idx 2
   169 #define json_import_arraymt_idx 3
   170 #define json_import_shadowtbl_idx 4
   172 // macros for hex decoding:
   173 #define json_utf16_surrogate(x) ((x) >= 0xD800 && (x) <= 0xDFFF)
   174 #define json_utf16_lead(x) ((x) >= 0xD800 && (x) <= 0xDBFF)
   175 #define json_utf16_tail(x) ((x) >= 0xDC00 && (x) <= 0xDFFF)
   176 #define json_import_readhex(x) \
   177   do { \
   178     x = 0; \
   179     for (i=0; i<4; i++) { \
   180       x <<= 4; \
   181       c = str[pos++]; \
   182       if (c >= '0' && c <= '9') x += c - '0'; \
   183       else if (c >= 'A' && c <= 'F') x += c - 'A' + 10; \
   184       else if (c >= 'a' && c <= 'f') x += c - 'a' + 10; \
   185       else if (c == 0) goto json_import_unexpected_eof; \
   186       else goto json_import_unexpected_escape; \
   187     } \
   188   } while (0)
   190 // decodes a JSON document:
   191 static int json_import(lua_State *L) {
   192   int i;             // loop variable
   193   const char *str;   // string to parse
   194   size_t total;      // total length of string to parse
   195   size_t pos = 0;    // current position in string to parse
   196   size_t level = 0;  // nested levels of objects/arrays currently being processed
   197   int mode = JSON_STATE_VALUE;  // state of parser (i.e. "what's expected next?")
   198   unsigned char c;     // variable to store a single character to be processed (unsigned!)
   199   luaL_Buffer luabuf;  // Lua buffer to decode JSON string values
   200   char *cbuf;          // C buffer to decode JSON string values
   201   size_t outlen;       // maximum length or write position of C buffer
   202   long codepoint;      // decoded UTF-16 character or higher codepoint
   203   long utf16tail;      // second decoded UTF-16 character (surrogate tail)
   204   size_t arraylen;     // variable to temporarily store the array length
   205   // require string as argument and convert to C string with length information:
   206   str = luaL_checklstring(L, 1, &total);
   207   // if string contains a NULL byte, this is a syntax error
   208   if (strlen(str) != total) goto json_import_syntax_error;
   209   // stack shall contain one function argument:
   210   lua_settop(L, 1);
   211   // push objectmt onto stack position 2:
   212   json_regfetch(L, objectmt);
   213   // push arraymt onto stack position 3:
   214   json_regfetch(L, arraymt);
   215   // push shadowtbl onto stack position 4:
   216   json_regfetch(L, shadowtbl);
   217   // main loop of parser:
   218   json_import_loop:
   219   // skip whitespace and store next character in variable 'c':
   220   while (c = str[pos],
   221     c == ' ' ||
   222     c == '\f' ||
   223     c == '\n' ||
   224     c == '\r' ||
   225     c == '\t' ||
   226     c == '\v'
   227   ) pos++;
   228   // NOTE: variable c needs to be unsigned in the following code
   229   // switch statement to handle certain (single) characters:
   230   switch (c) {
   231   // handle end of JSON document:
   232   case 0:
   233     // if end of JSON document was expected, then return top element of stack as result:
   234     if (mode == JSON_STATE_END) return 1;
   235     // otherwise, the JSON document was malformed:
   236     if (level == 0) {
   237       lua_pushnil(L);
   238       lua_pushliteral(L, "Empty string");
   239     } else {
   240       json_import_unexpected_eof:
   241       lua_pushnil(L);
   242       lua_pushliteral(L, "Unexpected end of JSON document");
   243     }
   244     return 2;
   245   // new JSON object:
   246   case '{':
   247     // if a JSON object is not expected here, then return an error:
   248     if (
   249       mode != JSON_STATE_VALUE &&
   250       mode != JSON_STATE_OBJECT_VALUE &&
   251       mode != JSON_STATE_ARRAY_VALUE
   252     ) goto json_import_syntax_error;
   253     // create JSON object on stack:
   254     lua_newtable(L);
   255     // set metatable of JSON object:
   256     lua_pushvalue(L, json_import_objectmt_idx);
   257     lua_setmetatable(L, -2);
   258     // create internal shadow table on stack:
   259     lua_newtable(L);
   260     // register internal shadow table:
   261     lua_pushvalue(L, -2);
   262     lua_pushvalue(L, -2);
   263     lua_rawset(L, json_import_shadowtbl_idx);
   264     // expect object key (or end of object) to follow:
   265     mode = JSON_STATE_OBJECT_KEY;
   266     // jump to common code for opening JSON object and JSON array:
   267     goto json_import_open;
   268   // new JSON array:
   269   case '[':
   270     // if a JSON array is not expected here, then return an error:
   271     if (
   272       mode != JSON_STATE_VALUE &&
   273       mode != JSON_STATE_OBJECT_VALUE &&
   274       mode != JSON_STATE_ARRAY_VALUE
   275     ) goto json_import_syntax_error;
   276     // create JSON array on stack:
   277     lua_newtable(L);
   278     // set metatable of JSON array:
   279     lua_pushvalue(L, json_import_arraymt_idx);
   280     lua_setmetatable(L, -2);
   281     // create internal shadow table on stack:
   282     lua_newtable(L);
   283     // register internal shadow table:
   284     lua_pushvalue(L, -2);
   285     lua_pushvalue(L, -2);
   286     lua_rawset(L, json_import_shadowtbl_idx);
   287     // add nil as key (needed to keep stack balance) and as magic to detect arrays:
   288     lua_pushnil(L);
   289     // expect array value (or end of array) to follow:
   290     mode = JSON_STATE_ARRAY_VALUE;
   291     // continue with common code for opening JSON object and JSON array:
   292   // common code for opening JSON object or JSON array:
   293   json_import_open:
   294     // limit nested levels:
   295     if (level >= JSON_MAXDEPTH) {
   296       lua_pushnil(L);
   297       lua_pushfstring(L, "More than %d nested JSON levels", JSON_MAXDEPTH);
   298       return 2;
   299     }
   300     // additional buffer overflow protection:
   301     if (!lua_checkstack(L, LUA_MINSTACK))
   302       return luaL_error(L, "Caught stack overflow in JSON import function (too many nested levels and stack size too small)");
   303     // increment level:
   304     level++;
   305     // consume input character:
   306     pos++;
   307     goto json_import_loop;
   308   // end of JSON object:
   309   case '}':
   310     // if end of JSON object is not expected here, then return an error:
   311     if (
   312       mode != JSON_STATE_OBJECT_KEY &&
   313       mode != JSON_STATE_OBJECT_SEPARATOR
   314     ) goto json_import_syntax_error;
   315     // jump to common code for end of JSON object and JSON array:
   316     goto json_import_close;
   317   // end of JSON array:
   318   case ']':
   319     // if end of JSON array is not expected here, then return an error:
   320     if (
   321       mode != JSON_STATE_ARRAY_VALUE &&
   322       mode != JSON_STATE_ARRAY_SEPARATOR
   323     ) goto json_import_syntax_error;
   324     // pop nil key/magic (that was needed to keep stack balance):
   325     lua_pop(L, 1);
   326     // continue with common code for end of JSON object and JSON array:
   327   // common code for end of JSON object or JSON array:
   328   json_import_close:
   329     // consume input character:
   330     pos++;
   331     // pop shadow table:
   332     lua_pop(L, 1);
   333     // check if nested:
   334     if (--level) {
   335       // if nested,
   336       // check if outer(!) structure is an array or object:
   337       if (lua_isnil(L, -2)) {
   338         // select array value processing:
   339         mode = JSON_STATE_ARRAY_VALUE;
   340       } else {
   341         // select object value processing:
   342         mode = JSON_STATE_OBJECT_VALUE;
   343       }
   344       // store value in outer structure:
   345       goto json_import_process_value;
   346     }
   347     // if not nested, then expect end of JSON document and continue with loop:
   348     mode = JSON_STATE_END;
   349     goto json_import_loop;
   350   // key terminator:
   351   case ':':
   352     // if key terminator is not expected here, then return an error:
   353     if (mode != JSON_STATE_OBJECT_KEY_TERMINATOR)
   354       goto json_import_syntax_error;
   355     // consume input character:
   356     pos++;
   357     // expect object value to follow:
   358     mode = JSON_STATE_OBJECT_VALUE;
   359     // continue with loop:
   360     goto json_import_loop;
   361   // value terminator (NOTE: trailing comma at end of value or key-value list is tolerated by this parser)
   362   case ',':
   363     // branch according to parser state:
   364     if (mode == JSON_STATE_OBJECT_SEPARATOR) {
   365       // expect an object key to follow:
   366       mode = JSON_STATE_OBJECT_KEY;
   367     } else if (mode == JSON_STATE_ARRAY_SEPARATOR) {
   368       // expect an array value to follow:
   369       mode = JSON_STATE_ARRAY_VALUE;
   370     } else {
   371        // if value terminator is not expected here, then return an error:
   372        goto json_import_syntax_error;
   373     }
   374     // consume input character:
   375     pos++;
   376     // continue with loop:
   377     goto json_import_loop;
   378   // string literal:
   379   case '"':
   380     // consume quote character:
   381     pos++;
   382     // find last character in input string:
   383     outlen = pos;
   384     while ((c = str[outlen]) != '"') {
   385       // consume one character:
   386       outlen++;
   387       // handle unexpected end of JSON document:
   388       if (c == 0) goto json_import_unexpected_eof;
   389       // consume one extra character when encountering an escaped quote:
   390       else if (c == '\\' && str[outlen] == '"') outlen++;
   391     }
   392     // determine buffer length:
   393     outlen -= pos;
   394     // check if string is non empty:
   395     if (outlen) {
   396       // prepare buffer to decode string (with maximum possible length) and set write position to zero:
   397       cbuf = luaL_buffinitsize(L, &luabuf, outlen);
   398       outlen = 0;
   399       // loop through the characters until encountering end quote:
   400       while ((c = str[pos++]) != '"') {
   401         // NOTE: unexpected end cannot happen anymore
   402         if (c < 32 || c == 127) {
   403           // do not allow ASCII control characters:
   404           // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized
   405           //       by this parser to allow different encodings than Unicode
   406           lua_pushnil(L);
   407           lua_pushliteral(L, "Unexpected control character in JSON string");
   408           return 2;
   409         } else if (c == '\\') {
   410           // read next char after backslash escape:
   411           c = str[pos++];
   412           switch (c) {
   413           // unexpected end-of-string:
   414           case 0:
   415             goto json_import_unexpected_eof;
   416           // unescaping of quotation mark, slash, and backslash:
   417           case '"':
   418           case '/':
   419           case '\\':
   420             cbuf[outlen++] = c;
   421             break;
   422           // unescaping of backspace:
   423           case 'b': cbuf[outlen++] = '\b'; break;
   424           // unescaping of form-feed:
   425           case 'f': cbuf[outlen++] = '\f'; break;
   426           // unescaping of new-line:
   427           case 'n': cbuf[outlen++] = '\n'; break;
   428           // unescaping of carriage-return:
   429           case 'r': cbuf[outlen++] = '\r'; break;
   430           // unescaping of tabulator:
   431           case 't': cbuf[outlen++] = '\t'; break;
   432           // unescaping of UTF-16 characters
   433           case 'u':
   434             // decode 4 hex nibbles:
   435             json_import_readhex(codepoint);
   436             // handle surrogate character:
   437             if (json_utf16_surrogate(codepoint)) {
   438               // check if first surrogate is in valid range:
   439               if (json_utf16_lead(codepoint)) {
   440                 // require second surrogate:
   441                 if ((c = str[pos++]) != '\\' || (c = str[pos++]) != 'u') {
   442                   if (c == 0) goto json_import_unexpected_eof;
   443                   else goto json_import_wrong_surrogate;
   444                 }
   445                 // read 4 hex nibbles of second surrogate character:
   446                 json_import_readhex(utf16tail);
   447                 // check if second surrogate is in valid range:
   448                 if (!json_utf16_tail(utf16tail)) goto json_import_wrong_surrogate;
   449                 // calculate codepoint:
   450                 codepoint = 0x10000 + (utf16tail - 0xDC00) + (codepoint - 0xD800) * 0x400;
   451               } else {
   452                 // throw error for wrong surrogates:
   453                 json_import_wrong_surrogate:
   454                 lua_pushnil(L);
   455                 lua_pushliteral(L, "Illegal UTF-16 surrogate in JSON string escape sequence");
   456                 return 2;
   457               }
   458             }
   459             // encode as UTF-8:
   460             if (codepoint < 0x80) {
   461               cbuf[outlen++] = (char)codepoint;
   462             } else if (codepoint < 0x800) {
   463               cbuf[outlen++] = (char)(0xc0 | (codepoint >> 6));
   464               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   465             } else if (codepoint < 0x10000) {
   466               cbuf[outlen++] = (char)(0xe0 | (codepoint >> 12));
   467               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 6) & 0x3f));
   468               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   469             } else {
   470               cbuf[outlen++] = (char)(0xf0 | (codepoint >> 18));
   471               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 12) & 0x3f));
   472               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 6) & 0x3f));
   473               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   474             }
   475             break;
   476           // unexpected escape sequence:
   477           default:
   478             json_import_unexpected_escape:
   479             lua_pushnil(L);
   480             lua_pushliteral(L, "Unexpected string escape sequence in JSON document");
   481             return 2;
   482           }
   483         } else {
   484           // normal character:
   485           cbuf[outlen++] = c;
   486         }
   487       }
   488       // process buffer to Lua string:
   489       luaL_pushresultsize(&luabuf, outlen);
   490     } else {
   491       // if JSON string is empty,
   492       // push empty Lua string:
   493       lua_pushliteral(L, "");
   494       // consume closing quote:
   495       pos++;
   496     }
   497     // continue with processing of decoded string:
   498     goto json_import_process_value;
   499   }
   500   // process values whose type is is not deducible from a single character:
   501   if ((c >= '0' && c <= '9') || c == '-' || c == '+') {
   502     // for numbers,
   503     // use strtod() call to parse a (double precision) floating point number:
   504     double numval;
   505     char *endptr;
   506     numval = strtod(str+pos, &endptr);
   507     // catch parsing errors:
   508     if (endptr == str+pos) goto json_import_syntax_error;
   509     // consume characters that were parsed:
   510     pos += endptr - (str+pos);
   511     // push parsed (double precision) floating point number on Lua stack:
   512     lua_pushnumber(L, numval);
   513   } else if (!strncmp(str+pos, "true", 4)) {
   514     // consume 4 input characters for "true":
   515     pos += 4;
   516     // put Lua true value onto stack:
   517     lua_pushboolean(L, 1);
   518   } else if (!strncmp(str+pos, "false", 5)) {
   519     // consume 5 input characters for "false":
   520     pos += 5;
   521     // put Lua false value onto stack:
   522     lua_pushboolean(L, 0);
   523   } else if (!strncmp(str+pos, "null", 4)) {
   524     // consume 4 input characters for "null":
   525     pos += 4;
   526     // different behavor for top-level and sub-levels:
   527     if (level) {
   528       // if sub-level,
   529       // push special null-marker onto stack:
   530       json_pushnullmark(L);
   531     } else {
   532       // if top-level,
   533       // push nil onto stack:
   534       lua_pushnil(L);
   535     }
   536   } else {
   537     // all other cases are a syntax error:
   538     goto json_import_syntax_error;
   539   }
   540   // process a decoded value or key value pair (expected on top of Lua stack):
   541   json_import_process_value:
   542   switch (mode) {
   543   // an object key has been read:
   544   case JSON_STATE_OBJECT_KEY:
   545     // if an object key is not a string, then this is a syntax error:
   546     if (lua_type(L, -1) != LUA_TSTRING) goto json_import_syntax_error;
   547     // expect key terminator to follow:
   548     mode = JSON_STATE_OBJECT_KEY_TERMINATOR;
   549     // continue with loop:
   550     goto json_import_loop;
   551   // a key value pair has been read:
   552   case JSON_STATE_OBJECT_VALUE:
   553     // store key value pair in outer shadow table:
   554     lua_rawset(L, -3);
   555     // expect value terminator (or end of object) to follow:
   556     mode = JSON_STATE_OBJECT_SEPARATOR;
   557     // continue with loop:
   558     goto json_import_loop;
   559   // an array value has been read:
   560   case JSON_STATE_ARRAY_VALUE:
   561     // get current array length:
   562     arraylen = lua_rawlen(L, -3);
   563     // throw error if array would exceed INT_MAX elements:
   564     // TODO: Lua 5.3 may support more elements
   565     if (arraylen >= INT_MAX) {
   566       lua_pushnil(L);
   567       lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX);
   568     }
   569     // store value in outer shadow table:
   570     lua_rawseti(L, -3, arraylen + 1);
   571     // expect value terminator (or end of object) to follow:
   572     mode = JSON_STATE_ARRAY_SEPARATOR;
   573     // continue with loop
   574     goto json_import_loop;
   575   // a single value has been read:
   576   case JSON_STATE_VALUE:
   577     // leave value on top of stack, expect end of JSON document, and continue with loop:
   578     mode = JSON_STATE_END;
   579     goto json_import_loop;
   580   }
   581   // syntax error handling (reachable by goto statement):
   582   json_import_syntax_error:
   583   lua_pushnil(L);
   584   lua_pushliteral(L, "Syntax error in JSON document");
   585   return 2;
   586 }
   588 // special Lua stack indicies for json_path function:
   589 #define json_path_shadowtbl_idx 1
   591 // stack offset of arguments to json_path function:
   592 #define json_path_idxshift 1
   594 // gets a value or its type from a JSON document (passed as first argument)
   595 // using a path (passed as variable number of keys after first argument):
   596 static int json_path(lua_State *L, int type_mode) {
   597   int stacktop;                      // stack index of top of stack (after shifting)
   598   int idx = 2 + json_path_idxshift;  // stack index of current argument to process
   599   // insert shadowtbl into stack at position 1 (shifting the arguments):
   600   json_regfetch(L, shadowtbl);
   601   lua_insert(L, 1);
   602   // store stack index of top of stack:
   603   stacktop = lua_gettop(L);
   604   // use first argument as "current value" (stored on top of stack):
   605   lua_pushvalue(L, 1 + json_path_idxshift);
   606   // process each "path key" (2nd argument and following arguments):
   607   while (idx <= stacktop) {
   608     // if "current value" (on top of stack) is nil, then the path cannot be walked and nil is returned:
   609     if (lua_isnil(L, -1)) return 1;
   610     // try to get shadow table of "current value":
   611     lua_pushvalue(L, -1);
   612     lua_rawget(L, json_path_shadowtbl_idx);
   613     if (lua_isnil(L, -1)) {
   614       // if no shadow table is found,
   615       if (lua_type(L, -1) == LUA_TTABLE) {
   616         // and if "current value" is a table,
   617         // drop nil from stack:
   618         lua_pop(L, 1);
   619         // get "next value" using the "path key":
   620         lua_pushvalue(L, idx++);
   621         lua_gettable(L, -2);
   622       } else {
   623         // if "current value" is not a table,
   624         // then the path cannot be walked and nil (already on top of stack) is returned:
   625         return 1;
   626       }
   627     } else {
   628       // if a shadow table is found,
   629       // set "current value" to its shadow table:
   630       lua_replace(L, -2);
   631       // get "next value" using the "path key":
   632       lua_pushvalue(L, idx++);
   633       lua_rawget(L, -2);
   634     }
   635     // the "next value" replaces the "current value":
   636     lua_replace(L, -2);
   637   }
   638   if (!type_mode) {
   639     // if a value (and not its type) was requested,
   640     // check if value is the null-marker, and store nil on top of Lua stack in that case:
   641     if (json_isnullmark(L, -1)) lua_pushnil(L);
   642   } else {
   643     // if the type was requested,
   644     // check if value is the null-marker:
   645     if (json_isnullmark(L, -1)) {
   646       // if yes, store string "null" on top of Lua stack:
   647       lua_pushliteral(L, "null");
   648     } else {
   649       // otherwise,
   650       // check if metatable indicates "object" or "array":
   651       if (lua_getmetatable(L, -1)) {
   652         json_regfetch(L, objectmt);
   653         if (lua_rawequal(L, -2, -1)) {
   654           // if value has metatable for JSON objects,
   655           // return string "object":
   656           lua_pushliteral(L, "object");
   657           return 1;
   658         }
   659         json_regfetch(L, arraymt);
   660         if (lua_rawequal(L, -3, -1)) {
   661           // if value has metatable for JSON arrays,
   662           // return string "object":
   663           lua_pushliteral(L, "array");
   664           return 1;
   665         }
   666         // remove 3 metatables (one of the value, two for comparison) from stack:
   667         lua_pop(L, 3);
   668       }
   669       // otherwise, get the Lua type:
   670       lua_pushstring(L, lua_typename(L, lua_type(L, -1)));
   671     }
   672   }
   673   // return the top most value on the Lua stack:
   674   return 1;
   675 }
   677 // gets a value from a JSON document (passed as first argument)
   678 // using a path (passed as variable number of keys after first argument):
   679 static int json_get(lua_State *L) {
   680   return json_path(L, 0);
   681 }
   683 // gets a value's type from a JSON document (passed as first argument)
   684 // using a path (variable number of keys after first argument):
   685 static int json_type(lua_State *L) {
   686   return json_path(L, 1);
   687 }
   689 // returns the length of a JSON array (or zero for a table without numeric keys):
   690 static int json_len(lua_State *L) {
   691   // stack shall contain one function argument:
   692   lua_settop(L, 1);
   693   // try to get corresponding shadow table for first argument:
   694   json_regfetch(L, shadowtbl);
   695   lua_pushvalue(L, 1);
   696   lua_rawget(L, -2);
   697   // if shadow table does not exist, return length of argument, else length of shadow table:
   698   lua_pushnumber(L, lua_rawlen(L, lua_isnil(L, -1) ? 1 : -1));
   699   return 1;
   700 }
   702 static int json_index(lua_State *L) {
   703   // stack shall contain two function arguments:
   704   lua_settop(L, 2);
   705   // get corresponding shadow table for first argument:
   706   json_regfetch(L, shadowtbl);
   707   lua_pushvalue(L, 1);
   708   lua_rawget(L, -2);
   709   // throw error if no shadow table was found:
   710   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   711   // use key passed as second argument to lookup value in shadow table:
   712   lua_pushvalue(L, 2);
   713   lua_rawget(L, -2);
   714   // if value is null-marker, then push nil onto stack:
   715   if (json_isnullmark(L, -1)) lua_pushnil(L);
   716   // return either looked up value, or nil
   717   return 1;
   718 }
   720 static int json_newindex(lua_State *L) {
   721   // stack shall contain three function arguments:
   722   lua_settop(L, 3);
   723   // get corresponding shadow table for first argument:
   724   json_regfetch(L, shadowtbl);
   725   lua_pushvalue(L, 1);
   726   lua_rawget(L, -2);
   727   // throw error if no shadow table was found:
   728   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   729   // replace first argument with shadow table:
   730   lua_replace(L, 1);
   731   // reset stack and use second and third argument to write to shadow table:
   732   lua_settop(L, 3);
   733   lua_rawset(L, 1);
   734   // return nothing:
   735   return 0;
   736 }
   738 static int json_pairs_iterfunc(lua_State *L) {
   739   // stack shall contain two function arguments:
   740   lua_settop(L, 2);
   741   // get corresponding shadow table for first argument:
   742   json_regfetch(L, shadowtbl);
   743   lua_pushvalue(L, 1);
   744   lua_rawget(L, -2);
   745   // throw error if no shadow table was found:
   746   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   747   // get next key value pair from shadow table (using previous key from argument 2)
   748   // and return nothing if there is no next pair:
   749   lua_pushvalue(L, 2);
   750   if (!lua_next(L, -2)) return 0;
   751   // replace null-marker with nil:
   752   if (json_isnullmark(L, -1)) {
   753     lua_pop(L, 1);
   754     lua_pushnil(L);
   755   }
   756   // return key and value (or key and nil, if null-marker was found):
   757   return 2;
   758 }
   760 // returns a triple such that 'for key, value in pairs(obj) do ... end'
   761 // iterates through all key value pairs (including JSON null keys represented as Lua nil):
   762 static int json_pairs(lua_State *L) {
   763   // require one argument to function
   764   luaL_checkany(L, 1);
   765   // return triple of function json_pairs_iterfunc, first argument, and nil:
   766   lua_pushcfunction(L, json_pairs_iterfunc);
   767   lua_pushvalue(L, 1);
   768   lua_pushnil(L);
   769   return 3;
   770 }
   772 static int json_ipairs_iterfunc(lua_State *L) {
   773   lua_Integer idx;
   774   // stack shall contain two function arguments:
   775   lua_settop(L, 2);
   776   // calculate new index by incrementing second argument:
   777   idx = lua_tointeger(L, 2) + 1;
   778   // get corresponding shadow table for first argument:
   779   json_regfetch(L, shadowtbl);
   780   lua_pushvalue(L, 1);
   781   lua_rawget(L, -2);
   782   // throw error if no shadow table was found:
   783   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   784   // do integer lookup in shadow table:
   785   lua_rawgeti(L, -1, idx);
   786   // return nothing if there was no value:
   787   if (lua_isnil(L, -1)) return 0;
   788   // return new index and
   789   // either the looked up value if it is not equal to the null-marker
   790   // or nil instead of null-marker:
   791   lua_pushinteger(L, idx);
   792   if (json_isnullmark(L, -2)) lua_pushnil(L);
   793   else lua_pushvalue(L, -2);
   794   return 2;
   795 }
   797 // returns a triple such that 'for idx, value in ipairs(ary) do ... end'
   798 // iterates through all values (including JSON null represented as Lua nil):
   799 static int json_ipairs(lua_State *L) {
   800   // require one argument to function
   801   luaL_checkany(L, 1);
   802   // return triple of function json_ipairs_iterfunc, first argument, and zero:
   803   lua_pushcfunction(L, json_ipairs_iterfunc);
   804   lua_pushvalue(L, 1);
   805   lua_pushinteger(L, 0);
   806   return 3;
   807 }
   809 typedef struct {
   810   size_t length;
   811   const char *data;
   812 } json_key_t;
   814 static int json_key_cmp(json_key_t *key1, json_key_t *key2) {
   815   size_t pos = 0;
   816   unsigned char c1, c2;
   817   while (1) {
   818     if (key1->length > pos) {
   819       if (key2->length > pos) {
   820         c1 = key1->data[pos];
   821         c2 = key2->data[pos];
   822         if (c1 < c2) return -1;
   823         else if (c1 > c2) return 1;
   824       } else {
   825         return 1;
   826       }
   827     } else {
   828       if (key2->length > pos) {
   829         return -1;
   830       } else {
   831         return 0;
   832       }
   833     }
   834     pos++;
   835   }
   836 }
   838 #define JSON_TABLETYPE_UNKNOWN 0
   839 #define JSON_TABLETYPE_OBJECT 1
   840 #define JSON_TABLETYPE_ARRAY 2
   842 #define json_export_internal_indentstring_idx 1
   843 #define json_export_internal_level_idx 2
   844 #define json_export_internal_value_idx 3
   845 #define json_export_internal_tmp_idx 4
   847 static int json_export_internal(lua_State *L) {
   848   int level;
   849   int pretty;
   850   int i;
   851   lua_Number num;
   852   const char *str;
   853   unsigned char c;
   854   size_t strlen;
   855   size_t pos = 0;
   856   luaL_Buffer buf;
   857   char hexcode[7];  // backslash, character 'u', 4 hex digits, and terminating NULL byte
   858   int tabletype = JSON_TABLETYPE_UNKNOWN;
   859   int anyelement = 0;
   860   size_t keycount = 0;
   861   size_t keypos = 0;
   862   json_key_t *keybuf = NULL;
   863   lua_Integer idx;
   864   lua_settop(L, json_export_internal_value_idx);
   865   if (json_isnullmark(L, json_export_internal_value_idx)) {
   866     lua_pop(L, 1);
   867     lua_pushnil(L);
   868   }
   869   switch (lua_type(L, json_export_internal_value_idx)) {
   870   case LUA_TNIL:
   871     lua_pushliteral(L, "null");
   872     return 1;
   873   case LUA_TNUMBER:
   874     num = lua_tonumber(L, json_export_internal_value_idx);
   875     if (isnan(num)) return luaL_error(L, "JSON export not possible for NaN value");
   876     if (isinf(num)) return luaL_error(L, "JSON export not possible for infinite numbers");
   877     lua_tostring(L, json_export_internal_value_idx);
   878     return 1;
   879   case LUA_TBOOLEAN:
   880     if (lua_toboolean(L, json_export_internal_value_idx)) {
   881       lua_pushliteral(L, "true");
   882     } else {
   883       lua_pushliteral(L, "false");
   884     }
   885     return 1;
   886   case LUA_TSTRING:
   887     str = lua_tolstring(L, 3, &strlen);
   888     luaL_buffinit(L, &buf);
   889     luaL_addchar(&buf, '"');
   890     while (pos < strlen) {
   891       c = str[pos++];
   892       if (c == '"')       luaL_addstring(&buf, "\\\"");
   893       else if (c == '\\') luaL_addstring(&buf, "\\\\");
   894       else if (c == 127)  luaL_addstring(&buf, "\\u007F");
   895       else if (c >= 32)   luaL_addchar(&buf, c);
   896       else if (c == '\b') luaL_addstring(&buf, "\\b");
   897       else if (c == '\f') luaL_addstring(&buf, "\\f");
   898       else if (c == '\n') luaL_addstring(&buf, "\\n");
   899       else if (c == '\r') luaL_addstring(&buf, "\\r");
   900       else if (c == '\t') luaL_addstring(&buf, "\\t");
   901       else if (c == '\v') luaL_addstring(&buf, "\\v");
   902       else {
   903         sprintf(hexcode, "\\u%04X", c);
   904         luaL_addstring(&buf, hexcode);
   905       }
   906     }
   907     luaL_addchar(&buf, '"');
   908     luaL_pushresult(&buf);
   909     return 1;
   910   case LUA_TTABLE:
   911     if (lua_getmetatable(L, json_export_internal_value_idx)) {
   912       json_regfetch(L, objectmt);
   913       if (lua_rawequal(L, -2, -1)) {
   914         tabletype = JSON_TABLETYPE_OBJECT;
   915       } else {
   916         json_regfetch(L, arraymt);
   917         if (lua_rawequal(L, -3, -1)) {
   918           tabletype = JSON_TABLETYPE_ARRAY;
   919         } else {
   920           return luaL_error(L, "JSON export not possible for tables with nonsupported metatable");
   921         }
   922       }
   923     }
   924     json_regfetch(L, shadowtbl);
   925     lua_pushvalue(L, json_export_internal_value_idx);
   926     lua_rawget(L, -2);
   927     if (!lua_isnil(L, -1)) lua_replace(L, json_export_internal_value_idx);
   928     lua_settop(L, json_export_internal_value_idx);
   929     if (tabletype == JSON_TABLETYPE_UNKNOWN) {
   930       for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) {
   931         switch (lua_type(L, -2)) {
   932         case LUA_TSTRING:
   933           keycount++;
   934           if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_OBJECT;
   935           else if (tabletype == JSON_TABLETYPE_ARRAY) goto json_export_tabletype_error;
   936           break;
   937         case LUA_TNUMBER:
   938           if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_ARRAY;
   939           else if (tabletype == JSON_TABLETYPE_OBJECT) goto json_export_tabletype_error;
   940           break;
   941         }
   942       }
   943     }
   944     pretty = lua_toboolean(L, json_export_internal_indentstring_idx);
   945     level = lua_tointeger(L, json_export_internal_level_idx) + 1;
   946     if (level > JSON_MAXDEPTH) {
   947       return luaL_error(L, "More than %d nested JSON levels", JSON_MAXDEPTH);
   948     }
   949     switch (tabletype) {
   950     case JSON_TABLETYPE_OBJECT:
   951       if (!keycount) {
   952         for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) {
   953           if (lua_type(L, -2) == LUA_TSTRING) keycount++;
   954         }
   955       }
   956       if (keycount) {
   957         keybuf = calloc(keycount, sizeof(json_key_t));
   958         if (!keybuf) return luaL_error(L, "Memory allocation failed in JSON library");
   959         for (lua_pushnil(L); lua_next(L, json_export_internal_value_idx); lua_pop(L, 1)) {
   960           if (lua_type(L, -2) == LUA_TSTRING) {
   961             json_key_t *key = keybuf + (keypos++);
   962             key->data = lua_tolstring(L, -2, &key->length);
   963           }
   964         }
   965         qsort(keybuf, keycount, sizeof(json_key_t), (void *)json_key_cmp);
   966       }
   967       luaL_buffinit(L, &buf);
   968       luaL_addchar(&buf, '{');
   969       for (keypos=0; keypos<keycount; keypos++) {
   970         json_key_t *key = keybuf + keypos;
   971         if (keypos) luaL_addchar(&buf, ',');
   972         if (pretty) {
   973           luaL_addchar(&buf, '\n');
   974           for (i=0; i<level; i++) {
   975             lua_pushvalue(L, json_export_internal_indentstring_idx);
   976             luaL_addvalue(&buf);
   977           }
   978         }
   979         lua_pushcfunction(L, json_export_internal);
   980         lua_pushvalue(L, json_export_internal_indentstring_idx);
   981         lua_pushinteger(L, level);
   982         lua_pushlstring(L, key->data, key->length);
   983         if (lua_pcall(L, 3, 1, 0)) {
   984           if (keybuf) free(keybuf);
   985           return lua_error(L);
   986         }
   987         luaL_addvalue(&buf);
   988         luaL_addchar(&buf, ':');
   989         if (pretty) luaL_addchar(&buf, ' ');
   990         lua_pushcfunction(L, json_export_internal);
   991         lua_pushvalue(L, json_export_internal_indentstring_idx);
   992         lua_pushinteger(L, level);
   993         lua_pushlstring(L, key->data, key->length);
   994         lua_rawget(L, json_export_internal_value_idx);
   995         if (lua_pcall(L, 3, 1, 0)) {
   996           if (keybuf) free(keybuf);
   997           return lua_error(L);
   998         }
   999         luaL_addvalue(&buf);
  1000       }
  1001       if (keybuf) free(keybuf);
  1002       if (pretty && keycount != 0) {
  1003         luaL_addchar(&buf, '\n');
  1004         for (i=0; i<level-1; i++) {
  1005           lua_pushvalue(L, json_export_internal_indentstring_idx);
  1006           luaL_addvalue(&buf);
  1007         }
  1008       }
  1009       luaL_addchar(&buf, '}');
  1010       if (pretty && level == 1) luaL_addchar(&buf, '\n');
  1011       luaL_pushresult(&buf);
  1012       return 1;
  1013     case JSON_TABLETYPE_ARRAY:
  1014       lua_settop(L, json_export_internal_tmp_idx);
  1015       luaL_buffinit(L, &buf);
  1016       luaL_addchar(&buf, '[');
  1017       for (idx = 1; ; idx++) {
  1018         lua_rawgeti(L, json_export_internal_value_idx, idx);
  1019         if (lua_isnil(L, -1)) {
  1020           lua_pop(L, 1);
  1021           break;
  1022         }
  1023         lua_replace(L, json_export_internal_tmp_idx);
  1024         if (anyelement) luaL_addchar(&buf, ',');
  1025         anyelement = 1;
  1026         if (pretty) {
  1027           luaL_addchar(&buf, '\n');
  1028           for (i=0; i<level; i++) {
  1029             lua_pushvalue(L, json_export_internal_indentstring_idx);
  1030             luaL_addvalue(&buf);
  1031           }
  1032         }
  1033         lua_pushcfunction(L, json_export_internal);
  1034         lua_pushvalue(L, json_export_internal_indentstring_idx);
  1035         lua_pushinteger(L, level);
  1036         lua_pushvalue(L, json_export_internal_tmp_idx);
  1037         lua_call(L, 3, 1);
  1038         luaL_addvalue(&buf);
  1039       }
  1040       if (pretty && anyelement) {
  1041         luaL_addchar(&buf, '\n');
  1042         for (i=0; i<level-1; i++) {
  1043           lua_pushvalue(L, json_export_internal_indentstring_idx);
  1044           luaL_addvalue(&buf);
  1045         }
  1046       }
  1047       luaL_addchar(&buf, ']');
  1048       if (pretty && level == 1) luaL_addchar(&buf, '\n');
  1049       luaL_pushresult(&buf);
  1050       return 1;
  1051     }
  1052     json_export_tabletype_error:
  1053     return luaL_error(L, "JSON export not possible for ambiguous table (cannot decide whether it is an object or array)");
  1054   }
  1055   return luaL_error(L, "JSON export not possible for values of type \"%s\"", lua_typename(L, lua_type(L, json_export_internal_value_idx)));
  1056 }
  1058 static int json_export(lua_State *L) {
  1059   lua_settop(L, 1);
  1060   lua_pushcfunction(L, json_export_internal);
  1061   lua_pushnil(L);
  1062   lua_pushinteger(L, 0);
  1063   lua_pushvalue(L, 1);
  1064   lua_call(L, 3, 1);
  1065   return 1;
  1066 }
  1068 static int json_pretty(lua_State *L) {
  1069   lua_settop(L, 2);
  1070   lua_pushcfunction(L, json_export_internal);
  1071   if (lua_isnil(L, 2)) lua_pushliteral(L, "  ");
  1072   else lua_pushvalue(L, 2);
  1073   lua_pushinteger(L, 0);
  1074   lua_pushvalue(L, 1);
  1075   lua_call(L, 3, 1);
  1076   return 1;
  1077 }
  1079 // functions in library module:
  1080 static const struct luaL_Reg json_module_functions[] = {
  1081   {"object", json_object},
  1082   {"array", json_array},
  1083   {"import", json_import},
  1084   {"export", json_export},
  1085   {"pretty", json_pretty},
  1086   {"get", json_get},
  1087   {"type", json_type},
  1088   {NULL, NULL}
  1089 };
  1091 // metamethods for JSON objects, JSON arrays, and unknown JSON collections (object or array):
  1092 static const struct luaL_Reg json_metatable_functions[] = {
  1093   {"__len", json_len},
  1094   {"__index", json_index},
  1095   {"__newindex", json_newindex},
  1096   {"__pairs", json_pairs},
  1097   {"__ipairs", json_ipairs},
  1098   {"__tostring", json_export},
  1099   {NULL, NULL}
  1100 };
  1102 // metamethods for JSON null marker:
  1103 static const struct luaL_Reg json_nullmark_metamethods[] = {
  1104   {"__tostring", json_nullmark_tostring},
  1105   {NULL, NULL}
  1106 };
  1108 // initializes json library:
  1109 int luaopen_json(lua_State *L) {
  1110   // empty stack:
  1111   lua_settop(L, 0);
  1112   // push library module onto stack position 1:
  1113   lua_newtable(L);
  1114   // register library functions:
  1115   luaL_setfuncs(L, json_module_functions, 0);
  1116   // create and store objectmt:
  1117   lua_newtable(L);
  1118   luaL_setfuncs(L, json_metatable_functions, 0);
  1119   json_regstore(L, objectmt);
  1120   // create and store arraymt:
  1121   lua_newtable(L);
  1122   luaL_setfuncs(L, json_metatable_functions, 0);
  1123   json_regstore(L, arraymt);
  1124   // create and store ephemeron table to store shadow tables for each JSON object/array
  1125   // to allow NULL values returned as nil
  1126   lua_newtable(L);
  1127   lua_newtable(L);  // metatable for ephemeron table
  1128   lua_pushliteral(L, "__mode");
  1129   lua_pushliteral(L, "k");
  1130   lua_rawset(L, -3);
  1131   lua_setmetatable(L, -2);
  1132   json_regstore(L, shadowtbl);
  1133   // set metatable of null marker and make it available through library module:
  1134   json_pushnullmark(L);
  1135   lua_newtable(L);
  1136   luaL_setfuncs(L, json_nullmark_metamethods, 0);
  1137   lua_setmetatable(L, -2);
  1138   lua_setfield(L, 1, "null");
  1139   // return library module (that's expected on top of stack):
  1140   return 1;
  1141 }
