luaclass: add generic {new,}index meta methods

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-06-16 15:42:32 +02:00
parent 537506a0c1
commit 1300b16c1e
3 changed files with 127 additions and 16 deletions

View File

@ -183,4 +183,123 @@ luaA_class_emit_signal(lua_State *L, lua_class_t *lua_class,
lua_pop(L, nargs); lua_pop(L, nargs);
} }
/** Try to use the metatable of an object.
* \param L The Lua VM state.
* \param idxobj The index of the object.
* \param idxfield The index of the field (attribute) to get.
* \return The number of element pushed on stack.
*/
int
luaA_usemetatable(lua_State *L, int idxobj, int idxfield)
{
/* Get metatable of the object. */
lua_getmetatable(L, idxobj);
/* Get the field */
lua_pushvalue(L, idxfield);
lua_rawget(L, -2);
/* Do we have a field like that? */
if(!lua_isnil(L, -1))
{
/* Yes, so return it! */
lua_remove(L, -2);
return 1;
}
/* No, so remove everything. */
lua_pop(L, 2);
return 0;
}
static lua_class_property_t *
lua_class_property_array_getbyid(lua_class_property_array_t *arr,
awesome_token_t id)
{
lua_class_property_t lookup_prop = { .id = id };
return lua_class_property_array_lookup(arr, &lookup_prop);
}
/** Get the class of an object.
* \param L The Lua VM state.
* \param idx The index of the object on the stack.
* \return The class if found, NULL otherwise.
*/
static lua_class_t *
luaA_class_get(lua_State *L, int idx)
{
int type = luaA_type(L, 1);
/* Find the class. */
lua_class_t *class = NULL;
foreach(classid, luaA_classes)
if(classid->id == type)
{
class = classid->class;
break;
}
return class;
}
/** Get a property of a object.
* \param L The Lua VM state.
* \param lua_class The Lua class.
* \param fieldidx The index of the field name.
* \return The object property if found, NULL otherwise.
*/
static lua_class_property_t *
luaA_class_property_get(lua_State *L, lua_class_t *lua_class, int fieldidx)
{
/* Lookup the property using token */
size_t len;
const char *attr = luaL_checklstring(L, fieldidx, &len);
awesome_token_t token = a_tokenize(attr, len);
return lua_class_property_array_getbyid(&lua_class->properties, token);
}
/** Generic index meta function for objects.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
*/
int
luaA_class_index(lua_State *L)
{
/* Try to use metatable first. */
if(luaA_usemetatable(L, 1, 2))
return 1;
lua_class_t *class = luaA_class_get(L, 1);
lua_class_property_t *prop = luaA_class_property_get(L, class, 2);
/* Property does exist and has an index callback */
if(prop && prop->index)
return prop->index(L, luaL_checkudata(L, 1, class->name));
return 0;
}
/** Generic newindex meta function for objects.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
*/
int
luaA_class_newindex(lua_State *L)
{
/* Try to use metatable first. */
if(luaA_usemetatable(L, 1, 2))
return 1;
lua_class_t *class = luaA_class_get(L, 1);
lua_class_property_t *prop = luaA_class_property_get(L, class, 2);
/* Property does exist and has a newindex callback */
if(prop && prop->newindex)
return prop->newindex(L, luaL_checkudata(L, 1, class->name));
return 0;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -69,6 +69,10 @@ void luaA_class_setup(lua_State *, lua_class_t *, const char *, lua_class_alloca
void luaA_class_add_property(lua_class_t *, awesome_token_t, const char *, void luaA_class_add_property(lua_class_t *, awesome_token_t, const char *,
lua_class_propfunc_t, lua_class_propfunc_t, lua_class_propfunc_t); lua_class_propfunc_t, lua_class_propfunc_t, lua_class_propfunc_t);
int luaA_usemetatable(lua_State *, int, int);
int luaA_class_index(lua_State *);
int luaA_class_newindex(lua_State *);
#define LUA_CLASS_FUNCS(prefix, lua_class) \ #define LUA_CLASS_FUNCS(prefix, lua_class) \
static inline int \ static inline int \
luaA_##prefix##_class_add_signal(lua_State *L) \ luaA_##prefix##_class_add_signal(lua_State *L) \
@ -98,6 +102,10 @@ void luaA_class_add_property(lua_class_t *, awesome_token_t, const char *,
{ "remove_signal", luaA_##class##_class_remove_signal }, \ { "remove_signal", luaA_##class##_class_remove_signal }, \
{ "emit_signal", luaA_##class##_class_emit_signal }, { "emit_signal", luaA_##class##_class_emit_signal },
#define LUA_CLASS_META \
{ "__index", luaA_class_index }, \
{ "__newindex", luaA_class_newindex },
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

16
luaa.h
View File

@ -118,22 +118,6 @@ luaA_pusharea(lua_State *L, area_t geometry)
return 1; return 1;
} }
static inline int
luaA_usemetatable(lua_State *L, int idxobj, int idxfield)
{
lua_getmetatable(L, idxobj);
lua_pushvalue(L, idxfield);
lua_rawget(L, -2);
if(!lua_isnil(L, -1))
{
lua_remove(L, -2);
return 1;
}
lua_pop(L, 2);
return 0;
}
/** Register an Lua object. /** Register an Lua object.
* \param L The Lua stack. * \param L The Lua stack.
* \param idx Index of the object in the stack. * \param idx Index of the object in the stack.