-#include "hook.h"
+#include <lttv/hook.h>
-typedef struct _lttv_hook_closure {
- lttv_hook hook;
+
+typedef struct _LttvHookClosure {
+ LttvHook hook;
void *hook_data;
-} lttv_hook_closure;
+} LttvHookClosure;
-inline lttv_hooks *lttv_hooks_new() {
- return g_array_new(FALSE, FALSE, sizeof(lttv_hook_closure));
+LttvHooks *lttv_hooks_new()
+{
+ return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
}
-/* MD: delete elements of the array also, but don't free pointed addresses
- * (functions).
- */
-inline void lttv_hooks_destroy(lttv_hooks *h) {
+
+void lttv_hooks_destroy(LttvHooks *h)
+{
g_array_free(h, TRUE);
}
-inline void lttv_hooks_add(lttv_hooks *h, lttv_hook f, void *hook_data) {
- lttv_hook_closure c;
- /* if h is null, do nothing, or popup a warning message */
- if(h == NULL)return;
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data)
+{
+ LttvHookClosure c;
+
+ if(h == NULL)g_error("Null hook added");
c.hook = f;
c.hook_data = hook_data;
}
-void lttv_hooks_call(lttv_hooks *h, void *call_data)
+void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list)
{
- int i;
- lttv_hook_closure * c;
+ guint i;
+
+ if(list == NULL) return;
+ for(i = 0 ; i < list->len; i++) {
+ g_array_append_val(h,g_array_index(list, LttvHookClosure, i));
+ }
+}
+
+
+void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
+{
+ unsigned i;
+
+ void *hook_data;
+
+ LttvHookClosure *c;
for(i = 0 ; i < h->len ; i++) {
- c = ((lttv_hook_closure *)h->data) + i;
- if(c != NULL)
- c->hook(c->hook_data,call_data);
- else
- g_critical("NULL hook called\n");
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook == f) {
+ hook_data = c->hook_data;
+ lttv_hooks_remove_by_position(h, i);
+ return hook_data;
+ }
+ }
+ return NULL;
+}
+
+
+void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
+{
+ unsigned i;
+
+ LttvHookClosure *c;
+
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook == f && c->hook_data == hook_data) {
+ lttv_hooks_remove_by_position(h, i);
+ return;
+ }
+ }
+}
+
+
+void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
+{
+ guint i, j;
+
+ LttvHookClosure *c, *c_list;
+
+ if(list == NULL) return;
+ for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ c_list = &g_array_index(list, LttvHookClosure, j);
+ if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
+ lttv_hooks_remove_by_position(h, i);
+ j++;
+ }
+ else i++;
+ }
+
+ /* Normally the hooks in h are ordered as in list. If this is not the case,
+ try harder here. */
+
+ if(j < list->len) {
+ for(; j < list->len ; j++) {
+ c_list = &g_array_index(list, LttvHookClosure, j);
+ lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
+ }
+ }
+}
+
+
+unsigned lttv_hooks_number(LttvHooks *h)
+{
+ return h->len;
+}
+
+
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data)
+{
+ LttvHookClosure *c;
+
+ c = &g_array_index(h, LttvHookClosure, i);
+ *f = c->hook;
+ *hook_data = c->hook_data;
+}
+
+
+void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
+{
+ g_array_remove_index(h, i);
+}
+
+
+gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
+{
+ gboolean ret = FALSE;
+
+ LttvHookClosure *c;
+
+ guint i;
+
+ if(h != NULL) {
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ ret = ret || c->hook(c->hook_data,call_data);
+ }
}
+ return ret;
}
-/* Sometimes different hooks need to be called based on the case. The
- case is represented by an unsigned integer id and may represent different
- event types, for instance. */
+gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
+{
+ LttvHookClosure *c;
+
+ guint i;
-inline lttv_hooks_by_id *lttv_hooks_by_id_new() {
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook(c->hook_data,call_data)) return TRUE;
+ }
+ return FALSE;
+}
+
+
+LttvHooksById *lttv_hooks_by_id_new()
+{
return g_ptr_array_new();
}
-inline void lttv_hooks_by_id_destroy(lttv_hooks_by_id *h) {
- /* MD: delete elements of the array also */
+void lttv_hooks_by_id_destroy(LttvHooksById *h)
+{
+ guint i;
+
+ for(i = 0 ; i < h->len ; i++) {
+ if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
+ }
g_ptr_array_free(h, TRUE);
}
-void lttv_hooks_by_id_add(lttv_hooks_by_id *h, lttv_hook f, void *hook_data,
- unsigned int id)
+LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
{
- if(h->len < id) g_ptr_array_set_size(h, id);
+ if(h->len <= id) g_ptr_array_set_size(h, id + 1);
if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
- lttv_hooks_add(h->pdata[id], f, hook_data);
+ return h->pdata[id];
+}
+
+
+unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
+{
+ return h->len;
}
-void lttv_hooks_by_id_call(lttv_hooks_by_id *h, void *call_data, unsigned int id)
+
+LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
{
- if(h->len <= id || h->pdata[id] == NULL) return;
- lttv_hooks_call(h->pdata[id],call_data);
+ if(id < h->len) return h->pdata[id];
+ return NULL;
+}
+
+
+void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
+{
+ if(id < h->len && h->pdata[id] != NULL) {
+ lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
+ h->pdata[id] = NULL;
+ }
}