* added qt_speedup.patch
[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) {
151                         dbg_assert(p!=NULL); 
152                         dbg(1,"p[0]=%p\n", p[0]);
153                 }
154                 for (i = 0 ; i < cb->pcount ; i++) 
155                         pf[i]=cb->p[i];
156                 for (i = 0 ; i < pcount ; i++)
157                         pf[i+cb->pcount]=p[i];
158                 switch (cb->pcount+pcount) {
159                 case 8:
160                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6],pf[7]);
161                         break;
162                 case 7:
163                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6]);
164                         break;
165                 case 6:
166                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5]);
167                         break;
168                 case 5:
169                         cb->func(pf[0],pf[1],pf[2],pf[3],pf[4]);
170                         break;
171                 case 4:
172                         cb->func(pf[0],pf[1],pf[2],pf[3]);
173                         break;
174                 case 3:
175                         cb->func(pf[0],pf[1],pf[2]);
176                         break;
177                 case 2:
178                         cb->func(pf[0],pf[1]);
179                         break;
180                 case 1:
181                         cb->func(pf[0]);
182                         break;
183                 case 0:
184                         cb->func();
185                         break;
186                 }
187         } else {
188                 dbg(0,"too many parameters for callback (%d+%d)\n", cb->pcount, pcount);
189         }
190 }
191
192 void
193 callback_call_args(struct callback *cb, int count, ...)
194 {
195         int i;
196         void *p[count];
197         va_list ap;
198         va_start(ap, count);
199         for (i = 0 ; i < count ; i++)
200                 p[i]=va_arg(ap, void *);
201         va_end(ap);
202         callback_call(cb, count, p);
203 }
204
205 void
206 callback_list_call_attr(struct callback_list *l, enum attr_type type, int pcount, void **p)
207 {
208         GList *cbi;
209         struct callback *cb;
210
211         if (!l) {
212                 return;
213         }
214
215         cbi=l->list;
216         while (cbi) {
217                 cb=cbi->data;
218                 if (type == attr_any || cb->type == attr_any || cb->type == type)
219                         callback_call(cb, pcount, p);
220                 cbi=g_list_next(cbi);
221         }
222         
223 }
224
225 void
226 callback_list_call_attr_args(struct callback_list *cbl, enum attr_type type, int count, ...)
227 {
228         int i;
229         void *p[count];
230         va_list ap;
231         va_start(ap, count);
232         for (i = 0 ; i < count ; i++)
233                 p[i]=va_arg(ap, void *);
234         va_end(ap);
235         callback_list_call_attr(cbl, type, count, p);
236 }
237
238 void
239 callback_list_call(struct callback_list *l, int pcount, void **p)
240 {
241         callback_list_call_attr(l, attr_any, pcount, p);
242 }
243
244 void
245 callback_list_call_args(struct callback_list *cbl, int count, ...)
246 {
247         int i;
248         void *p[count];
249         va_list ap;
250         va_start(ap, count);
251         for (i = 0 ; i < count ; i++)
252                 p[i]=va_arg(ap, void *);
253         va_end(ap);
254         callback_list_call(cbl, count, p);
255 }
256
257 void 
258 callback_list_destroy(struct callback_list *l)
259 {
260         GList *cbi;
261         cbi=l->list;
262         while (cbi) {
263                 g_free(cbi->data);
264                 cbi=g_list_next(cbi);
265         }
266         g_list_free(l->list);
267         g_free(l);
268 }