luaobject: add type recognition

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-06-15 17:57:04 +02:00
parent 706d545076
commit 284338532b
5 changed files with 63 additions and 39 deletions

View File

@ -32,6 +32,43 @@ DO_ARRAY(lua_class_id_t, lua_class_id, DO_NOTHING)
static lua_class_id_array_t luaA_classes;
/* This has to be initialized to the highest natural type of Lua */
#define LUA_HIGHEST_TYPE LUA_TTHREAD
/** Enhanced version of lua_type that recognizes setup Lua classes.
* \param L The Lua VM state.
* \param idx The index of the object on the stack.
*/
int
luaA_type(lua_State *L, int idx)
{
int type = lua_type(L, idx);
if(type == LUA_TUSERDATA)
foreach(class, luaA_classes)
if(luaA_toudata(L, idx, class->class->name))
return class->id;
return type;
}
/** Enhanced version of lua_typename that recognizes setup Lua classes.
* \param L The Lua VM state.
* \param idx The index of the object on the stack.
*/
const char *
luaA_typename(lua_State *L, int idx)
{
int type = luaA_type(L, idx);
if(type > LUA_HIGHEST_TYPE)
foreach(class, luaA_classes)
if(class->id == type)
return class->class->name;
return lua_typename(L, type);
}
void
luaA_openlib(lua_State *L, const char *name,
const struct luaL_reg methods[],
@ -55,7 +92,7 @@ luaA_class_setup(lua_State *L, lua_class_t *class,
const struct luaL_reg methods[],
const struct luaL_reg meta[])
{
static int class_type_counter = LUA_TTHREAD + 1;
static int class_type_counter = LUA_HIGHEST_TYPE;
luaA_openlib(L, name, methods, meta);

View File

@ -46,6 +46,9 @@ typedef struct
lua_class_allocator_t allocator;
} lua_class_t;
int luaA_type(lua_State *, int);
const char * luaA_typename(lua_State *, int);
void luaA_class_add_signal(lua_State *, lua_class_t *, const char *, int);
void luaA_class_remove_signal(lua_State *, lua_class_t *, const char *, int);
void luaA_class_emit_signal(lua_State *, lua_class_t *, const char *, int);

View File

@ -63,6 +63,27 @@ luaA_dofunction(lua_State *L, int nargs, int nret)
return true;
}
/** Convert a object to a udata if possible.
* \param L The Lua VM state.
* \param ud The index.
* \param tname The type name.
* \return A pointer to the object, NULL otherwise.
*/
static inline void *
luaA_toudata(lua_State *L, int ud, const char *tname)
{
void *p = lua_touserdata(L, ud);
if(p) /* value is a userdata? */
if(lua_getmetatable(L, ud)) /* does it have a metatable? */
{
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if(!lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
p = NULL;
lua_pop(L, 2); /* remove both metatables */
}
return p;
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

18
luaa.c
View File

@ -246,23 +246,7 @@ static int
luaAe_type(lua_State *L)
{
luaL_checkany(L, 1);
#define CHECK_TYPE(type) \
do { \
if(luaA_toudata(L, 1, #type)) \
{ \
lua_pushliteral(L, #type); \
return 1; \
} \
} while(0)
CHECK_TYPE(wibox);
CHECK_TYPE(client);
CHECK_TYPE(image);
CHECK_TYPE(key);
CHECK_TYPE(button);
CHECK_TYPE(tag);
CHECK_TYPE(widget);
#undef CHECK_TYPE
lua_pushstring(L, luaL_typename(L, 1));
lua_pushstring(L, luaA_typename(L, 1));
return 1;
}

21
luaa.h
View File

@ -90,27 +90,6 @@ luaA_dumpstack(lua_State *L)
fprintf(stderr, "------- Lua stack dump end ------\n");
}
/** Convert a object to a udata if possible.
* \param L The Lua VM state.
* \param ud The index.
* \param tname The type name.
* \return A pointer to the object, NULL otherwise.
*/
static inline void *
luaA_toudata(lua_State *L, int ud, const char *tname)
{
void *p = lua_touserdata(L, ud);
if(p) /* value is a userdata? */
if(lua_getmetatable(L, ud)) /* does it have a metatable? */
{
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if(!lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
p = NULL;
lua_pop(L, 2); /* remove both metatables */
}
return p;
}
static inline bool
luaA_checkboolean(lua_State *L, int n)
{