Alternative export method of arrays from C to Lua
The patch is mainly to export client_array_t object to Lua, but can be used to export any ..._array_t object. The idea: export to Lua not a table, but userdata with metamethods to get/set/define length of ..._array_t object directly. Now when I get clients field from tag object C code creates full copy of client_array_t structure into Lua table. It takes traversing a whole array of data. I did it in other way: userdata is exported, with __index, __newindex, and __len meta-methods defined, and Lua script gains direct access to client_array_t C-array: it can get client object, get length of array and assign client objects to some index in C-array. Pros: No overhead of creation a copy of C-structure into Lua-table: if I want just to test a number of clients for a tag, I don't need a whole loop to build table, I just want to read clients->len field, and I do so via __len meta-method. Also if I want to get some client from tags.clients, I don't need to create ALL clients Lua-objects, I just get client_t C-struct and create Lua-object from it. Just in place. So Lua-loop enuming all tag.clients is not 2 loops internally (first create copy of tag.clients into Lua-table, then enum this table), but only one, and if I break out of loop in the middle, I create only some client Lua-objects, not all of them from tag.clients. Contras: As far as clients field is not a table, I cant use pairs/ipairs and other table functions for it. But it can be implemented in other way: for k,c pairs(tag.clients) => for k = 1, #tag.clients, table.insert(tag.clients, client) => tag.clients[#tag.clients+1] = client etc. One more Pro now: As far as tag.clients in current implementation returns copy of data table.insert doesn't do what's expected: it doesn't really add client into tag.clients "array". With my implementation client is added as expected, as we work with client_array_t structure directly. Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
8b5f6266da
commit
4ab499fe26
1
client.h
1
client.h
|
@ -51,6 +51,7 @@ int luaA_client_newindex(lua_State *);
|
||||||
int luaA_client_userdata_new(lua_State *, client_t *);
|
int luaA_client_userdata_new(lua_State *, client_t *);
|
||||||
|
|
||||||
DO_SLIST(client_t, client, client_unref)
|
DO_SLIST(client_t, client, client_unref)
|
||||||
|
DO_LUA_EXPORT_ARRAY(client, "client_array", client_t, client_array_t, luaA_client_userdata_new)
|
||||||
|
|
||||||
#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
|
||||||
|
|
|
@ -1052,9 +1052,10 @@ function widget.taglist.label.all(t, args)
|
||||||
if sel and sel.tags[t] then
|
if sel and sel.tags[t] then
|
||||||
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarefw.png\""
|
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarefw.png\""
|
||||||
elseif bg_urgent and fg_urgent then
|
elseif bg_urgent and fg_urgent then
|
||||||
for k, c in pairs(t.clients) do
|
local cli = t.clients
|
||||||
|
for k = 1, #cli do
|
||||||
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarew.png\""
|
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarew.png\""
|
||||||
if c.urgent then
|
if cli[k].urgent then
|
||||||
bg_color = bg_urgent
|
bg_color = bg_urgent
|
||||||
fg_color = fg_urgent
|
fg_color = fg_urgent
|
||||||
break
|
break
|
||||||
|
|
61
lua.h
61
lua.h
|
@ -259,5 +259,66 @@ luaA_generic_pairs(lua_State *L)
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DO_LUA_EXPORT_ARRAY(pfx, typename, type, atype, ctor) \
|
||||||
|
static inline int \
|
||||||
|
luaA_##pfx##_array_index(lua_State *L) \
|
||||||
|
{ \
|
||||||
|
atype *value = lua_touserdata(L, 1); \
|
||||||
|
type **obj; \
|
||||||
|
int idx; \
|
||||||
|
\
|
||||||
|
if ((obj = lua_touserdata(L, 2))) \
|
||||||
|
{ \
|
||||||
|
for (idx = 0; idx < value->len; idx++) \
|
||||||
|
if (value->tab[idx] == *obj) \
|
||||||
|
return ctor(L, value->tab[idx]); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
idx = luaL_checknumber(L, 2) - 1; \
|
||||||
|
if (idx < 0 || idx >= value->len) \
|
||||||
|
return 0; \
|
||||||
|
\
|
||||||
|
return ctor(L, value->tab[idx]); \
|
||||||
|
} \
|
||||||
|
static inline int \
|
||||||
|
luaA_##pfx##_array_newindex(lua_State *L) \
|
||||||
|
{ \
|
||||||
|
atype *value = lua_touserdata(L, 1); \
|
||||||
|
int idx = luaL_checknumber(L, 2); \
|
||||||
|
type **elem = luaL_checkudata(L, 3, #pfx); \
|
||||||
|
pfx##_array_splice(value, idx - 1, 1, elem, 1); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
static inline int \
|
||||||
|
luaA_##pfx##_array_len(lua_State *L) \
|
||||||
|
{ \
|
||||||
|
atype *value = lua_touserdata(L, 1); \
|
||||||
|
lua_pushnumber(L, value->len); \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
static inline int \
|
||||||
|
luaA_##pfx##_array_tostring(lua_State *L) \
|
||||||
|
{ \
|
||||||
|
atype *value = lua_touserdata(L, 1); \
|
||||||
|
lua_pushfstring(L, "["typename" udata(%p)]", value); \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
static inline void \
|
||||||
|
luaA_##pfx##_array_export(lua_State *L, atype *arr) \
|
||||||
|
{ \
|
||||||
|
lua_pushlightuserdata(L, arr); \
|
||||||
|
lua_newtable(L); \
|
||||||
|
lua_pushcfunction(L, luaA_##pfx##_array_index); \
|
||||||
|
lua_setfield(L, -2, "__index"); \
|
||||||
|
lua_pushcfunction(L, luaA_##pfx##_array_tostring); \
|
||||||
|
lua_setfield(L, -2, "__tostring"); \
|
||||||
|
lua_pushcfunction(L, luaA_##pfx##_array_newindex); \
|
||||||
|
lua_setfield(L, -2, "__newindex"); \
|
||||||
|
lua_pushcfunction(L, luaA_##pfx##_array_len); \
|
||||||
|
lua_setfield(L, -2, "__len"); \
|
||||||
|
lua_setmetatable(L, -2); \
|
||||||
|
}
|
||||||
|
|
||||||
#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
|
||||||
|
|
11
tag.c
11
tag.c
|
@ -349,8 +349,6 @@ luaA_tag_index(lua_State *L)
|
||||||
size_t len;
|
size_t len;
|
||||||
tag_t **tag = luaA_checkudata(L, 1, "tag");
|
tag_t **tag = luaA_checkudata(L, 1, "tag");
|
||||||
const char *attr;
|
const char *attr;
|
||||||
client_array_t *clients;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(luaA_usemetatable(L, 1, 2))
|
if(luaA_usemetatable(L, 1, 2))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -383,14 +381,7 @@ luaA_tag_index(lua_State *L)
|
||||||
lua_pushnumber(L, (*tag)->ncol);
|
lua_pushnumber(L, (*tag)->ncol);
|
||||||
break;
|
break;
|
||||||
case A_TK_CLIENTS:
|
case A_TK_CLIENTS:
|
||||||
clients = &(*tag)->clients;
|
luaA_client_array_export(L, &(*tag)->clients);
|
||||||
luaA_otable_new(L);
|
|
||||||
for(i = 0; i < clients->len; i++)
|
|
||||||
{
|
|
||||||
luaA_client_userdata_new(L, clients->tab[i]);
|
|
||||||
luaA_client_userdata_new(L, clients->tab[i]);
|
|
||||||
lua_rawset(L, -3);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue