From a8fe0eccb4ab03231da0692f06b9e4bbb27dc5c2 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 2 Apr 2012 19:10:57 +0400 Subject: [PATCH] Add functions for checking validity of lua wrapper objects. --- library/LuaWrapper.cpp | 106 +++++++++++++++++++++++++++++++++++++ library/include/LuaTools.h | 23 ++++++++ 2 files changed, 129 insertions(+) diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 1148d3fcd..818e6b9e1 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -36,6 +36,7 @@ distribution. #include "DataDefs.h" #include "DataIdentity.h" #include "LuaWrapper.h" +#include "LuaTools.h" #include "MiscUtils.h" @@ -402,6 +403,46 @@ static bool is_valid_metatable(lua_State *state, int objidx, int metaidx) return ok; } +bool Lua::IsDFNull(lua_State *state, int val_index) +{ + if (lua_isnil(state, val_index)) + return true; + if (lua_islightuserdata(state, val_index)) + return lua_touserdata(state, val_index) == NULL; + return false; +} + +Lua::ObjectClass Lua::IsDFObject(lua_State *state, int val_index) +{ + if (lua_isnil(state, val_index)) + return Lua::OBJ_NULL; + if (lua_islightuserdata(state, val_index)) + return lua_touserdata(state, val_index) ? Lua::OBJ_VOIDPTR : OBJ_NULL; + + Lua::ObjectClass cls; + + if (lua_istable(state, val_index)) + { + cls = Lua::OBJ_TYPE; + lua_pushvalue(state, val_index); + LookupInTable(state, &DFHACK_TYPEID_TABLE_TOKEN); + } + else if (lua_isuserdata(state, val_index)) + { + if (!lua_getmetatable(state, val_index)) + return Lua::OBJ_INVALID; + cls = Lua::OBJ_REF; + LookupInTable(state, &DFHACK_TYPETABLE_TOKEN); + } + else + return Lua::OBJ_INVALID; + + bool ok = !lua_isnil(state, -1); + lua_pop(state, 1); + + return ok ? cls : Lua::OBJ_INVALID; +} + /** * Given a DF object reference or type, safely retrieve its identity pointer. */ @@ -865,6 +906,52 @@ static int meta_enum_attr_index(lua_State *state) return 1; } +/** + * Metamethod: df.isvalid(obj[,allow_null]) + */ +static int meta_isvalid(lua_State *state) +{ + luaL_checkany(state, 1); + + switch (Lua::IsDFObject(state, 1)) + { + case Lua::OBJ_NULL: + lua_settop(state, 2); + if (lua_toboolean(state, 2)) + lua_pushvalue(state, lua_upvalueindex(1)); + else + lua_pushnil(state); + return 1; + + case Lua::OBJ_TYPE: + lua_pushvalue(state, lua_upvalueindex(2)); + return 1; + + case Lua::OBJ_VOIDPTR: + lua_pushvalue(state, lua_upvalueindex(3)); + return 1; + + case Lua::OBJ_REF: + lua_pushvalue(state, lua_upvalueindex(4)); + return 1; + + case Lua::OBJ_INVALID: + default: + lua_pushnil(state); + return 1; + } +} + +/** + * Metamethod: df.isnull(obj) + */ +static int meta_isnull(lua_State *state) +{ + luaL_checkany(state, 1); + lua_pushboolean(state, Lua::IsDFNull(state, 1)); + return 1; +} + static int meta_nodata(lua_State *state) { return 0; @@ -1221,9 +1308,15 @@ static void RenderType(lua_State *state, compound_identity *node) break; case IDTYPE_GLOBAL: + lua_pushstring(state, "global"); + lua_setfield(state, ftable, "_kind"); + { RenderTypeChildren(state, node->getScopeChildren()); + lua_pushlightuserdata(state, node); + lua_setfield(state, ftable, "_identity"); + BuildTypeMetatable(state, node); lua_dup(state); @@ -1244,6 +1337,9 @@ static void RenderType(lua_State *state, compound_identity *node) RenderTypeChildren(state, node->getScopeChildren()); + lua_pushlightuserdata(state, node); + lua_setfield(state, ftable, "_identity"); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME); lua_setfield(state, ftable, "sizeof"); @@ -1341,6 +1437,16 @@ static int DoAttach(lua_State *state) lua_pushlightuserdata(state, NULL); lua_setglobal(state, "NULL"); + lua_pushstring(state, "null"); + lua_pushstring(state, "type"); + lua_pushstring(state, "voidptr"); + lua_pushstring(state, "ref"); + lua_pushcclosure(state, meta_isvalid, 4); + lua_setfield(state, -2, "isvalid"); + + lua_pushcfunction(state, meta_isnull); + lua_setfield(state, -2, "isnull"); + freeze_table(state, false, "df"); } diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index 32e352010..6f95e7f6e 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -46,6 +46,29 @@ namespace DFHack { namespace Lua { DFHACK_EXPORT bool Require(color_ostream &out, lua_State *state, const std::string &module, bool setglobal = false); + /** + * Check if the object at the given index is NIL or NULL. + */ + DFHACK_EXPORT bool IsDFNull(lua_State *state, int val_index); + + enum ObjectClass { + /** Not a DF wrapper object */ + OBJ_INVALID = 0, + /** NIL or NULL */ + OBJ_NULL, + /** A named type identity object */ + OBJ_TYPE, + /** A void* reference, i.e. non-null lightuserdata */ + OBJ_VOIDPTR, + /** A typed object reference */ + OBJ_REF + }; + + /** + * Check if the object at the given index is a valid wrapper object. + */ + DFHACK_EXPORT ObjectClass IsDFObject(lua_State *state, int val_index); + /** * Push the pointer onto the stack as a wrapped DF object of the given type. */