Refine the interactions between the hooks provided by the different modules.
[lttv.git] / ltt / branches / poly / lttv / hook.c
index eb7c5d9f194a302d9d3d0f4f1104320419e460cb..12f121986606473f211a86a533c648f4d2c66e8f 100644 (file)
@@ -1,28 +1,29 @@
 #include <lttv/hook.h>
 
 
-typedef struct _lttv_hook_closure {
+typedef struct _LttvHookClosure {
   lttv_hook 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;
@@ -30,47 +31,173 @@ inline void lttv_hooks_add(lttv_hooks *h, lttv_hook f, void *hook_data) {
 }
 
 
-int lttv_hooks_call(lttv_hooks *h, void *call_data)
+void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) 
+{
+  guint i;
+
+  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 = &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)
 {
-  int i;
-  lttv_hook_closure * c;
+  unsigned i;
+
+  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 && 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;
+
+  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);
+    }
   }
 }
 
 
-/* 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. */
+unsigned lttv_hooks_number(LttvHooks *h)
+{
+  return h->len;
+}
 
-inline lttv_hooks_by_id *lttv_hooks_by_id_new() {
+
+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;
+
+  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;
+}
+
+
+gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
+{
+  LttvHookClosure *c;
+
+  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];
 }
 
-void lttv_hooks_by_id_call(lttv_hooks_by_id *h, void *call_data, unsigned int id)
+
+unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
 {
-  if(h->len <= id || h->pdata[id] == NULL) return;
-  lttv_hooks_call(h->pdata[id],call_data);
+  return h->len;
+}
+
+
+LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
+{
+  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;
+  }
 }
 
This page took 0.024254 seconds and 4 git commands to generate.