webmcp
view libraries/json/json.c @ 200:035b58aa430a
Improve performance of pairs and ipairs in JSON library
| author | jbe | 
|---|---|
| date | Thu Aug 14 01:11:24 2014 +0200 (2014-08-14) | 
| parents | 9fd7e1bf9fe3 | 
| children | 1a10fef86d97 | 
 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: json_import can store 2^32 / 3 levels on stack swap (using
     9 //       also negative indicies after integer wraparound), and
    10 //       json_export can store even more levels, so 1024^3 =
    11 //       1073741824 is a safe value and allows practically unlimited
    12 //       levels for JSON documents <= 2 GiB.
    13 #define JSON_MAXDEPTH (1024*1024*1024)
    15 // define type JSON_LIGHTUSERDATA and
    16 // generate dummy memory addresses for lightuserdata values:
    17 #define JSON_LIGHTUSERDATA char
    18 static struct {
    19   JSON_LIGHTUSERDATA nullmark;   // lightuserdata value represents a NULL value
    20   JSON_LIGHTUSERDATA shadowtbl;  // lightuserdata key for shadow table
    21 } json_lightuserdata;
    23 // macros for special nullmark value:
    24 #define json_isnullmark(L, i) (lua_touserdata((L), (i)) == &json_lightuserdata.nullmark)
    25 #define json_pushnullmark(L) lua_pushlightuserdata((L), &json_lightuserdata.nullmark)
    27 // macros for getting and setting shadow tables
    28 #define json_setshadow(L, i) lua_rawsetp((L), (i), &json_lightuserdata.shadowtbl)
    29 #define json_getshadow(L, i) lua_rawgetp((L), (i), &json_lightuserdata.shadowtbl)
    30 #define json_createproxy(L) lua_createtable((L), 0, 1)
    32 // generate additional dummy memory addresses that represent Lua objects
    33 // via lightuserdata keys and LUA_REGISTRYINDEX:
    34 static struct {
    35   JSON_LIGHTUSERDATA objectmt;  // metatable for JSON objects
    36   JSON_LIGHTUSERDATA arraymt;   // metatable for JSON arrays
    37 } json_registry;
    39 // macros for usage of Lua registry:
    40 #define json_regpointer(x) (&json_registry.x)
    41 #define json_regfetchpointer(L, x) lua_rawgetp((L), LUA_REGISTRYINDEX, (x))
    42 #define json_regfetch(L, x) json_regfetchpointer(L, json_regpointer(x))
    43 #define json_regstore(L, x) lua_rawsetp(L, LUA_REGISTRYINDEX, json_regpointer(x))
    45 // returns the string "<JSON null marker>":
    46 static int json_nullmark_tostring(lua_State *L) {
    47   lua_pushliteral(L, "<JSON null marker>");
    48   return 1;
    49 }
    51 #define json_convert_source_idx 1
    52 #define json_convert_iterator_idx 2
    53 #define json_convert_output_idx 3
    54 #define json_convert_shadow_idx 4
    55 #define json_convert_iterfun_idx 5
    56 #define json_convert_itertbl_idx 6
    58 // converts a Lua table (or any other iterable value) to a JSON object or JSON array:
    59 // (does never modify the argument, returns an empty object or array if argument is nil)
    60 static int json_convert(lua_State *L, int array) {
    61   int arrayidx = 0;
    62   // determine is argument is given:
    63   if (lua_isnoneornil(L, json_convert_source_idx)) {
    64     // if no argument is given (or if argument is nil),
    65     // create proxy table with shadow table, and leave proxy table on top of stack:
    66     json_createproxy(L);
    67     lua_newtable(L);
    68     json_setshadow(L, -2);
    69   } else {
    70     // if an argument was given,
    71     // stack shall contain only one function argument:
    72     lua_settop(L, 1);
    73     // check if there is an iterator function in its metatable:
    74     if (luaL_getmetafield(L, json_convert_source_idx, array ? "__ipairs" : "__pairs")) {
    75       // if there is an iterator function,
    76       // leave it on stack position 2 and verify its type:
    77       if (lua_type(L, json_convert_iterator_idx) != LUA_TFUNCTION)
    78         return luaL_error(L, "%s metamethod is not a function", array ? "__ipairs" : "__pairs");
    79     } else {
    80       // if there is no iterator function,
    81       // verify the type of the argument itself:
    82       luaL_checktype(L, json_convert_source_idx, LUA_TTABLE);
    83       // push nil onto stack position 2:
    84       lua_pushnil(L);
    85     }
    86     // create result table on stack position 3:
    87     json_createproxy(L);
    88     // create shadow table on stack position 4:
    89     lua_newtable(L);
    90     lua_pushvalue(L, -1);
    91     json_setshadow(L, -3);
    92     // check if iterator function exists:
    93     if (lua_isnil(L, json_convert_iterator_idx)) {
    94       // if there is no iterator function,
    95       // distinguish between objects and arrays:
    96       if (array == 0) {
    97         // for an object, copy all string key value pairs to shadow table:
    98         for (lua_pushnil(L); lua_next(L, json_convert_source_idx); lua_pop(L, 1)) {
    99           if (lua_type(L, -2) == LUA_TSTRING) {
   100             lua_pushvalue(L, -2);
   101             lua_pushvalue(L, -2);
   102             lua_rawset(L, json_convert_shadow_idx);
   103           }
   104         }
   105       } else {
   106         // for an array, copy consecutive integer value pairs to shadow table:
   107         while (1) {
   108           // throw error if array would exceed INT_MAX elements:
   109           // TODO: Lua 5.3 may support more elements
   110           if (arrayidx == INT_MAX) {
   111             lua_pushnumber(L, (size_t)INT_MAX+1);
   112             lua_rawget(L, json_convert_source_idx);
   113             if (lua_isnil(L, -1)) break;
   114             return luaL_error(L, "Array exceeded length of %d elements", INT_MAX);
   115           }
   116           // get next array entry:
   117           arrayidx++;
   118           lua_rawgeti(L, json_convert_source_idx, arrayidx);
   119           // break if value is nil:
   120           if (lua_isnil(L, -1)) break;
   121           // store value in shadow table:
   122           lua_rawseti(L, json_convert_shadow_idx, arrayidx);
   123         }
   124       }
   125     } else {
   126       // if there is an iterator function,
   127       // call iterator function with source value (first argument)
   128       // and store 3 result values on stack positions 5 through 7:
   129       lua_pushvalue(L, json_convert_iterator_idx);
   130       lua_pushvalue(L, 1);
   131       lua_call(L, 1, 3);
   132       // iterate through key value pairs and store some of them in shadow table
   133       // while replacing nil values with null-marker:
   134       while (1) {
   135         // call iterfun function:
   136         lua_pushvalue(L, json_convert_iterfun_idx);
   137         lua_pushvalue(L, json_convert_itertbl_idx);
   138         lua_pushvalue(L, -3);
   139         lua_remove(L, -4);
   140         lua_call(L, 2, 2);
   141         // break iteration loop if key is nil:
   142         if (lua_isnil(L, -2)) break;
   143         // store key value pair only if key type is correct:
   144         if (lua_type(L, -2) == (array ? LUA_TNUMBER : LUA_TSTRING)) {
   145           // if key type is correct,
   146           // push key onto stack:
   147           lua_pushvalue(L, -2);
   148           // if value is nil, push null-marker onto stack (as value):
   149           if (lua_isnil(L, -2)) json_pushnullmark(L);
   150           // else push value onto stack:
   151           else lua_pushvalue(L, -2);
   152           // set key value pair in shadow table:
   153           lua_rawset(L, json_convert_shadow_idx);
   154         }
   155         // pop value from stack, but leave key on stack:
   156         lua_pop(L, 1);
   157       }
   158     }
   159     // let result table be on top of stack:
   160     lua_settop(L, json_convert_output_idx);
   161   }
   162   // set metatable (for result table on top of stack):
   163   if (array == 0) json_regfetch(L, objectmt);
   164   else json_regfetch(L, arraymt);
   165   lua_setmetatable(L, -2);
   166   // return table on top of stack:
   167   return 1;
   168 }
   170 // converts a Lua table (or any other iterable value) to a JSON object:
   171 // (does never modify the argument, returns an empty object or array if argument is nil)
   172 static int json_object(lua_State *L) {
   173   return json_convert(L, 0);
   174 }
   176 // converts a Lua table (or any other iterable value) to a JSON array:
   177 // (does never modify the argument, returns an empty object or array if argument is nil)
   178 static int json_array(lua_State *L) {
   179   return json_convert(L, 1);
   180 }
   182 // internal states of JSON parser:
   183 #define JSON_STATE_VALUE 0
   184 #define JSON_STATE_OBJECT_KEY 1
   185 #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
   186 #define JSON_STATE_OBJECT_VALUE 3
   187 #define JSON_STATE_OBJECT_SEPARATOR 4
   188 #define JSON_STATE_ARRAY_VALUE 5
   189 #define JSON_STATE_ARRAY_SEPARATOR 6
   190 #define JSON_STATE_END 7
   192 // special Lua stack indicies for json_import function:
   193 #define json_import_objectmt_idx 2
   194 #define json_import_arraymt_idx 3
   195 #define json_import_stackswap_idx 4
   197 // macros for hex decoding:
   198 #define json_utf16_surrogate(x) ((x) >= 0xD800 && (x) <= 0xDFFF)
   199 #define json_utf16_lead(x) ((x) >= 0xD800 && (x) <= 0xDBFF)
   200 #define json_utf16_tail(x) ((x) >= 0xDC00 && (x) <= 0xDFFF)
   201 #define json_import_readhex(x) \
   202   do { \
   203     x = 0; \
   204     for (i=0; i<4; i++) { \
   205       x <<= 4; \
   206       c = str[pos++]; \
   207       if (c >= '0' && c <= '9') x += c - '0'; \
   208       else if (c >= 'A' && c <= 'F') x += c - 'A' + 10; \
   209       else if (c >= 'a' && c <= 'f') x += c - 'a' + 10; \
   210       else if (c == 0) goto json_import_unexpected_eof; \
   211       else goto json_import_unexpected_escape; \
   212     } \
   213   } while (0)
   215 // decodes a JSON document:
   216 static int json_import(lua_State *L) {
   217   int stackswapidx = 0;  // elements in stack swap table
   218   int i;                 // loop variable
   219   const char *str;       // string to parse
   220   size_t total;          // total length of string to parse
   221   size_t pos = 0;        // current position in string to parse
   222   size_t level = 0;      // nested levels of objects/arrays currently being processed
   223   int mode = JSON_STATE_VALUE;  // state of parser (i.e. "what's expected next?")
   224   unsigned char c;       // variable to store a single character to be processed (unsigned!)
   225   luaL_Buffer luabuf;    // Lua buffer to decode JSON string values
   226   char *cbuf;            // C buffer to decode JSON string values
   227   size_t outlen;         // maximum length or write position of C buffer
   228   long codepoint;        // decoded UTF-16 character or higher codepoint
   229   long utf16tail;        // second decoded UTF-16 character (surrogate tail)
   230   size_t arraylen;       // variable to temporarily store the array length
   231   // require string as argument and convert to C string with length information:
   232   str = luaL_checklstring(L, 1, &total);
   233   // if string contains a NULL byte, this is a syntax error
   234   if (strlen(str) != total) goto json_import_syntax_error;
   235   // stack shall contain one function argument:
   236   lua_settop(L, 1);
   237   // push objectmt onto stack position 2:
   238   json_regfetch(L, objectmt);
   239   // push arraymt onto stack position 3:
   240   json_regfetch(L, arraymt);
   241   // push table for stack swapping onto stack position 5:
   242   // (needed to avoid Lua stack overflows)
   243   lua_newtable(L);
   244   // main loop of parser:
   245   json_import_loop:
   246   // skip whitespace and store next character in variable 'c':
   247   while (c = str[pos],
   248     c == ' ' ||
   249     c == '\f' ||
   250     c == '\n' ||
   251     c == '\r' ||
   252     c == '\t' ||
   253     c == '\v'
   254   ) pos++;
   255   // NOTE: variable c needs to be unsigned in the following code
   256   // switch statement to handle certain (single) characters:
   257   switch (c) {
   258   // handle end of JSON document:
   259   case 0:
   260     // if end of JSON document was expected, then return top element of stack as result:
   261     if (mode == JSON_STATE_END) return 1;
   262     // otherwise, the JSON document was malformed:
   263     if (level == 0) {
   264       lua_pushnil(L);
   265       lua_pushliteral(L, "Empty string");
   266     } else {
   267       json_import_unexpected_eof:
   268       lua_pushnil(L);
   269       lua_pushliteral(L, "Unexpected end of JSON document");
   270     }
   271     return 2;
   272   // new JSON object or JSON array:
   273   case '{':
   274   case '[':
   275     // if an encountered JSON object is not expected here, then return an error:
   276     if (
   277       c == '{' &&
   278       mode != JSON_STATE_VALUE &&
   279       mode != JSON_STATE_OBJECT_VALUE &&
   280       mode != JSON_STATE_ARRAY_VALUE
   281     ) goto json_import_syntax_error;
   282     // if an encountered JSON array is not expected here, then return an error:
   283     if (
   284       c == '[' &&
   285       mode != JSON_STATE_VALUE &&
   286       mode != JSON_STATE_OBJECT_VALUE &&
   287       mode != JSON_STATE_ARRAY_VALUE
   288     ) goto json_import_syntax_error;
   289     // consume input character:
   290     pos++;
   291     // limit nested levels:
   292     if (level >= JSON_MAXDEPTH) {
   293       lua_pushnil(L);
   294       lua_pushfstring(L, "More than %d nested JSON levels", JSON_MAXDEPTH);
   295       return 2;
   296     }
   297     // swap Lua stack entries for previous level to swap table:
   298     // (avoids depth limitations due to Lua stack size)
   299     if (level) {
   300       lua_rawseti(L, json_import_stackswap_idx, ++stackswapidx);
   301       lua_rawseti(L, json_import_stackswap_idx, ++stackswapidx);
   302       lua_rawseti(L, json_import_stackswap_idx, ++stackswapidx);
   303     }
   304     // increment level:
   305     level++;
   306     // create JSON object or JSON array on stack:
   307     lua_newtable(L);
   308     // set metatable of JSON object or JSON array:
   309     lua_pushvalue(L, c == '{' ? json_import_objectmt_idx : json_import_arraymt_idx);
   310     lua_setmetatable(L, -2);
   311     // create internal shadow table on stack:
   312     lua_newtable(L);
   313     // register internal shadow table:
   314     lua_pushvalue(L, -1);
   315     json_setshadow(L, -3);
   316     // distinguish between JSON objects and JSON arrays:
   317     if (c == '{') {
   318       // if JSON object,
   319       // expect object key (or end of object) to follow:
   320       mode = JSON_STATE_OBJECT_KEY;
   321     } else {
   322       // if JSON array,
   323       // expect array value (or end of array) to follow:
   324       mode = JSON_STATE_ARRAY_VALUE;
   325       // add nil as key (needed to keep stack balance) and as magic to detect arrays:
   326       if (c == '[') lua_pushnil(L);
   327     }
   328     goto json_import_loop;
   329   // end of JSON object:
   330   case '}':
   331     // if end of JSON object is not expected here, then return an error:
   332     if (
   333       mode != JSON_STATE_OBJECT_KEY &&
   334       mode != JSON_STATE_OBJECT_SEPARATOR
   335     ) goto json_import_syntax_error;
   336     // jump to common code for end of JSON object and JSON array:
   337     goto json_import_close;
   338   // end of JSON array:
   339   case ']':
   340     // if end of JSON array is not expected here, then return an error:
   341     if (
   342       mode != JSON_STATE_ARRAY_VALUE &&
   343       mode != JSON_STATE_ARRAY_SEPARATOR
   344     ) goto json_import_syntax_error;
   345     // pop nil key/magic (that was needed to keep stack balance):
   346     lua_pop(L, 1);
   347     // continue with common code for end of JSON object and JSON array:
   348   // common code for end of JSON object or JSON array:
   349   json_import_close:
   350     // consume input character:
   351     pos++;
   352     // pop shadow table:
   353     lua_pop(L, 1);
   354     // check if nested:
   355     if (--level) {
   356       // if nested,
   357       // restore previous stack elements from stack swap:
   358       lua_rawgeti(L, json_import_stackswap_idx, stackswapidx--);
   359       lua_insert(L, -2);
   360       lua_rawgeti(L, json_import_stackswap_idx, stackswapidx--);
   361       lua_insert(L, -2);
   362       lua_rawgeti(L, json_import_stackswap_idx, stackswapidx--);
   363       lua_insert(L, -2);
   364       // check if outer(!) structure is an array or object:
   365       if (lua_isnil(L, -2)) {
   366         // select array value processing:
   367         mode = JSON_STATE_ARRAY_VALUE;
   368       } else {
   369         // select object value processing:
   370         mode = JSON_STATE_OBJECT_VALUE;
   371       }
   372       // store value in outer structure:
   373       goto json_import_process_value;
   374     }
   375     // if not nested, then expect end of JSON document and continue with loop:
   376     mode = JSON_STATE_END;
   377     goto json_import_loop;
   378   // key terminator:
   379   case ':':
   380     // if key terminator is not expected here, then return an error:
   381     if (mode != JSON_STATE_OBJECT_KEY_TERMINATOR)
   382       goto json_import_syntax_error;
   383     // consume input character:
   384     pos++;
   385     // expect object value to follow:
   386     mode = JSON_STATE_OBJECT_VALUE;
   387     // continue with loop:
   388     goto json_import_loop;
   389   // value terminator (NOTE: trailing comma at end of value or key-value list is tolerated by this parser)
   390   case ',':
   391     // branch according to parser state:
   392     if (mode == JSON_STATE_OBJECT_SEPARATOR) {
   393       // expect an object key to follow:
   394       mode = JSON_STATE_OBJECT_KEY;
   395     } else if (mode == JSON_STATE_ARRAY_SEPARATOR) {
   396       // expect an array value to follow:
   397       mode = JSON_STATE_ARRAY_VALUE;
   398     } else {
   399        // if value terminator is not expected here, then return an error:
   400        goto json_import_syntax_error;
   401     }
   402     // consume input character:
   403     pos++;
   404     // continue with loop:
   405     goto json_import_loop;
   406   // string literal:
   407   case '"':
   408     // consume quote character:
   409     pos++;
   410     // find last character in input string:
   411     outlen = pos;
   412     while ((c = str[outlen]) != '"') {
   413       // consume one character:
   414       outlen++;
   415       // handle unexpected end of JSON document:
   416       if (c == 0) goto json_import_unexpected_eof;
   417       // consume one extra character when encountering an escaped quote:
   418       else if (c == '\\' && str[outlen] == '"') outlen++;
   419     }
   420     // determine buffer length:
   421     outlen -= pos;
   422     // check if string is non empty:
   423     if (outlen) {
   424       // prepare buffer to decode string (with maximum possible length) and set write position to zero:
   425       cbuf = luaL_buffinitsize(L, &luabuf, outlen);
   426       outlen = 0;
   427       // loop through the characters until encountering end quote:
   428       while ((c = str[pos++]) != '"') {
   429         // NOTE: unexpected end cannot happen anymore
   430         if (c < 32 || c == 127) {
   431           // do not allow ASCII control characters:
   432           // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized
   433           //       by this parser to allow different encodings than Unicode
   434           lua_pushnil(L);
   435           lua_pushliteral(L, "Unexpected control character in JSON string");
   436           return 2;
   437         } else if (c == '\\') {
   438           // read next char after backslash escape:
   439           c = str[pos++];
   440           switch (c) {
   441           // unexpected end-of-string:
   442           case 0:
   443             goto json_import_unexpected_eof;
   444           // unescaping of quotation mark, slash, and backslash:
   445           case '"':
   446           case '/':
   447           case '\\':
   448             cbuf[outlen++] = c;
   449             break;
   450           // unescaping of backspace:
   451           case 'b': cbuf[outlen++] = '\b'; break;
   452           // unescaping of form-feed:
   453           case 'f': cbuf[outlen++] = '\f'; break;
   454           // unescaping of new-line:
   455           case 'n': cbuf[outlen++] = '\n'; break;
   456           // unescaping of carriage-return:
   457           case 'r': cbuf[outlen++] = '\r'; break;
   458           // unescaping of tabulator:
   459           case 't': cbuf[outlen++] = '\t'; break;
   460           // unescaping of UTF-16 characters
   461           case 'u':
   462             // decode 4 hex nibbles:
   463             json_import_readhex(codepoint);
   464             // handle surrogate character:
   465             if (json_utf16_surrogate(codepoint)) {
   466               // check if first surrogate is in valid range:
   467               if (json_utf16_lead(codepoint)) {
   468                 // require second surrogate:
   469                 if ((c = str[pos++]) != '\\' || (c = str[pos++]) != 'u') {
   470                   if (c == 0) goto json_import_unexpected_eof;
   471                   else goto json_import_wrong_surrogate;
   472                 }
   473                 // read 4 hex nibbles of second surrogate character:
   474                 json_import_readhex(utf16tail);
   475                 // check if second surrogate is in valid range:
   476                 if (!json_utf16_tail(utf16tail)) goto json_import_wrong_surrogate;
   477                 // calculate codepoint:
   478                 codepoint = 0x10000 + (utf16tail - 0xDC00) + (codepoint - 0xD800) * 0x400;
   479               } else {
   480                 // throw error for wrong surrogates:
   481                 json_import_wrong_surrogate:
   482                 lua_pushnil(L);
   483                 lua_pushliteral(L, "Illegal UTF-16 surrogate in JSON string escape sequence");
   484                 return 2;
   485               }
   486             }
   487             // encode as UTF-8:
   488             if (codepoint < 0x80) {
   489               cbuf[outlen++] = (char)codepoint;
   490             } else if (codepoint < 0x800) {
   491               cbuf[outlen++] = (char)(0xc0 | (codepoint >> 6));
   492               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   493             } else if (codepoint < 0x10000) {
   494               cbuf[outlen++] = (char)(0xe0 | (codepoint >> 12));
   495               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 6) & 0x3f));
   496               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   497             } else {
   498               cbuf[outlen++] = (char)(0xf0 | (codepoint >> 18));
   499               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 12) & 0x3f));
   500               cbuf[outlen++] = (char)(0x80 | ((codepoint >> 6) & 0x3f));
   501               cbuf[outlen++] = (char)(0x80 | (codepoint & 0x3f));
   502             }
   503             break;
   504           // unexpected escape sequence:
   505           default:
   506             json_import_unexpected_escape:
   507             lua_pushnil(L);
   508             lua_pushliteral(L, "Unexpected string escape sequence in JSON document");
   509             return 2;
   510           }
   511         } else {
   512           // normal character:
   513           cbuf[outlen++] = c;
   514         }
   515       }
   516       // process buffer to Lua string:
   517       luaL_pushresultsize(&luabuf, outlen);
   518     } else {
   519       // if JSON string is empty,
   520       // push empty Lua string:
   521       lua_pushliteral(L, "");
   522       // consume closing quote:
   523       pos++;
   524     }
   525     // continue with processing of decoded string:
   526     goto json_import_process_value;
   527   }
   528   // process values whose type is is not deducible from a single character:
   529   if ((c >= '0' && c <= '9') || c == '-' || c == '+') {
   530     // for numbers,
   531     // use strtod() call to parse a (double precision) floating point number:
   532     double numval;
   533     char *endptr;
   534     numval = strtod(str+pos, &endptr);
   535     // catch parsing errors:
   536     if (endptr == str+pos) goto json_import_syntax_error;
   537     // consume characters that were parsed:
   538     pos += endptr - (str+pos);
   539     // push parsed (double precision) floating point number on Lua stack:
   540     lua_pushnumber(L, numval);
   541   } else if (!strncmp(str+pos, "true", 4)) {
   542     // consume 4 input characters for "true":
   543     pos += 4;
   544     // put Lua true value onto stack:
   545     lua_pushboolean(L, 1);
   546   } else if (!strncmp(str+pos, "false", 5)) {
   547     // consume 5 input characters for "false":
   548     pos += 5;
   549     // put Lua false value onto stack:
   550     lua_pushboolean(L, 0);
   551   } else if (!strncmp(str+pos, "null", 4)) {
   552     // consume 4 input characters for "null":
   553     pos += 4;
   554     // push special null-marker onto stack:
   555     json_pushnullmark(L);
   556   } else {
   557     // all other cases are a syntax error:
   558     goto json_import_syntax_error;
   559   }
   560   // process a decoded value or key value pair (expected on top of Lua stack):
   561   json_import_process_value:
   562   switch (mode) {
   563   // an object key has been read:
   564   case JSON_STATE_OBJECT_KEY:
   565     // if an object key is not a string, then this is a syntax error:
   566     if (lua_type(L, -1) != LUA_TSTRING) goto json_import_syntax_error;
   567     // expect key terminator to follow:
   568     mode = JSON_STATE_OBJECT_KEY_TERMINATOR;
   569     // continue with loop:
   570     goto json_import_loop;
   571   // a key value pair has been read:
   572   case JSON_STATE_OBJECT_VALUE:
   573     // store key value pair in outer shadow table:
   574     lua_rawset(L, -3);
   575     // expect value terminator (or end of object) to follow:
   576     mode = JSON_STATE_OBJECT_SEPARATOR;
   577     // continue with loop:
   578     goto json_import_loop;
   579   // an array value has been read:
   580   case JSON_STATE_ARRAY_VALUE:
   581     // get current array length:
   582     arraylen = lua_rawlen(L, -3);
   583     // throw error if array would exceed INT_MAX elements:
   584     // TODO: Lua 5.3 may support more elements
   585     if (arraylen >= INT_MAX) {
   586       lua_pushnil(L);
   587       lua_pushfstring(L, "Array exceeded length of %d elements", INT_MAX);
   588     }
   589     // store value in outer shadow table:
   590     lua_rawseti(L, -3, arraylen + 1);
   591     // expect value terminator (or end of object) to follow:
   592     mode = JSON_STATE_ARRAY_SEPARATOR;
   593     // continue with loop
   594     goto json_import_loop;
   595   // a single value has been read:
   596   case JSON_STATE_VALUE:
   597     // leave value on top of stack, expect end of JSON document, and continue with loop:
   598     mode = JSON_STATE_END;
   599     goto json_import_loop;
   600   }
   601   // syntax error handling (reachable by goto statement):
   602   json_import_syntax_error:
   603   lua_pushnil(L);
   604   lua_pushliteral(L, "Syntax error in JSON document");
   605   return 2;
   606 }
   608 // gets a value or its type from a JSON document (passed as first argument)
   609 // using a path (passed as variable number of keys after the first argument):
   610 static int json_path(lua_State *L, int type_mode) {
   611   int stacktop;  // number of arguments
   612   int idx = 2;   // stack index of current argument to process
   613   // require at least one argument:
   614   luaL_checkany(L, 1);
   615   // store stack index of top of stack (number of arguments):
   616   stacktop = lua_gettop(L);
   617   // use first argument as "current value" (stored on top of stack):
   618   lua_pushvalue(L, 1);
   619   // process each "path key" (2nd argument and following arguments):
   620   while (idx <= stacktop) {
   621     // if "current value" (on top of stack) is nil, then the path cannot be walked and nil is returned:
   622     if (lua_isnil(L, -1)) return 1;
   623     // try to get shadow table of "current value":
   624     json_getshadow(L, -1);
   625     if (lua_isnil(L, -1)) {
   626       // if no shadow table is found,
   627       if (lua_type(L, -2) == LUA_TTABLE) {
   628         // and if "current value" is a table,
   629         // pop nil from stack:
   630         lua_pop(L, 1);
   631         // get "next value" using the "path key":
   632         lua_pushvalue(L, idx++);
   633         lua_gettable(L, -2);
   634       } else {
   635         // if "current value" is not a table,
   636         // then the path cannot be walked and nil (already on top of stack) is returned:
   637         return 1;
   638       }
   639     } else {
   640       // if a shadow table is found,
   641       // set "current value" to its shadow table:
   642       lua_replace(L, -2);
   643       // get "next value" using the "path key":
   644       lua_pushvalue(L, idx++);
   645       lua_rawget(L, -2);
   646     }
   647     // the "next value" replaces the "current value":
   648     lua_replace(L, -2);
   649   }
   650   if (!type_mode) {
   651     // if a value (and not its type) was requested,
   652     // check if value is the null-marker, and store nil on top of Lua stack in that case:
   653     if (json_isnullmark(L, -1)) lua_pushnil(L);
   654   } else {
   655     // if the type was requested,
   656     // check if value is the null-marker:
   657     if (json_isnullmark(L, -1)) {
   658       // if yes, store string "null" on top of Lua stack:
   659       lua_pushliteral(L, "null");
   660     } else {
   661       // otherwise,
   662       // check if metatable indicates "object" or "array":
   663       if (lua_getmetatable(L, -1)) {
   664         json_regfetch(L, objectmt);
   665         if (lua_rawequal(L, -2, -1)) {
   666           // if value has metatable for JSON objects,
   667           // return string "object":
   668           lua_pushliteral(L, "object");
   669           return 1;
   670         }
   671         json_regfetch(L, arraymt);
   672         if (lua_rawequal(L, -3, -1)) {
   673           // if value has metatable for JSON arrays,
   674           // return string "object":
   675           lua_pushliteral(L, "array");
   676           return 1;
   677         }
   678         // remove 3 metatables (one of the value, two for comparison) from stack:
   679         lua_pop(L, 3);
   680       }
   681       // otherwise, get the Lua type:
   682       lua_pushstring(L, lua_typename(L, lua_type(L, -1)));
   683     }
   684   }
   685   // return the top most value on the Lua stack:
   686   return 1;
   687 }
   689 // gets a value from a JSON document (passed as first argument)
   690 // using a path (passed as variable number of keys after the first argument):
   691 static int json_get(lua_State *L) {
   692   return json_path(L, 0);
   693 }
   695 // gets a value's type from a JSON document (passed as first argument)
   696 // using a path (passed as variable number of keys after first the argument):
   697 static int json_type(lua_State *L) {
   698   return json_path(L, 1);
   699 }
   701 // special Lua stack indicies for json_set function:
   702 #define json_set_objectmt_idx 1
   703 #define json_set_arraymt_idx 2
   705 // stack offset of arguments to json_set function:
   706 #define json_set_idxshift 2
   708 // sets a value (passed as second argument) in a JSON document (passed as first argument)
   709 // using a path (passed as variable number of keys starting at third argument):
   710 static int json_set(lua_State *L) {
   711   int stacktop;  // stack index of top of stack (after shifting)
   712   int idx;       // stack index of current argument to process
   713   // require at least three arguments:
   714   luaL_checkany(L, 1);
   715   luaL_checkany(L, 2);
   716   luaL_checkany(L, 3);
   717   // insert objectmt into stack at position 1 (shifting the arguments):
   718   json_regfetch(L, objectmt);
   719   lua_insert(L, 1);
   720   // insert arraymt into stack at position 2 (shifting the arguments):
   721   json_regfetch(L, arraymt);
   722   lua_insert(L, 2);
   723   // store stack index of top of stack:
   724   stacktop = lua_gettop(L);
   725   // use nil as initial "parent value":
   726   lua_pushnil(L);
   727   // use first argument as "current value":
   728   lua_pushvalue(L, 1 + json_set_idxshift);
   729   // set all necessary values in path:
   730   for (idx = 3 + json_set_idxshift; idx<=stacktop; idx++) {
   731     // push metatable of "current value" onto stack:
   732     if (!lua_getmetatable(L, -1)) lua_pushnil(L);
   733     // distinguish according to type of path key:
   734     switch (lua_type(L, idx)) {
   735     case LUA_TSTRING:
   736       // if path key is a string,
   737       // check if "current value" is a JSON object (or table without metatable):
   738       if (
   739         lua_rawequal(L, -1, json_set_objectmt_idx) ||
   740         (lua_isnil(L, -1) && lua_type(L, -2) == LUA_TTABLE)
   741       ) {
   742         // if "current value" is acceptable,
   743         // pop metatable and leave "current value" on top of stack:
   744         lua_pop(L, 1);
   745       } else {
   746         // if "current value" is not acceptable:
   747         // pop metatable and "current value":
   748         lua_pop(L, 2);
   749         // throw error if parent element does not exist:
   750         if (lua_isnil(L, -1)) return luaL_error(L, "Root element is not a JSON object");
   751         // push new JSON object as "current value" onto stack:
   752         json_createproxy(L);
   753         // create and register shadow table:
   754         lua_newtable(L);
   755         json_setshadow(L, -2);
   756         // set metatable of JSON object: 
   757         lua_pushvalue(L, json_set_objectmt_idx);
   758         lua_setmetatable(L, -2);
   759         // set entry in "parent value":
   760         lua_pushvalue(L, idx-1);
   761         lua_pushvalue(L, -2);
   762         lua_settable(L, -4);
   763       }
   764       break;
   765     case LUA_TNUMBER:
   766       // if path key is a number,
   767       // check if "current value" is a JSON array (or table without metatable):
   768       if (
   769         lua_rawequal(L, -1, json_set_arraymt_idx) ||
   770         (lua_isnil(L, -1) && lua_type(L, -2) == LUA_TTABLE)
   771       ) {
   772         // if "current value" is acceptable,
   773         // pop metatable and leave "current value" on top of stack:
   774         lua_pop(L, 1);
   775       } else {
   776         // if "current value" is not acceptable:
   777         // pop metatable and "current value":
   778         lua_pop(L, 2);
   779         // throw error if parent element does not exist:
   780         if (lua_isnil(L, -1)) return luaL_error(L, "Root element is not a JSON array");
   781         // push new JSON array as "current value" onto stack:
   782         json_createproxy(L);
   783         // create and register shadow table:
   784         lua_newtable(L);
   785         json_setshadow(L, -2);
   786         // set metatable of JSON array: 
   787         lua_pushvalue(L, json_set_arraymt_idx);
   788         lua_setmetatable(L, -2);
   789         // set entry in "parent value":
   790         lua_pushvalue(L, idx-1);
   791         lua_pushvalue(L, -2);
   792         lua_settable(L, -4);
   793       }
   794       break;
   795     default:
   796       return luaL_error(L, "Invalid path key of type %s", lua_typename(L, lua_type(L, idx)));
   797     }
   798     // check if last path element is being processed:
   799     if (idx == stacktop) {
   800       // if the last path element is being processed,
   801       // set last path value in "current value" container:
   802       lua_pushvalue(L, idx);
   803       lua_pushvalue(L, 2 + json_set_idxshift);
   804       lua_settable(L, -3);
   805     } else {
   806       // if the processed path element is not the last,
   807       // use old "current value" as new "parent value"
   808       lua_remove(L, -2);
   809       // push new "current value" onto stack by performing a lookup:
   810       lua_pushvalue(L, idx);
   811       lua_gettable(L, -2);
   812     }
   813   }
   814   // return first argument for convenience:
   815   lua_settop(L, 1 + json_set_idxshift);
   816   return 1;
   817 }
   819 // returns the length of a JSON array (or zero for a table without numeric keys):
   820 static int json_len(lua_State *L) {
   821   // stack shall contain one function argument:
   822   lua_settop(L, 1);
   823   // push shadow table or nil onto stack:
   824   json_getshadow(L, 1);
   825   // pop nil from stack if no shadow table has been found:
   826   if (lua_isnil(L, -1)) lua_pop(L, 1);
   827   // return length of argument or shadow table:
   828   lua_pushnumber(L, lua_rawlen(L, -1));
   829   return 1;
   830 }
   832 // __index metamethod for JSON objects and JSON arrays:
   833 static int json_index(lua_State *L) {
   834   // stack shall contain two function arguments:
   835   lua_settop(L, 2);
   836   // replace first argument with its shadow table
   837   // or throw error if no shadow table is found:
   838   json_getshadow(L, 1);
   839   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   840   lua_replace(L, 1);
   841   // use key passed as second argument to lookup value in shadow table:
   842   lua_rawget(L, 1);
   843   // if value is null-marker, then push nil onto stack:
   844   if (json_isnullmark(L, 2)) lua_pushnil(L);
   845   // return either looked up value, or nil
   846   return 1;
   847 }
   849 // __newindex metamethod for JSON objects and JSON arrays:
   850 static int json_newindex(lua_State *L) {
   851   // stack shall contain three function arguments:
   852   lua_settop(L, 3);
   853   // replace first argument with its shadow table
   854   // or throw error if no shadow table is found:
   855   json_getshadow(L, 1);
   856   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   857   lua_replace(L, 1);
   858   // second and third argument to write to shadow table:
   859   lua_rawset(L, 1);
   860   // return nothing:
   861   return 0;
   862 }
   864 // function returned as first value by json_pairs function:
   865 static int json_pairs_iterfunc(lua_State *L) {
   866   // stack shall contain two function arguments:
   867   lua_settop(L, 2);
   868   // get next key value pair from shadow table (argument 1) using previous key (argument 2)
   869   // and return nothing if there is no next pair:
   870   if (!lua_next(L, 1)) return 0;
   871   // replace null-marker with nil:
   872   if (json_isnullmark(L, -1)) {
   873     lua_pop(L, 1);
   874     lua_pushnil(L);
   875   }
   876   // return key and value (or key and nil, if null-marker was found):
   877   return 2;
   878 }
   880 // returns a triple such that 'for key, value in pairs(obj) do ... end'
   881 // iterates through all key value pairs (including JSON null values represented as Lua nil):
   882 static int json_pairs(lua_State *L) {
   883   // require one argument to function
   884   luaL_checkany(L, 1);
   885   // return triple of function json_pairs_iterfunc, shadow table of first argument, and nil:
   886   lua_pushcfunction(L, json_pairs_iterfunc);
   887   json_getshadow(L, 1);
   888   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   889   lua_pushnil(L);
   890   return 3;
   891 }
   893 // function returned as first value by json_ipairs function:
   894 static int json_ipairs_iterfunc(lua_State *L) {
   895   lua_Integer idx;
   896   // stack shall contain two function arguments:
   897   lua_settop(L, 2);
   898   // calculate new index by incrementing second argument:
   899   idx = lua_tointeger(L, 2) + 1;
   900   // do integer lookup in shadow table and store result on stack position 3:
   901   lua_rawgeti(L, 1, idx);
   902   // return nothing if there was no value:
   903   if (lua_isnil(L, 3)) return 0;
   904   // return new index and
   905   // either the looked up value if it is not equal to the null-marker
   906   // or nil instead of null-marker:
   907   lua_pushinteger(L, idx);
   908   if (json_isnullmark(L, 3)) lua_pushnil(L);
   909   else lua_pushvalue(L, 3);
   910   return 2;
   911 }
   913 // returns a triple such that 'for idx, value in ipairs(ary) do ... end'
   914 // iterates through all values (including JSON null values represented as Lua nil):
   915 static int json_ipairs(lua_State *L) {
   916   // require one argument to function
   917   luaL_checkany(L, 1);
   918   // return triple of function json_ipairs_iterfunc, shadow table of first argument, and zero:
   919   lua_pushcfunction(L, json_ipairs_iterfunc);
   920   json_getshadow(L, 1);
   921   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   922   lua_pushinteger(L, 0);
   923   return 3;
   924 }
   926 // datatype representing a table key:
   927 // (used for sorting)
   928 typedef struct {
   929   size_t length;
   930   const char *data;
   931 } json_key_t;
   933 // comparation function for table keys to be passed to qsort function:
   934 static int json_key_cmp(json_key_t *key1, json_key_t *key2) {
   935   size_t pos = 0;
   936   unsigned char c1, c2;
   937   while (1) {
   938     if (key1->length > pos) {
   939       if (key2->length > pos) {
   940         c1 = key1->data[pos];
   941         c2 = key2->data[pos];
   942         if (c1 < c2) return -1;
   943         else if (c1 > c2) return 1;
   944       } else {
   945         return 1;
   946       }
   947     } else {
   948       if (key2->length > pos) {
   949         return -1;
   950       } else {
   951         return 0;
   952       }
   953     }
   954     pos++;
   955   }
   956 }
   958 // constants for type detection of ambiguous tables:
   959 #define JSON_TABLETYPE_UNKNOWN 0
   960 #define JSON_TABLETYPE_OBJECT 1
   961 #define JSON_TABLETYPE_ARRAY 2
   963 typedef struct {
   964   int type;
   965   int pos;
   966   int count;
   967   json_key_t keys[1];  // or more
   968 } json_container_t;
   970 // special Lua stack indicies for json_export function:
   971 #define json_export_value_idx 1
   972 #define json_export_indentstring_idx 2
   973 #define json_export_objectmt_idx 3
   974 #define json_export_arraymt_idx 4
   975 #define json_export_stackswap_idx 5
   976 #define json_export_luacontainer_idx 6
   977 #define json_export_ccontainer_idx 7
   978 #define json_export_buffer_idx 8
   980 // encodes a JSON document (passed as first argument)
   981 // optionally using indentation (indentation string or true passed as second argument)
   982 static int json_export(lua_State *L) {
   983   int pretty;           // pretty printing on? (i.e. printing with indentation)
   984   luaL_Buffer buf;      // Lua buffer containing result string
   985   lua_Number num;       // number to encode
   986   char numstr[21];      // encoded number (sign, zero, point, 17 significant digits, and terminating NULL byte)
   987   const char *str;      // string to encode
   988   size_t strlen;        // length of string to encode
   989   size_t strpos ;       // position in string or position of current key
   990   unsigned char c;      // character to encode (unsigned!)
   991   char hexcode[7];      // store for unicode hex escape sequence
   992                         // NOTE: 7 bytes due to backslash, character 'u', 4 hex digits, and terminating NULL byte
   993   int tabletype;        // table type: unknown, JSON object, or JSON array
   994   size_t keycount = 0;  // number of string keys in object
   995   json_key_t *key;      // pointer to C structure containing a string key
   996   int level = 0;        // current depth level
   997   int i;                // iteration variable for level dependent repetitions
   998   int stackswapidx = 0; // elements in stack swap table
   999   int containerkey = 0; // temporarily set to 1, if a container key is being encoded
  1000   json_container_t *container = NULL; // pointer to current C struct for container information
  1001   // stack shall contain two function arguments:
  1002   lua_settop(L, 2);
  1003   // check if pretty printing (with indentation) is desired:
  1004   if (lua_toboolean(L, json_export_indentstring_idx)) {
  1005     // if yes,
  1006     // set pretty variable to 1:
  1007     pretty = 1;
  1008     // check if second argument is a boolean (true):
  1009     if (lua_isboolean(L, json_export_indentstring_idx)) {
  1010       // if yes,
  1011       // use default indentation if indentation argument is boolean true:
  1012       lua_pushliteral(L, "  ");
  1013       lua_replace(L, json_export_indentstring_idx);
  1014     } else {
  1015       // if no,
  1016       // require second argument to be a string:
  1017       luaL_checktype(L, json_export_indentstring_idx, LUA_TSTRING);
  1018     }
  1019   } else {
  1020     // if no,
  1021     // set pretty variable to 0:
  1022     pretty = 0;
  1023   }
  1024   // push objectmt onto stack position 3:
  1025   json_regfetch(L, objectmt);
  1026   // push arraymt onto stack position 4:
  1027   json_regfetch(L, arraymt);
  1028   // push table for stack swapping onto stack position 5:
  1029   lua_newtable(L);
  1030   // create placeholders on stack positions 6 through 7:
  1031   lua_settop(L, json_export_buffer_idx);
  1032   // create Lua string buffer:
  1033   luaL_buffinit(L, &buf);
  1034   // loop:
  1035   while (1) {
  1036     // if value to encode is the null-marker, then treat it the same as nil:
  1037     if (json_isnullmark(L, json_export_value_idx)) {
  1038       lua_pushnil(L);
  1039       lua_replace(L, json_export_value_idx);
  1040     }
  1041     // distinguish between different Lua types:
  1042     switch (lua_type(L, json_export_value_idx)) {
  1043     // value to encode is nil:
  1044     case LUA_TNIL:
  1045       // add string "null" to output buffer:
  1046       luaL_addstring(&buf, "null");
  1047       break;
  1048     // value to encode is of type number:
  1049     case LUA_TNUMBER:
  1050       // convert value to double precision number:
  1051       num = lua_tonumber(L, json_export_value_idx);
  1052       // throw error if number is not-a-number:
  1053       if (isnan(num)) return luaL_error(L, "JSON export not possible for NaN value");
  1054       // throw error if number is positive or negative infinity:
  1055       if (isinf(num)) return luaL_error(L, "JSON export not possible for infinite numbers");
  1056       // determine necessary precision to represent double precision floating point number:
  1057       sprintf(numstr, "%.16g", num);
  1058       if (strtod(numstr, NULL) != num) sprintf(numstr, "%.17g", num);
  1059       // add string encoding of the number to the output buffer:
  1060       luaL_addstring(&buf, numstr);
  1061       break;
  1062     // value to encode is of type boolean:
  1063     case LUA_TBOOLEAN:
  1064       // add string "true" or "false" according to boolean value:
  1065       luaL_addstring(&buf, lua_toboolean(L, json_export_value_idx) ? "true" : "false");
  1066       break;
  1067     // value to encode is of type string:
  1068     case LUA_TSTRING:
  1069       // add quoted and escaped string to output buffer:
  1070       str = lua_tolstring(L, json_export_value_idx, &strlen);
  1071       luaL_addchar(&buf, '"');
  1072       strpos = 0;
  1073       while (strpos < strlen) {
  1074         c = str[strpos++];
  1075         if (c == '"')       luaL_addstring(&buf, "\\\"");
  1076         else if (c == '\\') luaL_addstring(&buf, "\\\\");
  1077         else if (c == 127)  luaL_addstring(&buf, "\\u007F");
  1078         else if (c >= 32)   luaL_addchar(&buf, c);
  1079         else if (c == '\b') luaL_addstring(&buf, "\\b");
  1080         else if (c == '\f') luaL_addstring(&buf, "\\f");
  1081         else if (c == '\n') luaL_addstring(&buf, "\\n");
  1082         else if (c == '\r') luaL_addstring(&buf, "\\r");
  1083         else if (c == '\t') luaL_addstring(&buf, "\\t");
  1084         else if (c == '\v') luaL_addstring(&buf, "\\v");
  1085         else {
  1086           sprintf(hexcode, "\\u%04X", c);
  1087           luaL_addstring(&buf, hexcode);
  1088         }
  1089       }
  1090       luaL_addchar(&buf, '"');
  1091       break;
  1092     // value to encode is of type table (this includes JSON objects and JSON arrays):
  1093     case LUA_TTABLE:
  1094       // use table's metatable to try to determine type of table:
  1095       tabletype = JSON_TABLETYPE_UNKNOWN;
  1096       if (lua_getmetatable(L, json_export_value_idx)) {
  1097         if (lua_rawequal(L, -1, json_export_objectmt_idx)) {
  1098           tabletype = JSON_TABLETYPE_OBJECT;
  1099         } else {
  1100           if (lua_rawequal(L, -1, json_export_arraymt_idx)) {
  1101             tabletype = JSON_TABLETYPE_ARRAY;
  1102           } else {
  1103             return luaL_error(L, "JSON export not possible for tables with nonsupported metatable");
  1104           }
  1105         }
  1106         // reset stack (pop metatable from stack):
  1107         lua_pop(L, 1);
  1108       }
  1109       // replace table with its shadow table if existent:
  1110       json_getshadow(L, json_export_value_idx);
  1111       if (lua_isnil(L, -1)) lua_pop(L, 1);
  1112       else lua_replace(L, json_export_value_idx); 
  1113       // check if type of table is still undetermined
  1114       // and optionally calculate number of string keys (keycount)
  1115       // or set keycount to zero:
  1116       keycount = 0;
  1117       if (tabletype == JSON_TABLETYPE_UNKNOWN) {
  1118         // if type of table is undetermined,
  1119         // iterate over all keys:
  1120         for (lua_pushnil(L); lua_next(L, json_export_value_idx); lua_pop(L, 1)) {
  1121           switch (lua_type(L, -2)) {
  1122           case LUA_TSTRING:
  1123             // for string keys,
  1124             // increase keycount (may avoid another iteration):
  1125             keycount++;
  1126             // if type of table was unknown, then type of table is a JSON object now:
  1127             if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_OBJECT;
  1128             // if type of table was a JSON array, then the type of table is ambiguous now
  1129             // and an error is thrown:
  1130             else if (tabletype == JSON_TABLETYPE_ARRAY) goto json_export_tabletype_error;
  1131             break;
  1132           case LUA_TNUMBER:
  1133             // for numeric keys,
  1134             // if type of table was unknown, then type of table is a JSON array now:
  1135             if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_ARRAY;
  1136             // if type of table was a JSON object, then the type of table is ambiguous now
  1137             // and an error is thrown:
  1138             else if (tabletype == JSON_TABLETYPE_OBJECT) goto json_export_tabletype_error;
  1139             break;
  1140           }
  1141         }
  1142       }
  1143       // raise error if too many nested levels:
  1144       if (level >= JSON_MAXDEPTH) {
  1145         return luaL_error(L, "More than %d nested JSON levels", JSON_MAXDEPTH);
  1146       }
  1147       // store previous container information (if existent) on stack swap
  1148       // and increase level variable:
  1149       if (level++) {
  1150         lua_pushvalue(L, json_export_luacontainer_idx);
  1151         lua_rawseti(L, json_export_stackswap_idx, ++stackswapidx);
  1152         lua_pushvalue(L, json_export_ccontainer_idx);
  1153         lua_rawseti(L, json_export_stackswap_idx, ++stackswapidx);
  1154       }
  1155       // use value as current container:
  1156       lua_pushvalue(L, json_export_value_idx);
  1157       lua_replace(L, json_export_luacontainer_idx);
  1158       // distinguish between JSON objects and JSON arrays:
  1159       switch (tabletype) {
  1160       // JSON object:
  1161       case JSON_TABLETYPE_OBJECT:
  1162         // calculate count of string keys unless it has been calculated before:
  1163         if (!keycount) {
  1164           for (lua_pushnil(L); lua_next(L, json_export_luacontainer_idx); lua_pop(L, 1)) {
  1165             if (lua_type(L, -2) == LUA_TSTRING) keycount++;
  1166           }
  1167         }
  1168         // allocate memory for C structure containing string keys and container iteration state:
  1169         container = lua_newuserdata(L, sizeof(json_container_t) + (keycount-1) * sizeof(json_key_t));
  1170         // store reference to C structure on designated stack position:
  1171         lua_replace(L, json_export_ccontainer_idx);
  1172         // initialize C structure for container state:
  1173         container->type = JSON_TABLETYPE_OBJECT;
  1174         container->count = keycount;
  1175         container->pos = 0;
  1176         // check if object contains any keys:
  1177         if (keycount) {
  1178           // if yes,
  1179           // copy all string keys to the C structure (and reset container->pos again):
  1180           for (lua_pushnil(L); lua_next(L, json_export_luacontainer_idx); lua_pop(L, 1)) {
  1181             if (lua_type(L, -2) == LUA_TSTRING) {
  1182               json_key_t *key = &container->keys[container->pos++];
  1183               key->data = lua_tolstring(L, -2, &key->length);
  1184             }
  1185           }
  1186           container->pos = 0;
  1187           // sort C array using quicksort:
  1188           qsort(container->keys, keycount, sizeof(json_key_t), (void *)json_key_cmp);
  1189         }
  1190         // add opening bracket to output buffer:
  1191         luaL_addchar(&buf, '{');
  1192         break;
  1193       // JSON array:
  1194       case JSON_TABLETYPE_ARRAY:
  1195         // allocate memory for C structure for container iteration state:
  1196         container = lua_newuserdata(L, sizeof(json_container_t) - sizeof(json_key_t));
  1197         // store reference to C structure on designated stack position:
  1198         lua_replace(L, json_export_ccontainer_idx);
  1199         // initialize C structure for container state:
  1200         container->type = JSON_TABLETYPE_ARRAY;
  1201         container->pos = 0;
  1202         // add opening bracket to output buffer:
  1203         luaL_addchar(&buf, '[');
  1204         break;
  1205       default:
  1206         // throw error if table type is unknown:
  1207         json_export_tabletype_error:
  1208         return luaL_error(L, "JSON export not possible for ambiguous table (cannot decide whether it is an object or array)");
  1209       }
  1210       break;
  1211     default:
  1212     // all other datatypes are considered an error:
  1213     return luaL_error(L, "JSON export not possible for values of type \"%s\"", lua_typename(L, lua_type(L, json_export_value_idx)));
  1214     }
  1215     // check if a container is being processed:
  1216     if (container) {
  1217       // if yes,
  1218       // execute code for container iteration:
  1219       json_export_container:
  1220       // distinguish between JSON objects and JSON arrays:
  1221       switch (container->type) {
  1222       // JSON object:
  1223       case JSON_TABLETYPE_OBJECT:
  1224         // finish iteration if all string keys have been processed:
  1225         if (container->pos == container->count) goto json_export_close;
  1226         // push current string key on top of stack:
  1227         key = &container->keys[container->pos];
  1228         lua_pushlstring(L, key->data, key->length);
  1229         // check if the key has already been exported:
  1230         if (!containerkey) {
  1231           // if no,
  1232           // add a comma to the output buffer if necessary:
  1233           if (container->pos) luaL_addchar(&buf, ',');
  1234           // set containerkey variable to true:
  1235           containerkey = 1;
  1236         } else {
  1237           // if a key has already been exported,
  1238           // add a colon to the output buffer:
  1239           luaL_addchar(&buf, ':');
  1240           // add a space to the output buffer for pretty results:
  1241           if (pretty) luaL_addchar(&buf, ' ');
  1242           // replace string key on top of stack with corresponding value:
  1243           lua_rawget(L, json_export_luacontainer_idx);
  1244           // reset containerkey variable
  1245           containerkey = 0;
  1246           // increase number of processed key value pairs:
  1247           container->pos++;
  1248         }
  1249         // store key or value on top of stack in designated stack position:
  1250         lua_replace(L, json_export_value_idx);
  1251         break;
  1252       // JSON array:
  1253       case JSON_TABLETYPE_ARRAY:
  1254         // store next value in designated stack position:
  1255         lua_rawgeti(L, json_export_luacontainer_idx, container->pos+1);
  1256         lua_replace(L, json_export_value_idx);
  1257         // finish iteration if value is nil:
  1258         if (lua_isnil(L, json_export_value_idx)) goto json_export_close;
  1259         // add a comma to the output buffer if necessary:
  1260         if (container->pos) luaL_addchar(&buf, ',');
  1261         // increase number of processed values:
  1262         container->pos++;
  1263         break;
  1264       // common code for closing JSON objects or JSON arrays:
  1265       json_export_close:
  1266         // decrement level variable:
  1267         level--;
  1268         // handle indentation for pretty results:
  1269         if (pretty && container->pos) {
  1270           luaL_addchar(&buf, '\n');
  1271           for (i=0; i<level; i++) {
  1272             lua_pushvalue(L, json_export_indentstring_idx);
  1273             luaL_addvalue(&buf);
  1274           }
  1275         }
  1276         // add closing bracket to output buffer:
  1277         luaL_addchar(&buf, container->type == JSON_TABLETYPE_OBJECT ? '}' : ']');
  1278         // finish export if last level has been closed:
  1279         if (!level) goto json_export_finish;
  1280         // otherwise,
  1281         // recall previous container information from stack swap
  1282         // and set C pointer to corresponding C struct:
  1283         lua_rawgeti(L, json_export_stackswap_idx, stackswapidx--);
  1284         lua_replace(L, json_export_ccontainer_idx);
  1285         container = lua_touserdata(L, json_export_ccontainer_idx);
  1286         lua_rawgeti(L, json_export_stackswap_idx, stackswapidx--);
  1287         lua_replace(L, json_export_luacontainer_idx);
  1288         // repeat code for container iteration:
  1289         goto json_export_container;
  1290       }
  1291       // handle indentation for pretty results:
  1292       if (pretty && (containerkey || container->type == JSON_TABLETYPE_ARRAY)) {
  1293         luaL_addchar(&buf, '\n');
  1294         for (i=0; i<level; i++) {
  1295           lua_pushvalue(L, json_export_indentstring_idx);
  1296           luaL_addvalue(&buf);
  1297         }
  1298       }
  1299     } else {
  1300       // if no container is being processed,
  1301       // finish export:
  1302       json_export_finish:
  1303       // for pretty results, add final newline character if outermost container is processed:
  1304       if (pretty) luaL_addchar(&buf, '\n');
  1305       // create and return Lua string from buffer contents
  1306       luaL_pushresult(&buf);
  1307       return 1;
  1308     }
  1309   }
  1310 }
  1312 // functions in library module:
  1313 static const struct luaL_Reg json_module_functions[] = {
  1314   {"object", json_object},
  1315   {"array",  json_array},
  1316   {"import", json_import},
  1317   {"export", json_export},
  1318   {"get",    json_get},
  1319   {"type",   json_type},
  1320   {"set",    json_set},
  1321   {NULL, NULL}
  1322 };
  1324 // metamethods for JSON objects, JSON arrays, and unknown JSON collections (object or array):
  1325 static const struct luaL_Reg json_metatable_functions[] = {
  1326   {"__len", json_len},
  1327   {"__index", json_index},
  1328   {"__newindex", json_newindex},
  1329   {"__pairs", json_pairs},
  1330   {"__ipairs", json_ipairs},
  1331   {"__tostring", json_export},
  1332   {NULL, NULL}
  1333 };
  1335 // metamethods for JSON null marker:
  1336 static const struct luaL_Reg json_nullmark_metamethods[] = {
  1337   {"__tostring", json_nullmark_tostring},
  1338   {NULL, NULL}
  1339 };
  1341 // initializes json library:
  1342 int luaopen_json(lua_State *L) {
  1343   // empty stack:
  1344   lua_settop(L, 0);
  1345   // push library module onto stack position 1:
  1346   lua_newtable(L);
  1347   // register library functions:
  1348   luaL_setfuncs(L, json_module_functions, 0);
  1349   // create and store objectmt:
  1350   lua_newtable(L);
  1351   luaL_setfuncs(L, json_metatable_functions, 0);
  1352   json_regstore(L, objectmt);
  1353   // create and store arraymt:
  1354   lua_newtable(L);
  1355   luaL_setfuncs(L, json_metatable_functions, 0);
  1356   json_regstore(L, arraymt);
  1357   // set metatable of null marker and make it available through library module:
  1358   json_pushnullmark(L);
  1359   lua_newtable(L);
  1360   luaL_setfuncs(L, json_nullmark_metamethods, 0);
  1361   lua_setmetatable(L, -2);
  1362   lua_setfield(L, 1, "null");
  1363   // return library module (that's expected on top of stack):
  1364   return 1;
  1365 }
