webmcp
view libraries/json/json.c @ 194:654ddbcc49d0
Bugfix in autodoc.lua; Added documentation for JSON library; json.import(...) returns json.null for "null" on top-level
| author | jbe | 
|---|---|
| date | Mon Aug 11 17:38:12 2014 +0200 (2014-08-11) | 
| parents | 0014a7c22013 | 
| children | 9fd7e1bf9fe3 | 
 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 two arguments:
   714   luaL_checkany(L, 1);
   715   luaL_checkany(L, 2);
   716   // insert objectmt into stack at position 1 (shifting the arguments):
   717   json_regfetch(L, objectmt);
   718   lua_insert(L, 1);
   719   // insert arraymt into stack at position 2 (shifting the arguments):
   720   json_regfetch(L, arraymt);
   721   lua_insert(L, 2);
   722   // store stack index of top of stack:
   723   stacktop = lua_gettop(L);
   724   // use nil as initial "parent value":
   725   lua_pushnil(L);
   726   // use first argument as "current value":
   727   lua_pushvalue(L, 1 + json_set_idxshift);
   728   // set all necessary values in path:
   729   for (idx = 3 + json_set_idxshift; idx<=stacktop; idx++) {
   730     // push metatable of "current value" onto stack:
   731     if (!lua_getmetatable(L, -1)) lua_pushnil(L);
   732     // distinguish according to type of path key:
   733     switch (lua_type(L, idx)) {
   734     case LUA_TSTRING:
   735       // if path key is a string,
   736       // check if "current value" is a JSON object (or table without metatable):
   737       if (
   738         lua_rawequal(L, -1, json_set_objectmt_idx) ||
   739         (lua_isnil(L, -1) && lua_type(L, -2) == LUA_TTABLE)
   740       ) {
   741         // if "current value" is acceptable,
   742         // pop metatable and leave "current value" on top of stack:
   743         lua_pop(L, 1);
   744       } else {
   745         // if "current value" is not acceptable:
   746         // pop metatable and "current value":
   747         lua_pop(L, 2);
   748         // throw error if parent element does not exist:
   749         if (lua_isnil(L, -1)) return luaL_error(L, "Root element is not a JSON object");
   750         // push new JSON object as "current value" onto stack:
   751         json_createproxy(L);
   752         // create and register shadow table:
   753         lua_newtable(L);
   754         json_setshadow(L, -2);
   755         // set metatable of JSON object: 
   756         lua_pushvalue(L, json_set_objectmt_idx);
   757         lua_setmetatable(L, -2);
   758         // set entry in "parent value":
   759         lua_pushvalue(L, idx-1);
   760         lua_pushvalue(L, -2);
   761         lua_settable(L, -4);
   762       }
   763       break;
   764     case LUA_TNUMBER:
   765       // if path key is a number,
   766       // check if "current value" is a JSON array (or table without metatable):
   767       if (
   768         lua_rawequal(L, -1, json_set_arraymt_idx) ||
   769         (lua_isnil(L, -1) && lua_type(L, -2) == LUA_TTABLE)
   770       ) {
   771         // if "current value" is acceptable,
   772         // pop metatable and leave "current value" on top of stack:
   773         lua_pop(L, 1);
   774       } else {
   775         // if "current value" is not acceptable:
   776         // pop metatable and "current value":
   777         lua_pop(L, 2);
   778         // throw error if parent element does not exist:
   779         if (lua_isnil(L, -1)) return luaL_error(L, "Root element is not a JSON array");
   780         // push new JSON array as "current value" onto stack:
   781         json_createproxy(L);
   782         // create and register shadow table:
   783         lua_newtable(L);
   784         json_setshadow(L, -2);
   785         // set metatable of JSON array: 
   786         lua_pushvalue(L, json_set_arraymt_idx);
   787         lua_setmetatable(L, -2);
   788         // set entry in "parent value":
   789         lua_pushvalue(L, idx-1);
   790         lua_pushvalue(L, -2);
   791         lua_settable(L, -4);
   792       }
   793       break;
   794     default:
   795       return luaL_error(L, "Invalid path key of type %s", lua_typename(L, lua_type(L, idx)));
   796     }
   797     // check if last path element is being processed:
   798     if (idx == stacktop) {
   799       // if the last path element is being processed,
   800       // set last path value in "current value" container:
   801       lua_pushvalue(L, idx);
   802       lua_pushvalue(L, 2 + json_set_idxshift);
   803       lua_settable(L, -3);
   804     } else {
   805       // if the processed path element is not the last,
   806       // use old "current value" as new "parent value"
   807       lua_remove(L, -2);
   808       // push new "current value" onto stack by performing a lookup:
   809       lua_pushvalue(L, idx);
   810       lua_gettable(L, -2);
   811     }
   812   }
   813   // return first argument for convenience:
   814   lua_settop(L, 1 + json_set_idxshift);
   815   return 1;
   816 }
   818 // returns the length of a JSON array (or zero for a table without numeric keys):
   819 static int json_len(lua_State *L) {
   820   // stack shall contain one function argument:
   821   lua_settop(L, 1);
   822   // push shadow table or nil onto stack:
   823   json_getshadow(L, 1);
   824   // pop nil from stack if no shadow table has been found:
   825   if (lua_isnil(L, -1)) lua_pop(L, 1);
   826   // return length of argument or shadow table:
   827   lua_pushnumber(L, lua_rawlen(L, -1));
   828   return 1;
   829 }
   831 // __index metamethod for JSON objects and JSON arrays:
   832 static int json_index(lua_State *L) {
   833   // stack shall contain two function arguments:
   834   lua_settop(L, 2);
   835   // replace first argument with its shadow table
   836   // or throw error if no shadow table is found:
   837   json_getshadow(L, 1);
   838   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   839   lua_replace(L, 1);
   840   // use key passed as second argument to lookup value in shadow table:
   841   lua_rawget(L, 1);
   842   // if value is null-marker, then push nil onto stack:
   843   if (json_isnullmark(L, 2)) lua_pushnil(L);
   844   // return either looked up value, or nil
   845   return 1;
   846 }
   848 // __newindex metamethod for JSON objects and JSON arrays:
   849 static int json_newindex(lua_State *L) {
   850   // stack shall contain three function arguments:
   851   lua_settop(L, 3);
   852   // replace first argument with its shadow table
   853   // or throw error if no shadow table is found:
   854   json_getshadow(L, 1);
   855   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   856   lua_replace(L, 1);
   857   // second and third argument to write to shadow table:
   858   lua_rawset(L, 1);
   859   // return nothing:
   860   return 0;
   861 }
   863 // function returned as first value by json_pairs function:
   864 static int json_pairs_iterfunc(lua_State *L) {
   865   // stack shall contain two function arguments:
   866   lua_settop(L, 2);
   867   // replace first argument with its shadow table
   868   // or throw error if no shadow table is found:
   869   json_getshadow(L, 1);
   870   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   871   lua_replace(L, 1);
   872   // get next key value pair from shadow table (using previous key from argument 2)
   873   // and return nothing if there is no next pair:
   874   if (!lua_next(L, 1)) return 0;
   875   // replace null-marker with nil:
   876   if (json_isnullmark(L, -1)) {
   877     lua_pop(L, 1);
   878     lua_pushnil(L);
   879   }
   880   // return key and value (or key and nil, if null-marker was found):
   881   return 2;
   882 }
   884 // returns a triple such that 'for key, value in pairs(obj) do ... end'
   885 // iterates through all key value pairs (including JSON null values represented as Lua nil):
   886 static int json_pairs(lua_State *L) {
   887   // require one argument to function
   888   luaL_checkany(L, 1);
   889   // return triple of function json_pairs_iterfunc, first argument, and nil:
   890   lua_pushcfunction(L, json_pairs_iterfunc);
   891   lua_pushvalue(L, 1);
   892   lua_pushnil(L);
   893   return 3;
   894 }
   896 // function returned as first value by json_ipairs function:
   897 static int json_ipairs_iterfunc(lua_State *L) {
   898   lua_Integer idx;
   899   // stack shall contain two function arguments:
   900   lua_settop(L, 2);
   901   // calculate new index by incrementing second argument:
   902   idx = lua_tointeger(L, 2) + 1;
   903   // push shadow table onto stack position 3
   904   // or throw error if no shadow table is found:
   905   json_getshadow(L, 1);
   906   if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
   907   // do integer lookup in shadow table and store result on stack position 4:
   908   lua_rawgeti(L, 3, idx);
   909   // return nothing if there was no value:
   910   if (lua_isnil(L, 4)) return 0;
   911   // return new index and
   912   // either the looked up value if it is not equal to the null-marker
   913   // or nil instead of null-marker:
   914   lua_pushinteger(L, idx);
   915   if (json_isnullmark(L, 4)) lua_pushnil(L);
   916   else lua_pushvalue(L, 4);
   917   return 2;
   918 }
   920 // returns a triple such that 'for idx, value in ipairs(ary) do ... end'
   921 // iterates through all values (including JSON null values represented as Lua nil):
   922 static int json_ipairs(lua_State *L) {
   923   // require one argument to function
   924   luaL_checkany(L, 1);
   925   // return triple of function json_ipairs_iterfunc, first argument, and zero:
   926   lua_pushcfunction(L, json_ipairs_iterfunc);
   927   lua_pushvalue(L, 1);
   928   lua_pushinteger(L, 0);
   929   return 3;
   930 }
   932 // datatype representing a table key:
   933 // (used for sorting)
   934 typedef struct {
   935   size_t length;
   936   const char *data;
   937 } json_key_t;
   939 // comparation function for table keys to be passed to qsort function:
   940 static int json_key_cmp(json_key_t *key1, json_key_t *key2) {
   941   size_t pos = 0;
   942   unsigned char c1, c2;
   943   while (1) {
   944     if (key1->length > pos) {
   945       if (key2->length > pos) {
   946         c1 = key1->data[pos];
   947         c2 = key2->data[pos];
   948         if (c1 < c2) return -1;
   949         else if (c1 > c2) return 1;
   950       } else {
   951         return 1;
   952       }
   953     } else {
   954       if (key2->length > pos) {
   955         return -1;
   956       } else {
   957         return 0;
   958       }
   959     }
   960     pos++;
   961   }
   962 }
   964 // constants for type detection of ambiguous tables:
   965 #define JSON_TABLETYPE_UNKNOWN 0
   966 #define JSON_TABLETYPE_OBJECT 1
   967 #define JSON_TABLETYPE_ARRAY 2
   969 typedef struct {
   970   int type;
   971   int pos;
   972   int count;
   973   json_key_t keys[1];  // or more
   974 } json_container_t;
   976 // special Lua stack indicies for json_export function:
   977 #define json_export_value_idx 1
   978 #define json_export_indentstring_idx 2
   979 #define json_export_objectmt_idx 3
   980 #define json_export_arraymt_idx 4
   981 #define json_export_stackswap_idx 5
   982 #define json_export_luacontainer_idx 6
   983 #define json_export_ccontainer_idx 7
   984 #define json_export_buffer_idx 8
   986 // encodes a JSON document (passed as first argument)
   987 // optionally using indentation (indentation string or true passed as second argument)
   988 static int json_export(lua_State *L) {
   989   int pretty;           // pretty printing on? (i.e. printing with indentation)
   990   luaL_Buffer buf;      // Lua buffer containing result string
   991   lua_Number num;       // number to encode
   992   char numstr[21];      // encoded number (sign, zero, point, 17 significant digits, and terminating NULL byte)
   993   const char *str;      // string to encode
   994   size_t strlen;        // length of string to encode
   995   size_t strpos ;       // position in string or position of current key
   996   unsigned char c;      // character to encode (unsigned!)
   997   char hexcode[7];      // store for unicode hex escape sequence
   998                         // NOTE: 7 bytes due to backslash, character 'u', 4 hex digits, and terminating NULL byte
   999   int tabletype;        // table type: unknown, JSON object, or JSON array
  1000   size_t keycount = 0;  // number of string keys in object
  1001   json_key_t *key;      // pointer to C structure containing a string key
  1002   int level = 0;        // current depth level
  1003   int i;                // iteration variable for level dependent repetitions
  1004   int stackswapidx = 0; // elements in stack swap table
  1005   int containerkey = 0; // temporarily set to 1, if a container key is being encoded
  1006   json_container_t *container = NULL; // pointer to current C struct for container information
  1007   // stack shall contain two function arguments:
  1008   lua_settop(L, 2);
  1009   // check if pretty printing (with indentation) is desired:
  1010   if (lua_toboolean(L, json_export_indentstring_idx)) {
  1011     // if yes,
  1012     // set pretty variable to 1:
  1013     pretty = 1;
  1014     // check if second argument is a boolean (true):
  1015     if (lua_isboolean(L, json_export_indentstring_idx)) {
  1016       // if yes,
  1017       // use default indentation if indentation argument is boolean true:
  1018       lua_pushliteral(L, "  ");
  1019       lua_replace(L, json_export_indentstring_idx);
  1020     } else {
  1021       // if no,
  1022       // require second argument to be a string:
  1023       luaL_checktype(L, json_export_indentstring_idx, LUA_TSTRING);
  1024     }
  1025   } else {
  1026     // if no,
  1027     // set pretty variable to 0:
  1028     pretty = 0;
  1029   }
  1030   // push objectmt onto stack position 3:
  1031   json_regfetch(L, objectmt);
  1032   // push arraymt onto stack position 4:
  1033   json_regfetch(L, arraymt);
  1034   // push table for stack swapping onto stack position 5:
  1035   lua_newtable(L);
  1036   // create placeholders on stack positions 6 through 7:
  1037   lua_settop(L, json_export_buffer_idx);
  1038   // create Lua string buffer:
  1039   luaL_buffinit(L, &buf);
  1040   // loop:
  1041   while (1) {
  1042     // if value to encode is the null-marker, then treat it the same as nil:
  1043     if (json_isnullmark(L, json_export_value_idx)) {
  1044       lua_pushnil(L);
  1045       lua_replace(L, json_export_value_idx);
  1046     }
  1047     // distinguish between different Lua types:
  1048     switch (lua_type(L, json_export_value_idx)) {
  1049     // value to encode is nil:
  1050     case LUA_TNIL:
  1051       // add string "null" to output buffer:
  1052       luaL_addstring(&buf, "null");
  1053       break;
  1054     // value to encode is of type number:
  1055     case LUA_TNUMBER:
  1056       // convert value to double precision number:
  1057       num = lua_tonumber(L, json_export_value_idx);
  1058       // throw error if number is not-a-number:
  1059       if (isnan(num)) return luaL_error(L, "JSON export not possible for NaN value");
  1060       // throw error if number is positive or negative infinity:
  1061       if (isinf(num)) return luaL_error(L, "JSON export not possible for infinite numbers");
  1062       // determine necessary precision to represent double precision floating point number:
  1063       sprintf(numstr, "%.16g", num);
  1064       if (strtod(numstr, NULL) != num) sprintf(numstr, "%.17g", num);
  1065       // add string encoding of the number to the output buffer:
  1066       luaL_addstring(&buf, numstr);
  1067       break;
  1068     // value to encode is of type boolean:
  1069     case LUA_TBOOLEAN:
  1070       // add string "true" or "false" according to boolean value:
  1071       luaL_addstring(&buf, lua_toboolean(L, json_export_value_idx) ? "true" : "false");
  1072       break;
  1073     // value to encode is of type string:
  1074     case LUA_TSTRING:
  1075       // add quoted and escaped string to output buffer:
  1076       str = lua_tolstring(L, json_export_value_idx, &strlen);
  1077       luaL_addchar(&buf, '"');
  1078       strpos = 0;
  1079       while (strpos < strlen) {
  1080         c = str[strpos++];
  1081         if (c == '"')       luaL_addstring(&buf, "\\\"");
  1082         else if (c == '\\') luaL_addstring(&buf, "\\\\");
  1083         else if (c == 127)  luaL_addstring(&buf, "\\u007F");
  1084         else if (c >= 32)   luaL_addchar(&buf, c);
  1085         else if (c == '\b') luaL_addstring(&buf, "\\b");
  1086         else if (c == '\f') luaL_addstring(&buf, "\\f");
  1087         else if (c == '\n') luaL_addstring(&buf, "\\n");
  1088         else if (c == '\r') luaL_addstring(&buf, "\\r");
  1089         else if (c == '\t') luaL_addstring(&buf, "\\t");
  1090         else if (c == '\v') luaL_addstring(&buf, "\\v");
  1091         else {
  1092           sprintf(hexcode, "\\u%04X", c);
  1093           luaL_addstring(&buf, hexcode);
  1094         }
  1095       }
  1096       luaL_addchar(&buf, '"');
  1097       break;
  1098     // value to encode is of type table (this includes JSON objects and JSON arrays):
  1099     case LUA_TTABLE:
  1100       // use table's metatable to try to determine type of table:
  1101       tabletype = JSON_TABLETYPE_UNKNOWN;
  1102       if (lua_getmetatable(L, json_export_value_idx)) {
  1103         if (lua_rawequal(L, -1, json_export_objectmt_idx)) {
  1104           tabletype = JSON_TABLETYPE_OBJECT;
  1105         } else {
  1106           if (lua_rawequal(L, -1, json_export_arraymt_idx)) {
  1107             tabletype = JSON_TABLETYPE_ARRAY;
  1108           } else {
  1109             return luaL_error(L, "JSON export not possible for tables with nonsupported metatable");
  1110           }
  1111         }
  1112         // reset stack (pop metatable from stack):
  1113         lua_pop(L, 1);
  1114       }
  1115       // replace table with its shadow table if existent:
  1116       json_getshadow(L, json_export_value_idx);
  1117       if (lua_isnil(L, -1)) lua_pop(L, 1);
  1118       else lua_replace(L, json_export_value_idx); 
  1119       // check if type of table is still undetermined
  1120       // and optionally calculate number of string keys (keycount)
  1121       // or set keycount to zero:
  1122       keycount = 0;
  1123       if (tabletype == JSON_TABLETYPE_UNKNOWN) {
  1124         // if type of table is undetermined,
  1125         // iterate over all keys:
  1126         for (lua_pushnil(L); lua_next(L, json_export_value_idx); lua_pop(L, 1)) {
  1127           switch (lua_type(L, -2)) {
  1128           case LUA_TSTRING:
  1129             // for string keys,
  1130             // increase keycount (may avoid another iteration):
  1131             keycount++;
  1132             // if type of table was unknown, then type of table is a JSON object now:
  1133             if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_OBJECT;
  1134             // if type of table was a JSON array, then the type of table is ambiguous now
  1135             // and an error is thrown:
  1136             else if (tabletype == JSON_TABLETYPE_ARRAY) goto json_export_tabletype_error;
  1137             break;
  1138           case LUA_TNUMBER:
  1139             // for numeric keys,
  1140             // if type of table was unknown, then type of table is a JSON array now:
  1141             if (tabletype == JSON_TABLETYPE_UNKNOWN) tabletype = JSON_TABLETYPE_ARRAY;
  1142             // if type of table was a JSON object, then the type of table is ambiguous now
  1143             // and an error is thrown:
  1144             else if (tabletype == JSON_TABLETYPE_OBJECT) goto json_export_tabletype_error;
  1145             break;
  1146           }
  1147         }
  1148       }
  1149       // raise error if too many nested levels:
  1150       if (level >= JSON_MAXDEPTH) {
  1151         return luaL_error(L, "More than %d nested JSON levels", JSON_MAXDEPTH);
  1152       }
  1153       // store previous container information (if existent) on stack swap
  1154       // and increase level variable:
  1155       if (level++) {
  1156         lua_pushvalue(L, json_export_luacontainer_idx);
  1157         lua_rawseti(L, json_export_stackswap_idx, ++stackswapidx);
  1158         lua_pushvalue(L, json_export_ccontainer_idx);
  1159         lua_rawseti(L, json_export_stackswap_idx, ++stackswapidx);
  1160       }
  1161       // use value as current container:
  1162       lua_pushvalue(L, json_export_value_idx);
  1163       lua_replace(L, json_export_luacontainer_idx);
  1164       // distinguish between JSON objects and JSON arrays:
  1165       switch (tabletype) {
  1166       // JSON object:
  1167       case JSON_TABLETYPE_OBJECT:
  1168         // calculate count of string keys unless it has been calculated before:
  1169         if (!keycount) {
  1170           for (lua_pushnil(L); lua_next(L, json_export_luacontainer_idx); lua_pop(L, 1)) {
  1171             if (lua_type(L, -2) == LUA_TSTRING) keycount++;
  1172           }
  1173         }
  1174         // allocate memory for C structure containing string keys and container iteration state:
  1175         container = lua_newuserdata(L, sizeof(json_container_t) + (keycount-1) * sizeof(json_key_t));
  1176         // store reference to C structure on designated stack position:
  1177         lua_replace(L, json_export_ccontainer_idx);
  1178         // initialize C structure for container state:
  1179         container->type = JSON_TABLETYPE_OBJECT;
  1180         container->count = keycount;
  1181         container->pos = 0;
  1182         // check if object contains any keys:
  1183         if (keycount) {
  1184           // if yes,
  1185           // copy all string keys to the C structure (and reset container->pos again):
  1186           for (lua_pushnil(L); lua_next(L, json_export_luacontainer_idx); lua_pop(L, 1)) {
  1187             if (lua_type(L, -2) == LUA_TSTRING) {
  1188               json_key_t *key = &container->keys[container->pos++];
  1189               key->data = lua_tolstring(L, -2, &key->length);
  1190             }
  1191           }
  1192           container->pos = 0;
  1193           // sort C array using quicksort:
  1194           qsort(container->keys, keycount, sizeof(json_key_t), (void *)json_key_cmp);
  1195         }
  1196         // add opening bracket to output buffer:
  1197         luaL_addchar(&buf, '{');
  1198         break;
  1199       // JSON array:
  1200       case JSON_TABLETYPE_ARRAY:
  1201         // allocate memory for C structure for container iteration state:
  1202         container = lua_newuserdata(L, sizeof(json_container_t) - sizeof(json_key_t));
  1203         // store reference to C structure on designated stack position:
  1204         lua_replace(L, json_export_ccontainer_idx);
  1205         // initialize C structure for container state:
  1206         container->type = JSON_TABLETYPE_ARRAY;
  1207         container->pos = 0;
  1208         // add opening bracket to output buffer:
  1209         luaL_addchar(&buf, '[');
  1210         break;
  1211       default:
  1212         // throw error if table type is unknown:
  1213         json_export_tabletype_error:
  1214         return luaL_error(L, "JSON export not possible for ambiguous table (cannot decide whether it is an object or array)");
  1215       }
  1216       break;
  1217     default:
  1218     // all other datatypes are considered an error:
  1219     return luaL_error(L, "JSON export not possible for values of type \"%s\"", lua_typename(L, lua_type(L, json_export_value_idx)));
  1220     }
  1221     // check if a container is being processed:
  1222     if (container) {
  1223       // if yes,
  1224       // execute code for container iteration:
  1225       json_export_container:
  1226       // distinguish between JSON objects and JSON arrays:
  1227       switch (container->type) {
  1228       // JSON object:
  1229       case JSON_TABLETYPE_OBJECT:
  1230         // finish iteration if all string keys have been processed:
  1231         if (container->pos == container->count) goto json_export_close;
  1232         // push current string key on top of stack:
  1233         key = &container->keys[container->pos];
  1234         lua_pushlstring(L, key->data, key->length);
  1235         // check if the key has already been exported:
  1236         if (!containerkey) {
  1237           // if no,
  1238           // add a comma to the output buffer if necessary:
  1239           if (container->pos) luaL_addchar(&buf, ',');
  1240           // set containerkey variable to true:
  1241           containerkey = 1;
  1242         } else {
  1243           // if a key has already been exported,
  1244           // add a colon to the output buffer:
  1245           luaL_addchar(&buf, ':');
  1246           // add a space to the output buffer for pretty results:
  1247           if (pretty) luaL_addchar(&buf, ' ');
  1248           // replace string key on top of stack with corresponding value:
  1249           lua_rawget(L, json_export_luacontainer_idx);
  1250           // reset containerkey variable
  1251           containerkey = 0;
  1252           // increase number of processed key value pairs:
  1253           container->pos++;
  1254         }
  1255         // store key or value on top of stack in designated stack position:
  1256         lua_replace(L, json_export_value_idx);
  1257         break;
  1258       // JSON array:
  1259       case JSON_TABLETYPE_ARRAY:
  1260         // store next value in designated stack position:
  1261         lua_rawgeti(L, json_export_luacontainer_idx, container->pos+1);
  1262         lua_replace(L, json_export_value_idx);
  1263         // finish iteration if value is nil:
  1264         if (lua_isnil(L, json_export_value_idx)) goto json_export_close;
  1265         // add a comma to the output buffer if necessary:
  1266         if (container->pos) luaL_addchar(&buf, ',');
  1267         // increase number of processed values:
  1268         container->pos++;
  1269         break;
  1270       // common code for closing JSON objects or JSON arrays:
  1271       json_export_close:
  1272         // decrement level variable:
  1273         level--;
  1274         // handle indentation for pretty results:
  1275         if (pretty && container->pos) {
  1276           luaL_addchar(&buf, '\n');
  1277           for (i=0; i<level; i++) {
  1278             lua_pushvalue(L, json_export_indentstring_idx);
  1279             luaL_addvalue(&buf);
  1280           }
  1281         }
  1282         // add closing bracket to output buffer:
  1283         luaL_addchar(&buf, container->type == JSON_TABLETYPE_OBJECT ? '}' : ']');
  1284         // finish export if last level has been closed:
  1285         if (!level) goto json_export_finish;
  1286         // otherwise,
  1287         // recall previous container information from stack swap
  1288         // and set C pointer to corresponding C struct:
  1289         lua_rawgeti(L, json_export_stackswap_idx, stackswapidx--);
  1290         lua_replace(L, json_export_ccontainer_idx);
  1291         container = lua_touserdata(L, json_export_ccontainer_idx);
  1292         lua_rawgeti(L, json_export_stackswap_idx, stackswapidx--);
  1293         lua_replace(L, json_export_luacontainer_idx);
  1294         // repeat code for container iteration:
  1295         goto json_export_container;
  1296       }
  1297       // handle indentation for pretty results:
  1298       if (pretty && (containerkey || container->type == JSON_TABLETYPE_ARRAY)) {
  1299         luaL_addchar(&buf, '\n');
  1300         for (i=0; i<level; i++) {
  1301           lua_pushvalue(L, json_export_indentstring_idx);
  1302           luaL_addvalue(&buf);
  1303         }
  1304       }
  1305     } else {
  1306       // if no container is being processed,
  1307       // finish export:
  1308       json_export_finish:
  1309       // for pretty results, add final newline character if outermost container is processed:
  1310       if (pretty) luaL_addchar(&buf, '\n');
  1311       // create and return Lua string from buffer contents
  1312       luaL_pushresult(&buf);
  1313       return 1;
  1314     }
  1315   }
  1316 }
  1318 // functions in library module:
  1319 static const struct luaL_Reg json_module_functions[] = {
  1320   {"object", json_object},
  1321   {"array",  json_array},
  1322   {"import", json_import},
  1323   {"export", json_export},
  1324   {"get",    json_get},
  1325   {"type",   json_type},
  1326   {"set",    json_set},
  1327   {NULL, NULL}
  1328 };
  1330 // metamethods for JSON objects, JSON arrays, and unknown JSON collections (object or array):
  1331 static const struct luaL_Reg json_metatable_functions[] = {
  1332   {"__len", json_len},
  1333   {"__index", json_index},
  1334   {"__newindex", json_newindex},
  1335   {"__pairs", json_pairs},
  1336   {"__ipairs", json_ipairs},
  1337   {"__tostring", json_export},
  1338   {NULL, NULL}
  1339 };
  1341 // metamethods for JSON null marker:
  1342 static const struct luaL_Reg json_nullmark_metamethods[] = {
  1343   {"__tostring", json_nullmark_tostring},
  1344   {NULL, NULL}
  1345 };
  1347 // initializes json library:
  1348 int luaopen_json(lua_State *L) {
  1349   // empty stack:
  1350   lua_settop(L, 0);
  1351   // push library module onto stack position 1:
  1352   lua_newtable(L);
  1353   // register library functions:
  1354   luaL_setfuncs(L, json_module_functions, 0);
  1355   // create and store objectmt:
  1356   lua_newtable(L);
  1357   luaL_setfuncs(L, json_metatable_functions, 0);
  1358   json_regstore(L, objectmt);
  1359   // create and store arraymt:
  1360   lua_newtable(L);
  1361   luaL_setfuncs(L, json_metatable_functions, 0);
  1362   json_regstore(L, arraymt);
  1363   // set metatable of null marker and make it available through library module:
  1364   json_pushnullmark(L);
  1365   lua_newtable(L);
  1366   luaL_setfuncs(L, json_nullmark_metamethods, 0);
  1367   lua_setmetatable(L, -2);
  1368   lua_setfield(L, 1, "null");
  1369   // return library module (that's expected on top of stack):
  1370   return 1;
  1371 }
