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