From 364eb009ca5f22f9c8994578853e24fdd6e883a3 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Sat, 21 Nov 2015 18:40:07 +0100
Subject: degesch: hook implementation cleanup
---
degesch.c | 152 ++++++++++++++++++++++++--------------------------------------
1 file changed, 59 insertions(+), 93 deletions(-)
diff --git a/degesch.c b/degesch.c
index 6bd0449..3a80c3f 100644
--- a/degesch.c
+++ b/degesch.c
@@ -1390,12 +1390,45 @@ plugin_destroy (struct plugin *self)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-struct input_hook
+// 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 input_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 hook super; ///< Common hook fields
struct input_hook_vtable *vtable; ///< Methods
- int priority; ///< The lesser the sooner
};
struct input_hook_vtable
@@ -1410,10 +1443,8 @@ struct input_hook_vtable
struct irc_hook
{
- LIST_HEADER (struct irc_hook)
-
+ struct hook super; ///< Common hook fields
struct irc_hook_vtable *vtable; ///< Methods
- int priority; ///< The lesser the sooner
};
struct irc_hook_vtable
@@ -1487,8 +1518,8 @@ struct app_context
int terminal_suspended; ///< Terminal suspension level
struct plugin *plugins; ///< Loaded plugins
- struct input_hook *input_hooks; ///< Input hooks
- struct irc_hook *irc_hooks; ///< IRC hooks
+ struct hook *input_hooks; ///< Input hooks
+ struct hook *irc_hooks; ///< IRC hooks
}
*g_ctx;
@@ -4116,8 +4147,9 @@ static char *
irc_process_hooks (struct server *s, char *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);
if (input == processed)
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 ---------------------------------------------------------------------
// 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
union
{
+ struct hook hook; ///< Base structure
struct input_hook input_hook; ///< Input hook
struct irc_hook irc_hook; ///< IRC hook
}
@@ -7514,10 +7480,10 @@ lua_hook_unhook (lua_State *L)
switch (hook->type)
{
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;
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;
default:
hard_assert (!"invalid hook type");
@@ -7679,13 +7645,16 @@ struct irc_hook_vtable lua_irc_hook_vtable =
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static struct lua_hook *
-lua_plugin_push_hook
- (struct lua_plugin *plugin, int callback_index, enum lua_hook_type type)
+lua_plugin_push_hook (struct lua_plugin *plugin, int callback_index,
+ enum lua_hook_type type, int priority)
{
lua_State *L = plugin->L;
+ luaL_checktype (L, callback_index, LUA_TFUNCTION);
+
struct lua_hook *hook = lua_newuserdata (L, sizeof *hook);
luaL_setmetatable (L, XLUA_HOOK_METATABLE);
memset (hook, 0, sizeof *hook);
+ hook->data.hook.priority = priority;
hook->type = type;
hook->plugin = plugin;
@@ -7702,13 +7671,11 @@ static int
lua_plugin_hook_input (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
- luaL_checktype (L, 1, LUA_TFUNCTION);
- lua_Integer priority = luaL_optinteger (L, 2, 0);
-
- struct lua_hook *hook = lua_plugin_push_hook (plugin, 1, XLUA_HOOK_INPUT);
+ struct lua_hook *hook = lua_plugin_push_hook
+ (plugin, 1, XLUA_HOOK_INPUT, luaL_optinteger (L, 2, 0));
hook->data.input_hook.vtable = &lua_input_hook_vtable;
- hook->data.input_hook.priority = priority;
- input_hook_insert (plugin->ctx, &hook->data.input_hook);
+ plugin->ctx->input_hooks =
+ hook_insert (plugin->ctx->input_hooks, &hook->data.hook);
return 1;
}
@@ -7716,13 +7683,11 @@ static int
lua_plugin_hook_irc (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
- luaL_checktype (L, 1, LUA_TFUNCTION);
- lua_Integer priority = luaL_optinteger (L, 2, 0);
-
- struct lua_hook *hook = lua_plugin_push_hook (plugin, 1, XLUA_HOOK_IRC);
+ struct lua_hook *hook = lua_plugin_push_hook
+ (plugin, 1, XLUA_HOOK_IRC, luaL_optinteger (L, 2, 0));
hook->data.irc_hook.vtable = &lua_irc_hook_vtable;
- hook->data.irc_hook.priority = priority;
- irc_hook_insert (plugin->ctx, &hook->data.irc_hook);
+ plugin->ctx->irc_hooks =
+ hook_insert (plugin->ctx->irc_hooks, &hook->data.hook);
return 1;
}
@@ -9520,8 +9485,9 @@ static char *
process_input_hooks (struct app_context *ctx, struct buffer *buffer,
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);
if (input == processed)
continue;
--
cgit v1.2.3-70-g09d2