degesch: hook implementation cleanup
This commit is contained in:
parent
d4cbc576e2
commit
364eb009ca
152
degesch.c
152
degesch.c
@ -1390,12 +1390,45 @@ plugin_destroy (struct plugin *self)
|
|||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
// This is a bit ugly since insertion is O(n) and the need to get rid of the
|
||||||
|
// specific type because of list macros, however I don't currently posses any
|
||||||
|
// strictly better, ordered data structure
|
||||||
|
|
||||||
|
struct hook
|
||||||
|
{
|
||||||
|
LIST_HEADER (struct hook)
|
||||||
|
int priority; ///< The lesser the sooner
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct hook *
|
||||||
|
hook_insert (struct hook *list, struct hook *item)
|
||||||
|
{
|
||||||
|
// Corner cases: list is empty or we precede everything
|
||||||
|
if (!list || item->priority < list->priority)
|
||||||
|
{
|
||||||
|
LIST_PREPEND (list, item);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise fast-forward to the last entry that precedes us
|
||||||
|
struct hook *before = list;
|
||||||
|
while (before->next && before->next->priority < item->next->priority)
|
||||||
|
before = before->next;
|
||||||
|
|
||||||
|
// And link ourselves in between it and its successor
|
||||||
|
if ((item->next = before->next))
|
||||||
|
item->next->prev = item;
|
||||||
|
before->next = item;
|
||||||
|
item->prev = before;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
struct input_hook
|
struct input_hook
|
||||||
{
|
{
|
||||||
LIST_HEADER (struct input_hook)
|
struct hook super; ///< Common hook fields
|
||||||
|
|
||||||
struct input_hook_vtable *vtable; ///< Methods
|
struct input_hook_vtable *vtable; ///< Methods
|
||||||
int priority; ///< The lesser the sooner
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct input_hook_vtable
|
struct input_hook_vtable
|
||||||
@ -1410,10 +1443,8 @@ struct input_hook_vtable
|
|||||||
|
|
||||||
struct irc_hook
|
struct irc_hook
|
||||||
{
|
{
|
||||||
LIST_HEADER (struct irc_hook)
|
struct hook super; ///< Common hook fields
|
||||||
|
|
||||||
struct irc_hook_vtable *vtable; ///< Methods
|
struct irc_hook_vtable *vtable; ///< Methods
|
||||||
int priority; ///< The lesser the sooner
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct irc_hook_vtable
|
struct irc_hook_vtable
|
||||||
@ -1487,8 +1518,8 @@ struct app_context
|
|||||||
int terminal_suspended; ///< Terminal suspension level
|
int terminal_suspended; ///< Terminal suspension level
|
||||||
|
|
||||||
struct plugin *plugins; ///< Loaded plugins
|
struct plugin *plugins; ///< Loaded plugins
|
||||||
struct input_hook *input_hooks; ///< Input hooks
|
struct hook *input_hooks; ///< Input hooks
|
||||||
struct irc_hook *irc_hooks; ///< IRC hooks
|
struct hook *irc_hooks; ///< IRC hooks
|
||||||
}
|
}
|
||||||
*g_ctx;
|
*g_ctx;
|
||||||
|
|
||||||
@ -4116,8 +4147,9 @@ static char *
|
|||||||
irc_process_hooks (struct server *s, char *input)
|
irc_process_hooks (struct server *s, char *input)
|
||||||
{
|
{
|
||||||
log_server_debug (s, "#a>> \"#S\"#r", ATTR_JOIN, input);
|
log_server_debug (s, "#a>> \"#S\"#r", ATTR_JOIN, input);
|
||||||
LIST_FOR_EACH (struct irc_hook, hook, s->ctx->irc_hooks)
|
LIST_FOR_EACH (struct hook, iter, s->ctx->irc_hooks)
|
||||||
{
|
{
|
||||||
|
struct irc_hook *hook = (struct irc_hook *) iter;
|
||||||
char *processed = hook->vtable->filter (hook, s, input);
|
char *processed = hook->vtable->filter (hook, s, input);
|
||||||
if (input == processed)
|
if (input == processed)
|
||||||
continue;
|
continue;
|
||||||
@ -7219,73 +7251,6 @@ server_rename (struct app_context *ctx, struct server *s, const char *new_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Ordered linked lists ----------------------------------------------------
|
|
||||||
|
|
||||||
// This is a bit ugly since there's no way to force a guarantee that the list
|
|
||||||
// members are going to be the first ones in the structure, plus insertion is
|
|
||||||
// O(n), however I don't currently posses any better ordered data structure
|
|
||||||
|
|
||||||
struct list_header
|
|
||||||
{
|
|
||||||
LIST_HEADER (struct list_header)
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct list_header *
|
|
||||||
list_insert_ordered (struct list_header *list, struct list_header *item,
|
|
||||||
bool (*less) (const void *, const void *))
|
|
||||||
{
|
|
||||||
// Corner cases: list is empty or we precede everything
|
|
||||||
if (!list || less (item, list))
|
|
||||||
{
|
|
||||||
LIST_PREPEND (list, item);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise fast-worward to the last entry that precedes us
|
|
||||||
struct list_header *before = list;
|
|
||||||
while (before->next && less (before->next, item))
|
|
||||||
before = before->next;
|
|
||||||
|
|
||||||
// And link ourselves in between it and its successor
|
|
||||||
if ((item->next = before->next))
|
|
||||||
item->next->prev = item;
|
|
||||||
before->next = item;
|
|
||||||
item->prev = before;
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Hooks -------------------------------------------------------------------
|
|
||||||
|
|
||||||
static bool
|
|
||||||
input_hook_less (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
return ((const struct input_hook *) a)->priority
|
|
||||||
< ((const struct input_hook *) b)->priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
input_hook_insert (struct app_context *ctx, struct input_hook *hook)
|
|
||||||
{
|
|
||||||
ctx->input_hooks = (struct input_hook *) list_insert_ordered (
|
|
||||||
(struct list_header *) ctx->input_hooks,
|
|
||||||
(struct list_header *) hook, input_hook_less);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
irc_hook_less (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
return ((const struct irc_hook *) a)->priority
|
|
||||||
< ((const struct irc_hook *) b)->priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
irc_hook_insert (struct app_context *ctx, struct irc_hook *hook)
|
|
||||||
{
|
|
||||||
ctx->irc_hooks = (struct irc_hook *) list_insert_ordered (
|
|
||||||
(struct list_header *) ctx->irc_hooks,
|
|
||||||
(struct list_header *) hook, irc_hook_less);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Lua ---------------------------------------------------------------------
|
// --- Lua ---------------------------------------------------------------------
|
||||||
|
|
||||||
// Each plugin has its own Lua state object, so that a/ they don't disturb each
|
// Each plugin has its own Lua state object, so that a/ they don't disturb each
|
||||||
@ -7501,6 +7466,7 @@ struct lua_hook
|
|||||||
enum lua_hook_type type; ///< Type of the hook
|
enum lua_hook_type type; ///< Type of the hook
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
struct hook hook; ///< Base structure
|
||||||
struct input_hook input_hook; ///< Input hook
|
struct input_hook input_hook; ///< Input hook
|
||||||
struct irc_hook irc_hook; ///< IRC hook
|
struct irc_hook irc_hook; ///< IRC hook
|
||||||
}
|
}
|
||||||
@ -7514,10 +7480,10 @@ lua_hook_unhook (lua_State *L)
|
|||||||
switch (hook->type)
|
switch (hook->type)
|
||||||
{
|
{
|
||||||
case XLUA_HOOK_INPUT:
|
case XLUA_HOOK_INPUT:
|
||||||
LIST_UNLINK (hook->plugin->ctx->input_hooks, &hook->data.input_hook);
|
LIST_UNLINK (hook->plugin->ctx->input_hooks, &hook->data.hook);
|
||||||
break;
|
break;
|
||||||
case XLUA_HOOK_IRC:
|
case XLUA_HOOK_IRC:
|
||||||
LIST_UNLINK (hook->plugin->ctx->irc_hooks, &hook->data.irc_hook);
|
LIST_UNLINK (hook->plugin->ctx->irc_hooks, &hook->data.hook);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hard_assert (!"invalid hook type");
|
hard_assert (!"invalid hook type");
|
||||||
@ -7679,13 +7645,16 @@ struct irc_hook_vtable lua_irc_hook_vtable =
|
|||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static struct lua_hook *
|
static struct lua_hook *
|
||||||
lua_plugin_push_hook
|
lua_plugin_push_hook (struct lua_plugin *plugin, int callback_index,
|
||||||
(struct lua_plugin *plugin, int callback_index, enum lua_hook_type type)
|
enum lua_hook_type type, int priority)
|
||||||
{
|
{
|
||||||
lua_State *L = plugin->L;
|
lua_State *L = plugin->L;
|
||||||
|
luaL_checktype (L, callback_index, LUA_TFUNCTION);
|
||||||
|
|
||||||
struct lua_hook *hook = lua_newuserdata (L, sizeof *hook);
|
struct lua_hook *hook = lua_newuserdata (L, sizeof *hook);
|
||||||
luaL_setmetatable (L, XLUA_HOOK_METATABLE);
|
luaL_setmetatable (L, XLUA_HOOK_METATABLE);
|
||||||
memset (hook, 0, sizeof *hook);
|
memset (hook, 0, sizeof *hook);
|
||||||
|
hook->data.hook.priority = priority;
|
||||||
hook->type = type;
|
hook->type = type;
|
||||||
hook->plugin = plugin;
|
hook->plugin = plugin;
|
||||||
|
|
||||||
@ -7702,13 +7671,11 @@ static int
|
|||||||
lua_plugin_hook_input (lua_State *L)
|
lua_plugin_hook_input (lua_State *L)
|
||||||
{
|
{
|
||||||
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
|
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
|
||||||
luaL_checktype (L, 1, LUA_TFUNCTION);
|
struct lua_hook *hook = lua_plugin_push_hook
|
||||||
lua_Integer priority = luaL_optinteger (L, 2, 0);
|
(plugin, 1, XLUA_HOOK_INPUT, luaL_optinteger (L, 2, 0));
|
||||||
|
|
||||||
struct lua_hook *hook = lua_plugin_push_hook (plugin, 1, XLUA_HOOK_INPUT);
|
|
||||||
hook->data.input_hook.vtable = &lua_input_hook_vtable;
|
hook->data.input_hook.vtable = &lua_input_hook_vtable;
|
||||||
hook->data.input_hook.priority = priority;
|
plugin->ctx->input_hooks =
|
||||||
input_hook_insert (plugin->ctx, &hook->data.input_hook);
|
hook_insert (plugin->ctx->input_hooks, &hook->data.hook);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7716,13 +7683,11 @@ static int
|
|||||||
lua_plugin_hook_irc (lua_State *L)
|
lua_plugin_hook_irc (lua_State *L)
|
||||||
{
|
{
|
||||||
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
|
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
|
||||||
luaL_checktype (L, 1, LUA_TFUNCTION);
|
struct lua_hook *hook = lua_plugin_push_hook
|
||||||
lua_Integer priority = luaL_optinteger (L, 2, 0);
|
(plugin, 1, XLUA_HOOK_IRC, luaL_optinteger (L, 2, 0));
|
||||||
|
|
||||||
struct lua_hook *hook = lua_plugin_push_hook (plugin, 1, XLUA_HOOK_IRC);
|
|
||||||
hook->data.irc_hook.vtable = &lua_irc_hook_vtable;
|
hook->data.irc_hook.vtable = &lua_irc_hook_vtable;
|
||||||
hook->data.irc_hook.priority = priority;
|
plugin->ctx->irc_hooks =
|
||||||
irc_hook_insert (plugin->ctx, &hook->data.irc_hook);
|
hook_insert (plugin->ctx->irc_hooks, &hook->data.hook);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9520,8 +9485,9 @@ static char *
|
|||||||
process_input_hooks (struct app_context *ctx, struct buffer *buffer,
|
process_input_hooks (struct app_context *ctx, struct buffer *buffer,
|
||||||
char *input)
|
char *input)
|
||||||
{
|
{
|
||||||
LIST_FOR_EACH (struct input_hook, hook, ctx->input_hooks)
|
LIST_FOR_EACH (struct hook, iter, ctx->input_hooks)
|
||||||
{
|
{
|
||||||
|
struct input_hook *hook = (struct input_hook *) iter;
|
||||||
char *processed = hook->vtable->filter (hook, buffer, input);
|
char *processed = hook->vtable->filter (hook, buffer, input);
|
||||||
if (input == processed)
|
if (input == processed)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user