#include "x-hook.h"
#include <stdlib.h>
#include <assert.h>
#define CELL_NEW(f,d) X_PFX (list_prepend) ((x_list *) (f), (d))
#define CELL_FREE(c) X_PFX (list_free_1) (c)
#define CELL_FUN(c) ((x_hook_function *) ((c)->next))
#define CELL_DATA(c) ((c)->data)
X_EXTERN x_list *
X_PFX (hook_add) (x_list *lst, x_hook_function *fun, void *data)
{
return X_PFX (list_prepend) (lst, CELL_NEW (fun, data));
}
X_EXTERN x_list *
X_PFX (hook_remove) (x_list *lst, x_hook_function *fun, void *data)
{
x_list *node, *cell;
x_list *to_delete = NULL;
for (node = lst; node != NULL; node = node->next)
{
cell = node->data;
if (CELL_FUN (cell) == fun && CELL_DATA (cell) == data)
to_delete = X_PFX (list_prepend) (to_delete, cell);
}
for (node = to_delete; node != NULL; node = node->next)
{
cell = node->data;
lst = X_PFX (list_remove) (lst, cell);
CELL_FREE (cell);
}
X_PFX (list_free) (to_delete);
}
X_EXTERN void
X_PFX (hook_run) (x_list *lst, void *arg)
{
x_list *node, *cell;
x_hook_function **fun;
void **data;
int length, i;
length = X_PFX (list_length) (lst);
fun = alloca (sizeof (x_hook_function *) * length);
data = alloca (sizeof (void *) * length);
for (i = 0, node = lst; node != NULL; node = node->next, i++)
{
cell = node->data;
fun[i] = CELL_FUN (cell);
data[i] = CELL_DATA (cell);
}
for (i = 0; i < length; i++)
{
(*fun[i]) (arg, data[i]);
}
}
X_EXTERN void
X_PFX (hook_free) (x_list *lst)
{
x_list *node;
for (node = lst; node != NULL; node = node->next)
{
CELL_FREE (node->data);
}
X_PFX (list_free) (lst);
}