Add functions for checking validity of lua wrapper objects.

develop
Alexander Gavrilov 2012-04-02 19:10:57 +04:00
parent 467f4108ae
commit a8fe0eccb4
2 changed files with 129 additions and 0 deletions

@ -36,6 +36,7 @@ distribution.
#include "DataDefs.h" #include "DataDefs.h"
#include "DataIdentity.h" #include "DataIdentity.h"
#include "LuaWrapper.h" #include "LuaWrapper.h"
#include "LuaTools.h"
#include "MiscUtils.h" #include "MiscUtils.h"
@ -402,6 +403,46 @@ static bool is_valid_metatable(lua_State *state, int objidx, int metaidx)
return ok; 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. * 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; 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) static int meta_nodata(lua_State *state)
{ {
return 0; return 0;
@ -1221,9 +1308,15 @@ static void RenderType(lua_State *state, compound_identity *node)
break; break;
case IDTYPE_GLOBAL: case IDTYPE_GLOBAL:
lua_pushstring(state, "global");
lua_setfield(state, ftable, "_kind");
{ {
RenderTypeChildren(state, node->getScopeChildren()); RenderTypeChildren(state, node->getScopeChildren());
lua_pushlightuserdata(state, node);
lua_setfield(state, ftable, "_identity");
BuildTypeMetatable(state, node); BuildTypeMetatable(state, node);
lua_dup(state); lua_dup(state);
@ -1244,6 +1337,9 @@ static void RenderType(lua_State *state, compound_identity *node)
RenderTypeChildren(state, node->getScopeChildren()); RenderTypeChildren(state, node->getScopeChildren());
lua_pushlightuserdata(state, node);
lua_setfield(state, ftable, "_identity");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME);
lua_setfield(state, ftable, "sizeof"); lua_setfield(state, ftable, "sizeof");
@ -1341,6 +1437,16 @@ static int DoAttach(lua_State *state)
lua_pushlightuserdata(state, NULL); lua_pushlightuserdata(state, NULL);
lua_setglobal(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"); freeze_table(state, false, "df");
} }

@ -46,6 +46,29 @@ namespace DFHack { namespace Lua {
DFHACK_EXPORT bool Require(color_ostream &out, lua_State *state, DFHACK_EXPORT bool Require(color_ostream &out, lua_State *state,
const std::string &module, bool setglobal = false); 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. * Push the pointer onto the stack as a wrapped DF object of the given type.
*/ */