add implementation details
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
ffd54a90 19
3d218f2a 20#include <lttv/hook.h>
eccb5352 21
22
dc877563 23typedef struct _LttvHookClosure {
47e76340 24 LttvHook hook;
25 void *hook_data;
26 LttvHookPrio prio;
dc877563 27} LttvHookClosure;
eccb5352 28
47e76340 29gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b)
30{
31 if(a->prio < b->prio) return -1;
32 if(a->prio > b->prio) return 1;
33 return 0;
34}
35
eccb5352 36
dc877563 37LttvHooks *lttv_hooks_new()
38{
39 return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
eccb5352 40}
41
dc877563 42
43void lttv_hooks_destroy(LttvHooks *h)
44{
2a2fa4f0 45 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
eccb5352 46 g_array_free(h, TRUE);
47}
48
eccb5352 49
47e76340 50void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p)
dc877563 51{
bb545b3c 52 LttvHookClosure *c, new_c;
53 guint i;
54
dc877563 55 if(h == NULL)g_error("Null hook added");
eccb5352 56
bb545b3c 57 new_c.hook = f;
58 new_c.hook_data = hook_data;
59 new_c.prio = p;
60 for(i = 0; i < h->len; i++) {
61
62 c = &g_array_index(h, LttvHookClosure, i);
63 if(new_c.prio < c->prio) {
64 g_array_insert_val(h,i,new_c);
65 return;
66 }
67 }
68 if(i == h->len)
69 g_array_append_val(h,new_c);
eccb5352 70}
71
bb545b3c 72/* lttv_hooks_add_list
73 *
74 * Adds a sorted list into another sorted list.
75 *
76 * Note : h->len is modified, but only incremented. This assures
77 * its coherence through the function.
78 *
79 * j is an index to the element following the last one added in the
80 * destination array.
81 */
82void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list)
dc877563 83{
bb545b3c 84 guint i,j;
85 LttvHookClosure *c;
86 const LttvHookClosure *new_c;
dc877563 87
ffd54a90 88 if(list == NULL) return;
bb545b3c 89 for(i = 0, j = 0 ; i < list->len; i++) {
90 new_c = &g_array_index(list, LttvHookClosure, i);
91 while(j < h->len) {
92 c = &g_array_index(h, LttvHookClosure, j);
93 if(new_c->prio < c->prio) {
94 g_array_insert_val(h,j,*new_c);
95 j++;
96 break;
97 }
98 else j++;
99 }
100 if(j == h->len) {
101 g_array_append_val(h,*new_c);
102 j++;
103 }
dc877563 104 }
105}
106
107
108void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
109{
110 unsigned i;
111
112 void *hook_data;
113
114 LttvHookClosure *c;
115
116 for(i = 0 ; i < h->len ; i++) {
117 c = &g_array_index(h, LttvHookClosure, i);
118 if(c->hook == f) {
119 hook_data = c->hook_data;
120 lttv_hooks_remove_by_position(h, i);
121 return hook_data;
122 }
123 }
124 return NULL;
125}
126
127
128void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
eccb5352 129{
dc877563 130 unsigned i;
131
132 LttvHookClosure *c;
eccb5352 133
134 for(i = 0 ; i < h->len ; i++) {
dc877563 135 c = &g_array_index(h, LttvHookClosure, i);
136 if(c->hook == f && c->hook_data == hook_data) {
137 lttv_hooks_remove_by_position(h, i);
138 return;
139 }
140 }
141}
142
143
144void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
145{
146 guint i, j;
147
148 LttvHookClosure *c, *c_list;
149
ffd54a90 150 if(list == NULL) return;
dc877563 151 for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
152 c = &g_array_index(h, LttvHookClosure, i);
153 c_list = &g_array_index(list, LttvHookClosure, j);
154 if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
155 lttv_hooks_remove_by_position(h, i);
156 j++;
157 }
158 else i++;
159 }
160
161 /* Normally the hooks in h are ordered as in list. If this is not the case,
162 try harder here. */
163
164 if(j < list->len) {
165 for(; j < list->len ; j++) {
166 c_list = &g_array_index(list, LttvHookClosure, j);
167 lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
168 }
eccb5352 169 }
170}
171
172
dc877563 173unsigned lttv_hooks_number(LttvHooks *h)
174{
175 return h->len;
176}
eccb5352 177
dc877563 178
47e76340 179void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
180 LttvHookPrio *p)
dc877563 181{
182 LttvHookClosure *c;
183
47e76340 184 if(i >= h->len)
185 {
186 *f = NULL;
187 *hook_data = NULL;
188 *p = 0;
189 return;
190 }
191
dc877563 192 c = &g_array_index(h, LttvHookClosure, i);
193 *f = c->hook;
194 *hook_data = c->hook_data;
47e76340 195 *p = c->prio;
dc877563 196}
197
198
ffd54a90 199void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
dc877563 200{
ffd54a90 201 g_array_remove_index(h, i);
dc877563 202}
203
dc877563 204gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
205{
b445142a 206 gboolean ret, sum_ret = FALSE;
dc877563 207
208 LttvHookClosure *c;
209
ffd54a90 210 guint i;
211
dc877563 212 if(h != NULL) {
213 for(i = 0 ; i < h->len ; i++) {
214 c = &g_array_index(h, LttvHookClosure, i);
b445142a 215 ret = c->hook(c->hook_data,call_data);
216 sum_ret = sum_ret || ret;
dc877563 217 }
218 }
b445142a 219 return sum_ret;
dc877563 220}
221
222
223gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
224{
225 LttvHookClosure *c;
226
ffd54a90 227 guint i;
228
dc877563 229 for(i = 0 ; i < h->len ; i++) {
230 c = &g_array_index(h, LttvHookClosure, i);
231 if(c->hook(c->hook_data,call_data)) return TRUE;
232 }
233 return FALSE;
234}
235
47e76340 236gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
237 LttvHooks *h2, void *call_data2)
238{
239 gboolean ret, sum_ret = FALSE;
240
241 LttvHookClosure *c1, *c2;
242
243 guint i, j;
244
245 if(h1 != NULL && h2 != NULL) {
246 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
247 c1 = &g_array_index(h1, LttvHookClosure, i);
248 c2 = &g_array_index(h2, LttvHookClosure, j);
249 if(c1->prio <= c2->prio) {
250 ret = c1->hook(c1->hook_data,call_data1);
251 sum_ret = sum_ret || ret;
252 i++;
253 }
254 else {
255 ret = c2->hook(c2->hook_data,call_data2);
256 sum_ret = sum_ret || ret;
257 j++;
258 }
259 }
260 /* Finish the last list with hooks left */
261 for(;i < h1->len; i++) {
262 c1 = &g_array_index(h1, LttvHookClosure, i);
263 ret = c1->hook(c1->hook_data,call_data1);
264 sum_ret = sum_ret || ret;
265 }
266 for(;j < h2->len; j++) {
267 c2 = &g_array_index(h2, LttvHookClosure, j);
268 ret = c2->hook(c2->hook_data,call_data2);
269 sum_ret = sum_ret || ret;
270 }
271 }
272 else if(h1 != NULL && h2 == NULL) {
273 for(i = 0 ; i < h1->len ; i++) {
274 c1 = &g_array_index(h1, LttvHookClosure, i);
275 ret = c1->hook(c1->hook_data,call_data1);
276 sum_ret = sum_ret || ret;
277 }
278 }
279 else if(h1 == NULL && h2 != NULL) {
280 for(j = 0 ; j < h2->len ; j++) {
281 c2 = &g_array_index(h2, LttvHookClosure, j);
282 ret = c2->hook(c2->hook_data,call_data2);
283 sum_ret = sum_ret || ret;
284 }
285 }
286
287 return sum_ret;
288}
289
290gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
291 LttvHooks *h2, void *call_data2)
292{
293 LttvHookClosure *c1, *c2;
294
295 guint i, j;
296
297 if(h1 != NULL && h2 != NULL) {
298 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
299 c1 = &g_array_index(h1, LttvHookClosure, i);
300 c2 = &g_array_index(h2, LttvHookClosure, j);
301 if(c1->prio <= c2->prio) {
302 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
303 i++;
304 }
305 else {
306 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
307 j++;
308 }
309 }
310 /* Finish the last list with hooks left */
311 for(;i < h1->len; i++) {
312 c1 = &g_array_index(h1, LttvHookClosure, i);
313 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
314 }
315 for(;j < h2->len; j++) {
316 c2 = &g_array_index(h2, LttvHookClosure, j);
317 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
318 }
319 }
320 else if(h1 != NULL && h2 == NULL) {
321 for(i = 0 ; i < h1->len ; i++) {
322 c1 = &g_array_index(h1, LttvHookClosure, i);
323 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
324 }
325 }
326 else if(h1 == NULL && h2 != NULL) {
327 for(j = 0 ; j < h2->len ; j++) {
328 c2 = &g_array_index(h2, LttvHookClosure, j);
329 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
330 }
331 }
332
333 return FALSE;
334
335}
336
dc877563 337
338LttvHooksById *lttv_hooks_by_id_new()
339{
eccb5352 340 return g_ptr_array_new();
341}
342
343
dc877563 344void lttv_hooks_by_id_destroy(LttvHooksById *h)
345{
346 guint i;
347
348 for(i = 0 ; i < h->len ; i++) {
349 if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
350 }
eccb5352 351 g_ptr_array_free(h, TRUE);
352}
353
354
ffd54a90 355LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
eccb5352 356{
dc877563 357 if(h->len <= id) g_ptr_array_set_size(h, id + 1);
eccb5352 358 if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
dc877563 359 return h->pdata[id];
eccb5352 360}
361
dc877563 362
363unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
eccb5352 364{
dc877563 365 return h->len;
366}
367
368
369LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
370{
371 if(id < h->len) return h->pdata[id];
372 return NULL;
373}
374
375
376void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
377{
378 if(id < h->len && h->pdata[id] != NULL) {
379 lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
380 h->pdata[id] = NULL;
381 }
eccb5352 382}
383
This page took 0.0565600000000001 seconds and 4 git commands to generate.