# HG changeset patch # User jbe # Date 1406464680 -7200 # Node ID 83aced09adc793540d98ffc42e54350f9546cd7e # Parent bccaa05aada7e40577d5fb02ffacb37881fe74b5 New function json.type(...) diff -r bccaa05aada7 -r 83aced09adc7 libraries/json/json.c --- a/libraries/json/json.c Sun Jul 27 03:54:39 2014 +0200 +++ b/libraries/json/json.c Sun Jul 27 14:38:00 2014 +0200 @@ -3,8 +3,9 @@ #include #include -#define JSON_UPVAL_NULLS lua_upvalueindex(1) -#define JSON_UPVAL_METATABLE lua_upvalueindex(2) +#define JSON_UPVAL_TYPES lua_upvalueindex(1) +#define JSON_UPVAL_NULLS lua_upvalueindex(2) +#define JSON_UPVAL_METATABLE lua_upvalueindex(3) #define JSON_STATE_VALUE 0 #define JSON_STATE_OBJECT_KEY 1 @@ -46,6 +47,9 @@ lua_newtable(L); // the actual JSON object lua_pushvalue(L, JSON_UPVAL_METATABLE); lua_setmetatable(L, -2); + lua_pushvalue(L, -1); + lua_pushliteral(L, "object"); + lua_rawset(L, JSON_UPVAL_TYPES); lua_newtable(L); // stores set of NULL values lua_pushvalue(L, -2); lua_pushvalue(L, -2); @@ -60,6 +64,9 @@ lua_newtable(L); // the actual JSON array lua_pushvalue(L, JSON_UPVAL_METATABLE); lua_setmetatable(L, -2); + lua_pushvalue(L, -1); + lua_pushliteral(L, "array"); + lua_rawset(L, JSON_UPVAL_TYPES); lua_newtable(L); // stores set of NULL values lua_pushvalue(L, -2); lua_pushvalue(L, -2); @@ -218,18 +225,16 @@ static int json_arylen(lua_State *L) { int lower, middle; int upper = 1; - // TODO: check input for valid array! lua_settop(L, 1); lua_pushvalue(L, 1); lua_rawget(L, JSON_UPVAL_NULLS); - if (lua_isnil(L, -1)) goto json_arylen_default; + if (lua_isnil(L, 2)) goto json_arylen_default; lua_pushnil(L); - if (!lua_next(L, -2)) goto json_arylen_default; - lua_pop(L, 2); + if (!lua_next(L, 2)) goto json_arylen_default; + lua_settop(L, 2); while (1) { lua_rawgeti(L, 1, upper); if (lua_isnil(L, -1)) { - // TODO: require metatable set? lua_pop(L, 1); lua_pushinteger(L, upper); lua_rawget(L, 2); @@ -245,7 +250,6 @@ middle = (lower + upper) / 2; lua_rawgeti(L, 1, middle); if (lua_isnil(L, -1)) { - // TODO: require metatable set? lua_pop(L, 1); lua_pushinteger(L, middle); lua_rawget(L, 2); @@ -261,8 +265,16 @@ return 1; } +static int json_type(lua_State *L) { + lua_settop(L, 1); + lua_rawget(L, JSON_UPVAL_TYPES); + return 1; +} + static int json_isnull(lua_State *L) { - // TODO: require metatable set? + lua_settop(L, 2); + lua_getmetatable(L, 1); + if (!lua_rawequal(L, -1, JSON_UPVAL_METATABLE)) goto json_isnull_false; lua_pushvalue(L, 1); lua_rawget(L, JSON_UPVAL_NULLS); if (lua_isnil(L, -1)) goto json_isnull_false; @@ -276,7 +288,7 @@ static const struct luaL_Reg json_module_functions[] = { {"import", json_import}, - {"arylen", json_arylen}, + {"type", json_type}, {"isnull", json_isnull}, {NULL, NULL} }; @@ -289,18 +301,22 @@ int luaopen_json(lua_State *L) { lua_settop(L, 0); lua_newtable(L); // 1: library table on stack position - lua_newtable(L); // 2: ephemeron table to store a set of keys associated with JSON-null values - lua_newtable(L); // 3: meta table for ephemeron table + lua_newtable(L); // 2: ephemeron table to store the type of the JSON object/array + lua_newtable(L); // 3: ephemeron table to store a set of keys associated with JSON-null values + lua_newtable(L); // 4: metatable for ephemeron tables lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); - lua_rawset(L, 3); + lua_rawset(L, 4); + lua_pushvalue(L, 4); // 5: cloned metatable reference lua_setmetatable(L, 2); - lua_newtable(L); // 3: metatable for JSON objects and JSON arrays - lua_pushvalue(L, 3); + lua_setmetatable(L, 3); + lua_newtable(L); // 4: metatable for JSON objects and JSON arrays + lua_pushvalue(L, 4); lua_setfield(L, 1, "metatable"); lua_pushvalue(L, 2); lua_pushvalue(L, 3); - luaL_setfuncs(L, json_metatable_functions, 2); - luaL_setfuncs(L, json_module_functions, 2); + lua_pushvalue(L, 4); + luaL_setfuncs(L, json_metatable_functions, 3); + luaL_setfuncs(L, json_module_functions, 3); return 1; }