Hooks by priority
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
index a7f0960db27f9bd1b5f018c6cabb3ee8aaa9c840..f92b397d3bbb1c370a97721a7574ca2414180dbb 100644 (file)
 
 
 typedef struct _LttvHookClosure {
-  LttvHook hook;
-  void *hook_data;
+  LttvHook      hook;
+  void         *hook_data;
+  LttvHookPrio  prio;
 } LttvHookClosure;
 
+gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b)
+{
+  if(a->prio < b->prio) return -1;
+  if(a->prio > b->prio) return 1;
+  return 0;
+}
+
 
 LttvHooks *lttv_hooks_new() 
 {
@@ -39,7 +47,7 @@ void lttv_hooks_destroy(LttvHooks *h)
 }
 
 
-void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data) 
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p
 {
   LttvHookClosure c;
 
@@ -47,7 +55,9 @@ void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data)
 
   c.hook = f;
   c.hook_data = hook_data;
+  c.prio = p;
   g_array_append_val(h,c);
+  g_array_sort(h, (GCompareFunc)lttv_hooks_prio_compare);
 }
 
 
@@ -59,6 +69,7 @@ void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list)
   for(i = 0 ; i < list->len; i++) {
     g_array_append_val(h,g_array_index(list, LttvHookClosure, i));
   }
+  g_array_sort(h, (GCompareFunc)lttv_hooks_prio_compare);
 }
 
 
@@ -133,13 +144,23 @@ unsigned lttv_hooks_number(LttvHooks *h)
 }
 
 
-void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data)
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
+                                              LttvHookPrio *p)
 {
   LttvHookClosure *c;
 
+  if(i >= h->len)
+  {
+    *f = NULL;
+    *hook_data = NULL;
+    *p = 0;
+    return;
+  }
+  
   c = &g_array_index(h, LttvHookClosure, i);
   *f = c->hook;
   *hook_data = c->hook_data;
+  *p = c->prio;
 }
 
 
@@ -148,7 +169,6 @@ 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, sum_ret = FALSE;
@@ -181,6 +201,107 @@ gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
   return FALSE;
 }
 
+gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
+                               LttvHooks *h2, void *call_data2)
+{
+  gboolean ret, sum_ret = FALSE;
+
+  LttvHookClosure *c1, *c2;
+
+  guint i, j;
+
+  if(h1 != NULL && h2 != NULL) {
+    for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      if(c1->prio <= c2->prio) {
+        ret = c1->hook(c1->hook_data,call_data1);
+        sum_ret = sum_ret || ret;
+        i++;
+      }
+      else {
+        ret = c2->hook(c2->hook_data,call_data2);
+        sum_ret = sum_ret || ret;
+        j++;
+      }
+    }
+    /* Finish the last list with hooks left */
+    for(;i < h1->len; i++) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      ret = c1->hook(c1->hook_data,call_data1);
+      sum_ret = sum_ret || ret;
+    }
+    for(;j < h2->len; j++) {
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      ret = c2->hook(c2->hook_data,call_data2);
+      sum_ret = sum_ret || ret;
+    }
+  }
+  else if(h1 != NULL && h2 == NULL) {
+    for(i = 0 ; i < h1->len ; i++) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      ret = c1->hook(c1->hook_data,call_data1);
+      sum_ret = sum_ret || ret;
+    }
+  } 
+  else if(h1 == NULL && h2 != NULL) {
+    for(j = 0 ; j < h2->len ; j++) {
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      ret = c2->hook(c2->hook_data,call_data2);
+      sum_ret = sum_ret || ret;
+    }
+  }
+
+  return sum_ret;
+}
+
+gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
+                                     LttvHooks *h2, void *call_data2)
+{
+  LttvHookClosure *c1, *c2;
+
+  guint i, j;
+
+  if(h1 != NULL && h2 != NULL) {
+    for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      if(c1->prio <= c2->prio) {
+        if(c1->hook(c1->hook_data,call_data1)) return TRUE;
+        i++;
+      }
+      else {
+        if(c2->hook(c2->hook_data,call_data2)) return TRUE;
+        j++;
+      }
+    }
+    /* Finish the last list with hooks left */
+    for(;i < h1->len; i++) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      if(c1->hook(c1->hook_data,call_data1)) return TRUE;
+    }
+    for(;j < h2->len; j++) {
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      if(c2->hook(c2->hook_data,call_data2)) return TRUE;
+    }
+  }
+  else if(h1 != NULL && h2 == NULL) {
+    for(i = 0 ; i < h1->len ; i++) {
+      c1 = &g_array_index(h1, LttvHookClosure, i);
+      if(c1->hook(c1->hook_data,call_data1)) return TRUE;
+    }
+  } 
+  else if(h1 == NULL && h2 != NULL) {
+    for(j = 0 ; j < h2->len ; j++) {
+      c2 = &g_array_index(h2, LttvHookClosure, j);
+      if(c2->hook(c2->hook_data,call_data2)) return TRUE;
+    }
+  }
+
+  return FALSE;
+
+}
+
 
 LttvHooksById *lttv_hooks_by_id_new() 
 {
This page took 0.024547 seconds and 4 git commands to generate.