webmcp

annotate libraries/json/json.c @ 135:663722e35330

Added pairs metamethod for (sparse) JSON objects
author jbe
date Mon Jul 28 03:00:40 2014 +0200 (2014-07-28)
parents a1507b499fa5
children 3cf5fcf2bd5f
rev   line source
jbe@121 1 #include <lua.h>
jbe@121 2 #include <lauxlib.h>
jbe@122 3 #include <stdlib.h>
jbe@121 4 #include <string.h>
jbe@121 5
jbe@130 6 #define JSON_UPVAL_NULLMARK lua_upvalueindex(1)
jbe@130 7 #define JSON_UPVAL_SHADOWTBL lua_upvalueindex(2)
jbe@130 8 #define JSON_UPVAL_TYPES lua_upvalueindex(3)
jbe@130 9 #define JSON_UPVAL_METATABLE lua_upvalueindex(4)
jbe@135 10 #define JSON_UPVAL_PAIRS_ITERFUNC lua_upvalueindex(5)
jbe@135 11 #define JSON_UPVAL_IPAIRS_ITERFUNC lua_upvalueindex(6)
jbe@123 12
jbe@124 13 #define JSON_STATE_VALUE 0
jbe@124 14 #define JSON_STATE_OBJECT_KEY 1
jbe@124 15 #define JSON_STATE_OBJECT_KEY_TERMINATOR 2
jbe@124 16 #define JSON_STATE_OBJECT_VALUE 3
jbe@124 17 #define JSON_STATE_OBJECT_SEPARATOR 4
jbe@124 18 #define JSON_STATE_ARRAY_VALUE 5
jbe@124 19 #define JSON_STATE_ARRAY_SEPARATOR 6
jbe@124 20 #define JSON_STATE_END 7
jbe@121 21
jbe@133 22 static int json_object(lua_State *L) {
jbe@133 23 lua_settop(L, 1);
jbe@133 24 if (lua_isnil(L, 1)) {
jbe@133 25 lua_settop(L, 0);
jbe@133 26 lua_newtable(L);
jbe@133 27 }
jbe@133 28 lua_pushvalue(L, JSON_UPVAL_METATABLE);
jbe@133 29 lua_setmetatable(L, 1);
jbe@133 30 lua_pushvalue(L, 1);
jbe@133 31 lua_newtable(L); // internal shadow table
jbe@133 32 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
jbe@133 33 lua_pushvalue(L, 1);
jbe@133 34 lua_pushliteral(L, "object");
jbe@133 35 lua_rawset(L, JSON_UPVAL_TYPES);
jbe@133 36 return 1;
jbe@133 37 }
jbe@133 38
jbe@133 39 static int json_array(lua_State *L) {
jbe@133 40 lua_settop(L, 1);
jbe@133 41 if (lua_isnil(L, 1)) {
jbe@133 42 lua_settop(L, 0);
jbe@133 43 lua_newtable(L);
jbe@133 44 }
jbe@133 45 lua_pushvalue(L, JSON_UPVAL_METATABLE);
jbe@133 46 lua_setmetatable(L, 1);
jbe@133 47 lua_pushvalue(L, 1);
jbe@133 48 lua_newtable(L); // internal shadow table
jbe@133 49 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
jbe@133 50 lua_pushvalue(L, 1);
jbe@133 51 lua_pushliteral(L, "array");
jbe@133 52 lua_rawset(L, JSON_UPVAL_TYPES);
jbe@133 53 return 1;
jbe@133 54 }
jbe@133 55
jbe@121 56 static int json_import(lua_State *L) {
jbe@121 57 const char *str;
jbe@121 58 size_t total;
jbe@121 59 size_t pos = 0;
jbe@121 60 size_t level = 0;
jbe@124 61 int mode = JSON_STATE_VALUE;
jbe@121 62 char c;
jbe@121 63 luaL_Buffer luabuf;
jbe@121 64 char *cbuf;
jbe@121 65 size_t writepos;
jbe@121 66 lua_settop(L, 1);
jbe@121 67 str = lua_tostring(L, 1);
jbe@121 68 total = strlen(str);
jbe@121 69 json_import_loop:
jbe@121 70 while (c = str[pos], c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f') pos++;
jbe@121 71 switch (c) {
jbe@121 72 case 0:
jbe@124 73 if (mode == JSON_STATE_END) return 1;
jbe@121 74 json_import_unexpected_eof:
jbe@121 75 lua_pushnil(L);
jbe@121 76 if (level == 0) lua_pushliteral(L, "Empty string");
jbe@121 77 else lua_pushliteral(L, "Unexpected end of JSON document");
jbe@121 78 return 2;
jbe@121 79 case '{':
jbe@124 80 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
jbe@121 81 goto json_import_syntax_error;
jbe@121 82 pos++;
jbe@130 83 lua_newtable(L); // the external JSON object representation
jbe@125 84 lua_pushvalue(L, JSON_UPVAL_METATABLE);
jbe@125 85 lua_setmetatable(L, -2);
jbe@127 86 lua_pushvalue(L, -1);
jbe@127 87 lua_pushliteral(L, "object");
jbe@127 88 lua_rawset(L, JSON_UPVAL_TYPES);
jbe@130 89 lua_newtable(L); // the internal shadow table
jbe@123 90 lua_pushvalue(L, -2);
jbe@123 91 lua_pushvalue(L, -2);
jbe@130 92 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
jbe@124 93 mode = JSON_STATE_OBJECT_KEY;
jbe@121 94 level++;
jbe@121 95 goto json_import_loop;
jbe@121 96 case '[':
jbe@124 97 if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE)
jbe@121 98 goto json_import_syntax_error;
jbe@121 99 pos++;
jbe@130 100 lua_newtable(L); // the external JSON array representation
jbe@125 101 lua_pushvalue(L, JSON_UPVAL_METATABLE);
jbe@125 102 lua_setmetatable(L, -2);
jbe@127 103 lua_pushvalue(L, -1);
jbe@127 104 lua_pushliteral(L, "array");
jbe@127 105 lua_rawset(L, JSON_UPVAL_TYPES);
jbe@130 106 lua_newtable(L); // the internal shadow table
jbe@123 107 lua_pushvalue(L, -2);
jbe@123 108 lua_pushvalue(L, -2);
jbe@130 109 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
jbe@130 110 lua_pushinteger(L, 0); // magic integer to indicate an array
jbe@124 111 mode = JSON_STATE_ARRAY_VALUE;
jbe@121 112 level++;
jbe@121 113 goto json_import_loop;
jbe@121 114 case '}':
jbe@124 115 if (mode != JSON_STATE_OBJECT_KEY && mode != JSON_STATE_OBJECT_SEPARATOR)
jbe@121 116 goto json_import_syntax_error;
jbe@121 117 goto json_import_close;
jbe@121 118 case ']':
jbe@124 119 if (mode != JSON_STATE_ARRAY_VALUE && mode != JSON_STATE_ARRAY_SEPARATOR)
jbe@121 120 goto json_import_syntax_error;
jbe@130 121 lua_pop(L, 1); // pop magic integer
jbe@121 122 json_import_close:
jbe@121 123 pos++;
jbe@130 124 lua_pop(L, 1); // pop shadow table
jbe@121 125 if (--level) {
jbe@121 126 if (lua_type(L, -2) == LUA_TNUMBER) {
jbe@124 127 mode = JSON_STATE_ARRAY_VALUE;
jbe@121 128 } else {
jbe@124 129 mode = JSON_STATE_OBJECT_VALUE;
jbe@121 130 }
jbe@121 131 goto json_import_process_value;
jbe@121 132 } else {
jbe@124 133 mode = JSON_STATE_END;
jbe@121 134 }
jbe@121 135 goto json_import_loop;
jbe@121 136 case ':':
jbe@124 137 if (mode != JSON_STATE_OBJECT_KEY_TERMINATOR)
jbe@121 138 goto json_import_syntax_error;
jbe@121 139 pos++;
jbe@124 140 mode = JSON_STATE_OBJECT_VALUE;
jbe@121 141 goto json_import_loop;
jbe@121 142 case ',':
jbe@124 143 if (mode == JSON_STATE_OBJECT_SEPARATOR) {
jbe@124 144 mode = JSON_STATE_OBJECT_KEY;
jbe@124 145 } else if (mode == JSON_STATE_ARRAY_SEPARATOR) {
jbe@124 146 mode = JSON_STATE_ARRAY_VALUE;
jbe@121 147 } else {
jbe@121 148 goto json_import_syntax_error;
jbe@121 149 }
jbe@121 150 pos++;
jbe@121 151 goto json_import_loop;
jbe@121 152 case '"':
jbe@121 153 cbuf = luaL_buffinitsize(L, &luabuf, total-pos);
jbe@121 154 writepos = 0;
jbe@121 155 pos++;
jbe@121 156 while ((c = str[pos++]) != '"') {
jbe@121 157 if (c == 0) {
jbe@121 158 goto json_import_unexpected_eof;
jbe@121 159 } else if (c < 32 || c == 127) {
jbe@121 160 lua_pushnil(L);
jbe@121 161 lua_pushliteral(L, "Unexpected control character in JSON string");
jbe@121 162 return 2;
jbe@121 163 } else if (c == '\\') {
jbe@121 164 c = str[pos++];
jbe@121 165 switch (c) {
jbe@121 166 case 0:
jbe@121 167 goto json_import_unexpected_eof;
jbe@121 168 case '"':
jbe@121 169 case '/':
jbe@121 170 case '\\':
jbe@121 171 cbuf[writepos++] = c;
jbe@121 172 break;
jbe@121 173 case 'b':
jbe@121 174 cbuf[writepos++] = '\b';
jbe@121 175 break;
jbe@121 176 case 'f':
jbe@121 177 cbuf[writepos++] = '\f';
jbe@121 178 break;
jbe@121 179 case 'n':
jbe@121 180 cbuf[writepos++] = '\n';
jbe@121 181 break;
jbe@121 182 case 'r':
jbe@121 183 cbuf[writepos++] = '\r';
jbe@121 184 break;
jbe@121 185 case 't':
jbe@121 186 cbuf[writepos++] = '\t';
jbe@121 187 break;
jbe@121 188 case 'u':
jbe@121 189 lua_pushnil(L);
jbe@121 190 lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO
jbe@121 191 return 2;
jbe@121 192 default:
jbe@121 193 lua_pushnil(L);
jbe@121 194 lua_pushliteral(L, "Unexpected string escape sequence in JSON document");
jbe@121 195 return 2;
jbe@121 196 }
jbe@121 197 } else {
jbe@121 198 cbuf[writepos++] = c;
jbe@121 199 }
jbe@121 200 }
jbe@121 201 if (!c) goto json_import_unexpected_eof;
jbe@121 202 luaL_pushresultsize(&luabuf, writepos);
jbe@121 203 goto json_import_process_value;
jbe@121 204 }
jbe@122 205 if (c == '-' || (c >= '0' && c <= '9')) {
jbe@122 206 char *endptr;
jbe@122 207 double numval;
jbe@122 208 numval = strtod(str+pos, &endptr);
jbe@122 209 if (endptr == str+pos) goto json_import_syntax_error;
jbe@122 210 pos += endptr - (str+pos);
jbe@122 211 lua_pushnumber(L, numval);
jbe@122 212 } else if (!strncmp(str+pos, "true", 4)) {
jbe@121 213 lua_pushboolean(L, 1);
jbe@121 214 pos += 4;
jbe@121 215 } else if (!strncmp(str+pos, "false", 5)) {
jbe@121 216 lua_pushboolean(L, 0);
jbe@121 217 pos += 5;
jbe@121 218 } else if (!strncmp(str+pos, "null", 4)) {
jbe@130 219 lua_pushvalue(L, JSON_UPVAL_NULLMARK);
jbe@121 220 pos += 4;
jbe@121 221 } else {
jbe@121 222 goto json_import_syntax_error;
jbe@121 223 }
jbe@121 224 json_import_process_value:
jbe@121 225 switch (mode) {
jbe@124 226 case JSON_STATE_OBJECT_KEY:
jbe@121 227 if (lua_type(L, -1) != LUA_TSTRING) goto json_import_syntax_error;
jbe@124 228 mode = JSON_STATE_OBJECT_KEY_TERMINATOR;
jbe@121 229 goto json_import_loop;
jbe@124 230 case JSON_STATE_OBJECT_VALUE:
jbe@130 231 lua_rawset(L, -3);
jbe@124 232 mode = JSON_STATE_OBJECT_SEPARATOR;
jbe@121 233 goto json_import_loop;
jbe@124 234 case JSON_STATE_ARRAY_VALUE:
jbe@130 235 lua_rawseti(L, -3, lua_rawlen(L, -3) + 1);
jbe@124 236 mode = JSON_STATE_ARRAY_SEPARATOR;
jbe@121 237 goto json_import_loop;
jbe@124 238 case JSON_STATE_VALUE:
jbe@124 239 mode = JSON_STATE_END;
jbe@121 240 goto json_import_loop;
jbe@121 241 }
jbe@121 242 json_import_syntax_error:
jbe@121 243 lua_pushnil(L);
jbe@121 244 lua_pushliteral(L, "Syntax error in JSON document");
jbe@121 245 return 2;
jbe@121 246 }
jbe@121 247
jbe@130 248 #define JSON_PATH_GET 1
jbe@130 249 #define JSON_PATH_TYPE 2
jbe@130 250 #define JSON_PATH_ISNULL 3
jbe@130 251
jbe@130 252 static int json_path(lua_State *L, int mode) {
jbe@130 253 int argc;
jbe@130 254 int idx = 2;
jbe@130 255 argc = lua_gettop(L);
jbe@126 256 lua_pushvalue(L, 1);
jbe@130 257 while (idx <= argc) {
jbe@132 258 if (lua_isnil(L, -1)) {
jbe@132 259 if (mode == JSON_PATH_ISNULL) lua_pushboolean(L, 0);
jbe@132 260 return 1;
jbe@132 261 }
jbe@130 262 lua_pushvalue(L, -1);
jbe@130 263 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@126 264 if (lua_isnil(L, -1)) {
jbe@126 265 lua_pop(L, 1);
jbe@130 266 if (lua_type(L, -1) == LUA_TTABLE) {
jbe@130 267 lua_pushvalue(L, idx++);
jbe@130 268 lua_gettable(L, -2);
jbe@130 269 } else {
jbe@130 270 lua_pushnil(L);
jbe@130 271 }
jbe@130 272 } else {
jbe@130 273 lua_replace(L, -2);
jbe@130 274 lua_pushvalue(L, idx++);
jbe@130 275 lua_rawget(L, -2);
jbe@126 276 }
jbe@130 277 lua_replace(L, -2);
jbe@126 278 }
jbe@130 279 switch (mode) {
jbe@130 280 case JSON_PATH_GET:
jbe@130 281 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
jbe@130 282 return 1;
jbe@130 283 case JSON_PATH_TYPE:
jbe@130 284 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) {
jbe@130 285 lua_pushliteral(L, "null");
jbe@130 286 return 1;
jbe@126 287 }
jbe@130 288 lua_pushvalue(L, -1);
jbe@130 289 lua_rawget(L, JSON_UPVAL_TYPES);
jbe@130 290 if (lua_isnil(L, -1)) lua_pushstring(L, lua_typename(L, lua_type(L, -2)));
jbe@130 291 return 1;
jbe@130 292 case JSON_PATH_ISNULL:
jbe@130 293 lua_pushboolean(L, lua_rawequal(L, -1, JSON_UPVAL_NULLMARK));
jbe@130 294 return 1;
jbe@126 295 }
jbe@130 296 return 0;
jbe@130 297 }
jbe@130 298
jbe@130 299 static int json_get(lua_State *L) {
jbe@130 300 return json_path(L, JSON_PATH_GET);
jbe@130 301 }
jbe@130 302
jbe@130 303 static int json_type(lua_State *L) {
jbe@130 304 return json_path(L, JSON_PATH_TYPE);
jbe@130 305 }
jbe@130 306
jbe@130 307 static int json_isnull(lua_State *L) {
jbe@130 308 return json_path(L, JSON_PATH_ISNULL);
jbe@130 309 }
jbe@130 310
jbe@131 311 static int json_setnull(lua_State *L) {
jbe@131 312 lua_settop(L, 2);
jbe@131 313 lua_pushvalue(L, JSON_UPVAL_METATABLE);
jbe@131 314 lua_setmetatable(L, 1);
jbe@131 315 lua_pushvalue(L, 1);
jbe@131 316 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@131 317 if (lua_isnil(L, -1)) {
jbe@131 318 lua_newtable(L);
jbe@131 319 lua_pushvalue(L, 1);
jbe@131 320 lua_pushvalue(L, -2);
jbe@131 321 lua_rawset(L, JSON_UPVAL_SHADOWTBL);
jbe@131 322 }
jbe@131 323 lua_pushvalue(L, 2);
jbe@131 324 lua_pushvalue(L, JSON_UPVAL_NULLMARK);
jbe@131 325 lua_rawset(L, -3);
jbe@131 326 return 0;
jbe@131 327 }
jbe@131 328
jbe@130 329 static int json_len(lua_State *L) {
jbe@130 330 lua_settop(L, 1);
jbe@130 331 lua_pushvalue(L, 1);
jbe@130 332 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@130 333 if (lua_isnil(L, -1)) lua_pop(L, 1);
jbe@130 334 lua_pushinteger(L, lua_rawlen(L, -1));
jbe@123 335 return 1;
jbe@123 336 }
jbe@123 337
jbe@130 338 static int json_index(lua_State *L) {
jbe@130 339 lua_settop(L, 2);
jbe@130 340 lua_pushvalue(L, 1);
jbe@130 341 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@130 342 if (lua_isnil(L, -1)) return 1;
jbe@130 343 lua_pushvalue(L, 2);
jbe@130 344 lua_rawget(L, -2);
jbe@130 345 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
jbe@127 346 return 1;
jbe@127 347 }
jbe@127 348
jbe@130 349 static int json_newindex(lua_State *L) {
jbe@130 350 lua_settop(L, 3);
jbe@123 351 lua_pushvalue(L, 1);
jbe@130 352 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@130 353 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
jbe@130 354 lua_replace(L, 1);
jbe@130 355 lua_rawset(L, 1);
jbe@121 356 return 1;
jbe@121 357 }
jbe@121 358
jbe@135 359 static int json_pairs_iterfunc(lua_State *L) {
jbe@135 360 lua_settop(L, 2);
jbe@135 361 lua_pushvalue(L, 1);
jbe@135 362 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@135 363 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
jbe@135 364 lua_pushvalue(L, 2);
jbe@135 365 if (!lua_next(L, -2)) return 0;
jbe@135 366 if (lua_rawequal(L, -1, JSON_UPVAL_NULLMARK)) {
jbe@135 367 lua_pop(L, 1);
jbe@135 368 lua_pushnil(L);
jbe@135 369 }
jbe@135 370 return 2;
jbe@135 371 }
jbe@135 372
jbe@135 373 static int json_pairs(lua_State *L) {
jbe@135 374 lua_pushvalue(L, JSON_UPVAL_PAIRS_ITERFUNC);
jbe@135 375 lua_pushvalue(L, 1);
jbe@135 376 lua_pushnil(L);
jbe@135 377 return 3;
jbe@135 378 }
jbe@135 379
jbe@134 380 static int json_ipairs_iterfunc(lua_State *L) {
jbe@134 381 int idx;
jbe@134 382 lua_settop(L, 2);
jbe@134 383 idx = lua_tointeger(L, 2) + 1;
jbe@134 384 lua_pushvalue(L, 1);
jbe@134 385 lua_rawget(L, JSON_UPVAL_SHADOWTBL);
jbe@134 386 if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found");
jbe@134 387 lua_rawgeti(L, -1, idx);
jbe@134 388 if (lua_isnil(L, -1)) return 0;
jbe@134 389 lua_pushinteger(L, idx);
jbe@134 390 if (lua_rawequal(L, -2, JSON_UPVAL_NULLMARK)) lua_pushnil(L);
jbe@134 391 else lua_pushvalue(L, -2);
jbe@134 392 return 2;
jbe@134 393 }
jbe@134 394
jbe@134 395 static int json_ipairs(lua_State *L) {
jbe@134 396 lua_pushvalue(L, JSON_UPVAL_IPAIRS_ITERFUNC);
jbe@134 397 lua_pushvalue(L, 1);
jbe@134 398 lua_pushinteger(L, 0);
jbe@134 399 return 3;
jbe@134 400 }
jbe@134 401
jbe@121 402 static const struct luaL_Reg json_module_functions[] = {
jbe@133 403 {"object", json_object},
jbe@133 404 {"array", json_array},
jbe@121 405 {"import", json_import},
jbe@130 406 {"get", json_get},
jbe@127 407 {"type", json_type},
jbe@123 408 {"isnull", json_isnull},
jbe@131 409 {"setnull", json_setnull},
jbe@121 410 {NULL, NULL}
jbe@121 411 };
jbe@121 412
jbe@126 413 static const struct luaL_Reg json_metatable_functions[] = {
jbe@130 414 {"__len", json_len},
jbe@130 415 {"__index", json_index},
jbe@130 416 {"__newindex", json_newindex},
jbe@135 417 {"__pairs", json_pairs},
jbe@134 418 {"__ipairs", json_ipairs},
jbe@126 419 {NULL, NULL}
jbe@126 420 };
jbe@126 421
jbe@121 422 int luaopen_json(lua_State *L) {
jbe@126 423 lua_settop(L, 0);
jbe@126 424 lua_newtable(L); // 1: library table on stack position
jbe@130 425 lua_newtable(L); // 2: table used as JSON NULL value in internal shadow tables
jbe@130 426 lua_newtable(L); // 3: ephemeron table to store shadow tables for each JSON object/array to allow NULL values returned as nil
jbe@130 427 lua_newtable(L); // 4: ephemeron table to store the type of the JSON object/array
jbe@130 428 lua_newtable(L); // 5: metatable for ephemeron tables
jbe@121 429 lua_pushliteral(L, "__mode");
jbe@121 430 lua_pushliteral(L, "k");
jbe@130 431 lua_rawset(L, 5);
jbe@130 432 lua_pushvalue(L, 5); // 6: cloned metatable reference
jbe@127 433 lua_setmetatable(L, 3);
jbe@130 434 lua_setmetatable(L, 4);
jbe@130 435 lua_newtable(L); // 5: metatable for JSON objects and JSON arrays
jbe@126 436 lua_pushvalue(L, 2);
jbe@126 437 lua_pushvalue(L, 3);
jbe@127 438 lua_pushvalue(L, 4);
jbe@130 439 lua_pushvalue(L, 5);
jbe@135 440 lua_pushcclosure(L, json_pairs_iterfunc, 4); // 6: iteration function for pairs
jbe@135 441 lua_pushvalue(L, 2);
jbe@135 442 lua_pushvalue(L, 3);
jbe@135 443 lua_pushvalue(L, 4);
jbe@135 444 lua_pushvalue(L, 5);
jbe@135 445 lua_pushcclosure(L, json_ipairs_iterfunc, 4); // 7: iteration function for ipairs
jbe@134 446 lua_pushvalue(L, 5);
jbe@134 447 lua_pushvalue(L, 2);
jbe@134 448 lua_pushvalue(L, 3);
jbe@134 449 lua_pushvalue(L, 4);
jbe@134 450 lua_pushvalue(L, 5);
jbe@134 451 lua_pushvalue(L, 6);
jbe@135 452 lua_pushvalue(L, 7);
jbe@135 453 luaL_setfuncs(L, json_metatable_functions, 6);
jbe@135 454 lua_setfield(L, 1, "metatable");
jbe@135 455 luaL_setfuncs(L, json_module_functions, 6);
jbe@121 456 return 1;
jbe@121 457 }

Impressum / About Us