wslua: register attributes along with their class

At the moment, wslua first registers a class and then adds its
attributes in a second step. This registration creates empty __getters
and __setters tables which are later populated with the getter and
setter methods of the attributes.

Looking at the code and the comments, it seems that this was meant to be
a temporary solution. Eventually, attributes should be stored in
wslua_class' attrs field. The code to read and write attributes was
already updated to handle this.

Add new macros WSLUA_REGISTER_CLASS/_META_WITH_ATTRS that store the
attributes in wslua_class. Defining new macros is simpler than modifying
WSLUA_REGISTER_CLASS/_META to register attributes. If we did the latter,
we'd have to add an empty attribute list for all classes without
attributes.

We can now drop the WSLUA_REGISTER_ATTRIBUTES macro and the
wslua_reg_attributes function.

Using this new way of registering attributes, the __getters and
__setters tables are still available. The tests is the test suite that
rely on those tables still pass.

Change-Id: I526b9116435645c9c54ab69a05c3c7f3d459ec33
Reviewed-on: https://code.wireshark.org/review/31417
Reviewed-by: Martin Kaiser <wireshark@kaiser.cx>
Petri-Dish: Martin Kaiser <wireshark@kaiser.cx>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Martin Kaiser 2019-01-06 15:03:01 +01:00 committed by Peter Wu
parent 369c39ace8
commit 965248dcfb
12 changed files with 24 additions and 79 deletions

View File

@ -416,39 +416,36 @@ extern int wslua_reg_attributes(lua_State *L, const wslua_attribute_table *t, gb
/* pop the metatable */ \
lua_pop(L, 1)
#define WSLUA_REGISTER_META(C) { \
#define __WSLUA_REGISTER_META(C, ATTRS_BLOCK) { \
const wslua_class C ## _class = { \
.name = #C, \
.instance_meta = C ## _meta, \
ATTRS_BLOCK \
}; \
wslua_register_classinstance_meta(L, &C ## _class); \
WSLUA_REGISTER_GC(C); \
}
#define WSLUA_REGISTER_CLASS(C) { \
#define WSLUA_REGISTER_META(C) __WSLUA_REGISTER_META(C,)
#define WSLUA_REGISTER_META_WITH_ATTRS(C) \
__WSLUA_REGISTER_META(C, .attrs = C ## _attributes)
#define __WSLUA_REGISTER_CLASS(C, ATTRS_BLOCK) { \
const wslua_class C ## _class = { \
.name = #C, \
.class_methods = C ## _methods, \
.class_meta = C ## _meta, \
.instance_methods = C ## _methods, \
.instance_meta = C ## _meta, \
ATTRS_BLOCK \
}; \
wslua_register_class(L, &C ## _class); \
WSLUA_REGISTER_GC(C); \
}
/* see comments for wslua_reg_attributes and wslua_attribute_dispatcher to see how this attribute stuff works */
#define WSLUA_REGISTER_ATTRIBUTES(C) { \
/* get metatable from Lua registry */ \
luaL_getmetatable(L, #C); \
if (lua_isnil(L, -1)) { \
g_error("Attempt to register attributes without a pre-existing metatable for '%s' in Lua registry\n", #C); \
} \
/* register the getters/setters in their tables */ \
wslua_reg_attributes(L, C##_attributes, TRUE); \
wslua_reg_attributes(L, C##_attributes, FALSE); \
lua_pop(L, 1); /* pop the metatable */ \
}
#define WSLUA_REGISTER_CLASS(C) __WSLUA_REGISTER_CLASS(C,)
#define WSLUA_REGISTER_CLASS_WITH_ATTRS(C) \
__WSLUA_REGISTER_CLASS(C, .attrs = C ## _attributes)
#define WSLUA_INIT(L) \
luaL_openlibs(L); \

View File

@ -292,8 +292,7 @@ WSLUA_META CaptureInfo_meta[] = {
};
int CaptureInfo_register(lua_State* L) {
WSLUA_REGISTER_META(CaptureInfo);
WSLUA_REGISTER_ATTRIBUTES(CaptureInfo);
WSLUA_REGISTER_META_WITH_ATTRS(CaptureInfo);
return 0;
}
@ -502,8 +501,7 @@ WSLUA_META CaptureInfoConst_meta[] = {
};
int CaptureInfoConst_register(lua_State* L) {
WSLUA_REGISTER_META(CaptureInfoConst);
WSLUA_REGISTER_ATTRIBUTES(CaptureInfoConst);
WSLUA_REGISTER_META_WITH_ATTRS(CaptureInfoConst);
return 0;
}

View File

@ -472,8 +472,7 @@ WSLUA_META FieldInfo_meta[] = {
};
int FieldInfo_register(lua_State* L) {
WSLUA_REGISTER_META(FieldInfo);
WSLUA_REGISTER_ATTRIBUTES(FieldInfo);
WSLUA_REGISTER_META_WITH_ATTRS(FieldInfo);
return 0;
}
@ -794,8 +793,7 @@ int Field_register(lua_State* L) {
wanted_fields = g_ptr_array_new();
WSLUA_REGISTER_CLASS(Field);
WSLUA_REGISTER_ATTRIBUTES(Field);
WSLUA_REGISTER_CLASS_WITH_ATTRS(Field);
outstanding_FieldInfo = g_ptr_array_new();
return 0;

View File

@ -501,8 +501,7 @@ WSLUA_META File_meta[] = {
};
int File_register(lua_State* L) {
WSLUA_REGISTER_CLASS(File);
WSLUA_REGISTER_ATTRIBUTES(File);
WSLUA_REGISTER_CLASS_WITH_ATTRS(File);
return 0;
}

View File

@ -1027,8 +1027,7 @@ WSLUA_META FileHandler_meta[] = {
};
int FileHandler_register(lua_State* L) {
WSLUA_REGISTER_CLASS(FileHandler);
WSLUA_REGISTER_ATTRIBUTES(FileHandler);
WSLUA_REGISTER_CLASS_WITH_ATTRS(FileHandler);
return 0;
}

View File

@ -239,8 +239,7 @@ WSLUA_META FrameInfo_meta[] = {
};
int FrameInfo_register(lua_State* L) {
WSLUA_REGISTER_CLASS(FrameInfo);
WSLUA_REGISTER_ATTRIBUTES(FrameInfo);
WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfo);
return 0;
}
@ -384,8 +383,7 @@ WSLUA_META FrameInfoConst_meta[] = {
};
int FrameInfoConst_register(lua_State* L) {
WSLUA_REGISTER_CLASS(FrameInfoConst);
WSLUA_REGISTER_ATTRIBUTES(FrameInfoConst);
WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfoConst);
return 0;
}

View File

@ -229,45 +229,6 @@ gboolean wslua_get_field(lua_State *L, int idx, const gchar *name) {
return result;
}
/**
* This is a transition function that sets attributes on classes. It must be
* replaced by setting the attributes in the wslua_class structure such that
* WSLUA_REGISTER_ATTRIBUTES can be nuked.
*/
int wslua_reg_attributes(lua_State *L, const wslua_attribute_table *t, gboolean is_getter) {
const gchar *metafield = is_getter ? "__index" : "__newindex";
/* assume __index/__newindex exists and index 1 is a metatable */
lua_rawgetfield(L, -1, metafield);
if (lua_isnil(L, -1)) {
g_error("%s expected in metatable, found none!\n", metafield);
}
lua_pop(L, 1);
/* Find table to add properties. */
metafield = is_getter ? "__getters" : "__setters";
lua_rawgetfield(L, -1, metafield);
if (!lua_istable(L, -1)) {
g_error("Property %s is not found in metatable!\n", metafield);
}
/* Fill the getter/setter table with given functions. Being a transition
* function that will be removed later, this does not perform duplicate
* keys detection. */
for (; t->fieldname != NULL; t++) {
lua_CFunction cfunc = is_getter ? t->getfunc : t->setfunc;
if (cfunc) {
lua_pushcfunction(L, cfunc);
lua_rawsetfield(L, -2, t->fieldname);
}
}
/* Drop __getters/__setters table */
lua_pop(L, 1);
return 0;
}
/**
* The __index metamethod for classes. Expected upvalues: class name.
*/

View File

@ -375,8 +375,7 @@ int Listener_register(lua_State* L) {
listeners = g_ptr_array_new();
WSLUA_REGISTER_CLASS(Listener);
WSLUA_REGISTER_ATTRIBUTES(Listener);
WSLUA_REGISTER_CLASS_WITH_ATTRS(Listener);
return 0;
}

View File

@ -216,8 +216,7 @@ WSLUA_META NSTime_meta[] = {
};
int NSTime_register(lua_State* L) {
WSLUA_REGISTER_CLASS(NSTime);
WSLUA_REGISTER_ATTRIBUTES(NSTime);
WSLUA_REGISTER_CLASS_WITH_ATTRS(NSTime);
return 0;
}

View File

@ -462,8 +462,7 @@ WSLUA_META Pinfo_meta[] = {
};
int Pinfo_register(lua_State* L) {
WSLUA_REGISTER_META(Pinfo);
WSLUA_REGISTER_ATTRIBUTES(Pinfo);
WSLUA_REGISTER_META_WITH_ATTRS(Pinfo);
outstanding_Pinfo = g_ptr_array_new();
outstanding_PrivateTable = g_ptr_array_new();
return 0;

View File

@ -549,8 +549,7 @@ WSLUA_META Proto_meta[] = {
};
int Proto_register(lua_State* L) {
WSLUA_REGISTER_CLASS(Proto);
WSLUA_REGISTER_ATTRIBUTES(Proto);
WSLUA_REGISTER_CLASS_WITH_ATTRS(Proto);
outstanding_FuncSavers = g_ptr_array_new();

View File

@ -964,8 +964,7 @@ WSLUA_META TreeItem_meta[] = {
int TreeItem_register(lua_State *L) {
gint* etts[] = { &wslua_ett };
wslua_ett = -1; /* Reset to support reload Lua plugins */
WSLUA_REGISTER_CLASS(TreeItem);
WSLUA_REGISTER_ATTRIBUTES(TreeItem);
WSLUA_REGISTER_CLASS_WITH_ATTRS(TreeItem);
outstanding_TreeItem = g_ptr_array_new();
proto_register_subtree_array(etts,1);
return 0;