Fix:Core:Cleaned up callback handling
[navit-package] / navit / callback.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <glib.h>
21 #include <string.h>
22 #include "item.h"
23 #include "debug.h"
24 #include "callback.h"
25
26 struct callback {
27         void (*func)();
28         int pcount;
29         enum attr_type type;
30         void *p[0];
31         
32 };
33
34 struct callback_list {
35         GList *list;
36 };
37
38 struct callback_list *
39 callback_list_new(void)
40 {
41         struct callback_list *ret=g_new0(struct callback_list, 1);
42         
43         return ret;
44 }
45
46 struct callback *
47 callback_new_attr(void (*func)(void), enum attr_type type, int pcount, void **p)
48 {
49         struct callback *ret;
50         int i;
51
52         ret=g_malloc0(sizeof(struct callback)+pcount*sizeof(void *));
53         ret->func=func;
54         ret->pcount=pcount;
55         ret->type=type;
56         for (i = 0 ; i < pcount ; i++) {
57                 ret->p[i]=p[i];
58         }       
59         return ret;
60 }
61
62 struct callback *
63 callback_new_attr_args(void (*func)(void), enum attr_type type, int count, ...)
64 {
65         int i;
66         void *p[count];
67         va_list ap;
68         va_start(ap, count);
69         for (i = 0 ; i < count ; i++)
70                 p[i]=va_arg(ap, void *);
71         va_end(ap);
72         return callback_new_attr(func, type, count, p);
73 }
74
75 struct callback *
76 callback_new(void (*func)(void), int pcount, void **p)
77 {
78         return callback_new_attr(func, attr_none, pcount, p);
79 }
80
81 struct callback *
82 callback_new_args(void (*func)(void), int count, ...)
83 {
84         int i;
85         void *p[count];
86         va_list ap;
87         va_start(ap, count);
88         for (i = 0 ; i < count ; i++)
89                 p[i]=va_arg(ap, void *);
90         va_end(ap);
91         return callback_new(func, count, p);
92 }
93
94 void
95 callback_destroy(struct callback *cb)
96 {
97         g_free(cb);
98 }
99
100 void
101 callback_set_arg(struct callback *cb, int arg, void *p)
102 {
103         if (arg < 0 || arg > cb->pcount)
104                 return;
105         cb->p[arg]=p;
106 }
107
108 void
109 callback_list_add(struct callback_list *l, struct callback *cb)
110 {
111         l->list=g_list_prepend(l->list, cb);
112 }
113
114
115 struct callback *
116 callback_list_add_new(struct callback_list *l, void (*func)(void), int pcount, void **p)
117 {
118         struct callback *ret;
119         
120         ret=callback_new(func, pcount, p);      
121         callback_list_add(l, ret);
122         return ret;
123 }
124
125 void
126 callback_list_remove(struct callback_list *l, struct callback *cb)
127 {
128         l->list=g_list_remove(l->list, cb);
129 }
130
131 void
132 callback_list_remove_destroy(struct callback_list *l, struct callback *cb)
133 {
134         callback_list_remove(l, cb);
135         g_free(cb);
136 }
137
138 void
139 callback_call(struct callback *cb, int pcount, void **p)
140 {
141         int i;
142         void *pf[8];
143         if (! cb)
144                 return;
145         if (cb->pcount + pcount <= 8) {
146                 dbg(1,"cb->pcount=%d\n", cb->pcount);
147                 if (cb->pcount && cb->p) 
148                         dbg(1,"cb->p[0]=%p\n", cb->p[0]);
149                 dbg(1,"pcount=%d\n", pcount);
150                 if (pcount && p) 
151                         dbg(1,"p[0]=%p\n", p[0]);
152                 for (i = 0 ; i < cb->pcount ; i++) 
153                         pf[i]=cb->p[i];
154                 for (i = 0 ; i < pcount ; i++)
155                         pf[i+cb->pcount]=p[i];
156                 switch (cb->pcount+pcount) {
157                 case 8:
158                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6],pf[7]);
159                         break;
160                 case 7:
161                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6]);
162                         break;
163                 case 6:
164                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5]);
165                         break;
166                 case 5:
167                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4]);
168                         break;
169                 case 4:
170                         cb->func(pf[0],pf[1],pf[2],pf[3]);
171                         break;
172                 case 3:
173                         cb->func(pf[0],pf[1],pf[2]);
174                         break;
175                 case 2:
176                         cb->func(pf[0],pf[1]);
177                         break;
178                 case 1:
179                         cb->func(pf[0]);
180                         break;
181                 case 0:
182                         cb->func();
183                         break;
184                 }
185         } else {
186                 dbg(0,"too many parameters for callback (%d+%d)\n", cb->pcount, pcount);
187         }
188 }
189
190 void
191 callback_call_args(struct callback *cb, int count, ...)
192 {
193         int i;
194         void *p[count];
195         va_list ap;
196         va_start(ap, count);
197         for (i = 0 ; i < count ; i++)
198                 p[i]=va_arg(ap, void *);
199         va_end(ap);
200         callback_call(cb, count, p);
201 }
202
203 void
204 callback_list_call_attr(struct callback_list *l, enum attr_type type, int pcount, void **p)
205 {
206         GList *cbi;
207         struct callback *cb;
208
209         cbi=l->list;
210         while (cbi) {
211                 cb=cbi->data;
212                 if (type == attr_any || cb->type == attr_any || cb->type == type)
213                         callback_call(cb, pcount, p);
214                 cbi=g_list_next(cbi);
215         }
216         
217 }
218
219 void
220 callback_list_call_attr_args(struct callback_list *cbl, enum attr_type type, int count, ...)
221 {
222         int i;
223         void *p[count];
224         va_list ap;
225         va_start(ap, count);
226         for (i = 0 ; i < count ; i++)
227                 p[i]=va_arg(ap, void *);
228         va_end(ap);
229         callback_list_call_attr(cbl, type, count, p);
230 }
231
232 void
233 callback_list_call(struct callback_list *l, int pcount, void **p)
234 {
235         callback_list_call_attr(l, attr_any, pcount, p);
236 }
237
238 void
239 callback_list_call_args(struct callback_list *cbl, int count, ...)
240 {
241         int i;
242         void *p[count];
243         va_list ap;
244         va_start(ap, count);
245         for (i = 0 ; i < count ; i++)
246                 p[i]=va_arg(ap, void *);
247         va_end(ap);
248         callback_list_call(cbl, count, p);
249 }
250
251 void 
252 callback_list_destroy(struct callback_list *l)
253 {
254         GList *cbi;
255         cbi=l->list;
256         while (cbi) {
257                 g_free(cbi->data);
258                 cbi=g_list_next(cbi);
259         }
260         g_list_free(l->list);
261         g_free(l);
262 }