| 58 /*{{{ is/cast */ |
58 /*{{{ is/cast */ |
| 59 |
59 |
| 60 |
60 |
| 61 bool obj_is(const Obj *obj, const ClassDescr *descr) |
61 bool obj_is(const Obj *obj, const ClassDescr *descr) |
| 62 { |
62 { |
| 63 ClassDescr *d; |
63 ClassDescr *d; |
| 64 |
64 |
| 65 if(obj==NULL) |
65 if(obj==NULL) |
| 66 return FALSE; |
66 return FALSE; |
| 67 |
67 |
| 68 d=obj->obj_type; |
68 d=obj->obj_type; |
| 69 |
69 |
| 70 while(d!=NULL){ |
70 while(d!=NULL){ |
| 71 if(d==descr) |
71 if(d==descr) |
| 72 return TRUE; |
72 return TRUE; |
| 73 d=d->ancestor; |
73 d=d->ancestor; |
| 74 } |
74 } |
| 75 return FALSE; |
75 return FALSE; |
| 76 } |
76 } |
| 77 |
77 |
| 78 |
78 |
| 79 bool obj_is_str(const Obj *obj, const char *str) |
79 bool obj_is_str(const Obj *obj, const char *str) |
| 80 { |
80 { |
| 81 ClassDescr *d; |
81 ClassDescr *d; |
| 82 |
82 |
| 83 if(obj==NULL || str==NULL) |
83 if(obj==NULL || str==NULL) |
| 84 return FALSE; |
84 return FALSE; |
| 85 |
85 |
| 86 d=obj->obj_type; |
86 d=obj->obj_type; |
| 87 |
87 |
| 88 while(d!=NULL){ |
88 while(d!=NULL){ |
| 89 if(strcmp(d->name, str)==0) |
89 if(strcmp(d->name, str)==0) |
| 90 return TRUE; |
90 return TRUE; |
| 91 d=d->ancestor; |
91 d=d->ancestor; |
| 92 } |
92 } |
| 93 return FALSE; |
93 return FALSE; |
| 94 } |
94 } |
| 95 |
95 |
| 96 |
96 |
| 97 const void *obj_cast(const Obj *obj, const ClassDescr *descr) |
97 const void *obj_cast(const Obj *obj, const ClassDescr *descr) |
| 98 { |
98 { |
| 99 ClassDescr *d; |
99 ClassDescr *d; |
| 100 |
100 |
| 101 if(obj==NULL) |
101 if(obj==NULL) |
| 102 return NULL; |
102 return NULL; |
| 103 |
103 |
| 104 d=obj->obj_type; |
104 d=obj->obj_type; |
| 105 |
105 |
| 106 while(d!=NULL){ |
106 while(d!=NULL){ |
| 107 if(d==descr) |
107 if(d==descr) |
| 108 return (void*)obj; |
108 return (void*)obj; |
| 109 d=d->ancestor; |
109 d=d->ancestor; |
| 110 } |
110 } |
| 111 return NULL; |
111 return NULL; |
| 112 } |
112 } |
| 113 |
113 |
| 114 |
114 |
| 115 /*}}}*/ |
115 /*}}}*/ |
| 116 |
116 |
| 125 } |
125 } |
| 126 |
126 |
| 127 |
127 |
| 128 static int comp_fun(const void *a, const void *b) |
128 static int comp_fun(const void *a, const void *b) |
| 129 { |
129 { |
| 130 void *af=(void*)((DynFunTab*)a)->func; |
130 void *af=(void*)((DynFunTab*)a)->func; |
| 131 void *bf=(void*)((DynFunTab*)b)->func; |
131 void *bf=(void*)((DynFunTab*)b)->func; |
| 132 |
132 |
| 133 return (af<bf ? -1 : (af==bf ? 0 : 1)); |
133 return (af<bf ? -1 : (af==bf ? 0 : 1)); |
| 134 } |
134 } |
| 135 |
135 |
| 136 |
136 |
| 137 DynFun *lookup_dynfun(const Obj *obj, DynFun *func, |
137 DynFun *lookup_dynfun(const Obj *obj, DynFun *func, |
| 138 bool *funnotfound) |
138 bool *funnotfound) |
| 139 { |
139 { |
| 140 ClassDescr *descr; |
140 ClassDescr *descr; |
| 141 DynFunTab *df; |
141 DynFunTab *df; |
| 142 /*DynFunTab dummy={NULL, NULL};*/ |
142 /*DynFunTab dummy={NULL, NULL};*/ |
| 143 /*dummy.func=func;*/ |
143 /*dummy.func=func;*/ |
| 144 |
144 |
| 145 if(obj==NULL) |
145 if(obj==NULL) |
| 146 return NULL; |
146 return NULL; |
| 147 |
147 |
| 148 descr=obj->obj_type; |
148 descr=obj->obj_type; |
| 149 |
149 |
| 150 for(; descr!=&Obj_classdescr; descr=descr->ancestor){ |
150 for(; descr!=&Obj_classdescr; descr=descr->ancestor){ |
| 151 if(descr->funtab==NULL) |
151 if(descr->funtab==NULL) |
| 152 continue; |
152 continue; |
| 153 |
153 |
| 154 if(descr->funtab_n==-1){ |
154 if(descr->funtab_n==-1){ |
| 155 /* Need to sort the table. */ |
155 /* Need to sort the table. */ |
| 156 descr->funtab_n=0; |
156 descr->funtab_n=0; |
| 157 df=descr->funtab; |
157 df=descr->funtab; |
| 158 while(df->func!=NULL){ |
158 while(df->func!=NULL){ |
| 159 descr->funtab_n++; |
159 descr->funtab_n++; |
| 160 df++; |
160 df++; |
| 161 } |
161 } |
| 162 |
162 |
| 163 if(descr->funtab_n>0){ |
163 if(descr->funtab_n>0){ |
| 164 qsort(descr->funtab, descr->funtab_n, sizeof(DynFunTab), |
164 qsort(descr->funtab, descr->funtab_n, sizeof(DynFunTab), |
| 165 comp_fun); |
165 comp_fun); |
| 166 } |
166 } |
| 167 } |
167 } |
| 168 |
168 |
| 169 /* |
169 /* |
| 170 if(descr->funtab_n==0) |
170 if(descr->funtab_n==0) |
| 171 continue; |
171 continue; |
| 172 |
172 |
| 173 df=(DynFunTab*)bsearch(&dummy, descr->funtab, descr->funtab_n, |
173 df=(DynFunTab*)bsearch(&dummy, descr->funtab, descr->funtab_n, |
| 174 sizeof(DynFunTab), comp_fun); |
174 sizeof(DynFunTab), comp_fun); |
| 175 if(df!=NULL){ |
175 if(df!=NULL){ |
| 176 *funnotfound=FALSE; |
176 *funnotfound=FALSE; |
| 177 return df->handler; |
177 return df->handler; |
| 178 } |
178 } |
| 179 */ |
179 */ |
| 180 |
180 |
| 181 /* Using custom bsearch instead of the one in libc is probably |
181 /* Using custom bsearch instead of the one in libc is probably |
| 182 * faster as the overhead of calling a comparison function would |
182 * faster as the overhead of calling a comparison function would |
| 183 * be significant given that the comparisons are simple and |
183 * be significant given that the comparisons are simple and |
| 184 * funtab_n not that big. |
184 * funtab_n not that big. |
| 185 */ |
185 */ |
| 186 { |
186 { |
| 187 int min=0, max=descr->funtab_n-1; |
187 int min=0, max=descr->funtab_n-1; |
| 188 int ndx; |
188 int ndx; |
| 189 df=descr->funtab; |
189 df=descr->funtab; |
| 190 while(max>=min){ |
190 while(max>=min){ |
| 191 ndx=(max+min)/2; |
191 ndx=(max+min)/2; |
| 192 if((void*)df[ndx].func==(void*)func){ |
192 if((void*)df[ndx].func==(void*)func){ |
| 193 *funnotfound=FALSE; |
193 *funnotfound=FALSE; |
| 194 return df[ndx].handler; |
194 return df[ndx].handler; |
| 195 } |
195 } |
| 196 if((void*)df[ndx].func<(void*)func) |
196 if((void*)df[ndx].func<(void*)func) |
| 197 min=ndx+1; |
197 min=ndx+1; |
| 198 else |
198 else |
| 199 max=ndx-1; |
199 max=ndx-1; |
| 200 } |
200 } |
| 201 } |
201 } |
| 202 } |
202 } |
| 203 |
203 |
| 204 *funnotfound=TRUE; |
204 *funnotfound=TRUE; |
| 205 return dummy_dyn; |
205 return dummy_dyn; |
| 206 } |
206 } |
| 207 |
207 |
| 208 |
208 |
| 209 bool has_dynfun(const Obj *obj, DynFun *func) |
209 bool has_dynfun(const Obj *obj, DynFun *func) |
| 210 { |
210 { |
| 211 bool funnotfound; |
211 bool funnotfound; |
| 212 lookup_dynfun(obj, func, &funnotfound); |
212 lookup_dynfun(obj, func, &funnotfound); |
| 213 return !funnotfound; |
213 return !funnotfound; |
| 214 } |
214 } |
| 215 |
215 |
| 216 |
216 |
| 217 /*}}}*/ |
217 /*}}}*/ |
| 218 |
218 |
| 220 /*{{{ Watches */ |
220 /*{{{ Watches */ |
| 221 |
221 |
| 222 |
222 |
| 223 bool watch_setup(Watch *watch, Obj *obj, WatchHandler *handler) |
223 bool watch_setup(Watch *watch, Obj *obj, WatchHandler *handler) |
| 224 { |
224 { |
| 225 if(OBJ_IS_BEING_DESTROYED(obj)) |
225 if(OBJ_IS_BEING_DESTROYED(obj)) |
| 226 return FALSE; |
226 return FALSE; |
| 227 |
227 |
| 228 watch_reset(watch); |
228 watch_reset(watch); |
| 229 |
229 |
| 230 watch->handler=handler; |
230 watch->handler=handler; |
| 231 LINK_ITEM(obj->obj_watches, watch, next, prev); |
231 LINK_ITEM(obj->obj_watches, watch, next, prev); |
| 232 watch->obj=obj; |
232 watch->obj=obj; |
| 233 |
233 |
| 234 return TRUE; |
234 return TRUE; |
| 235 } |
235 } |
| 236 |
236 |
| 237 void do_watch_reset(Watch *watch, bool call) |
237 void do_watch_reset(Watch *watch, bool call) |
| 238 { |
238 { |
| 239 WatchHandler *handler=watch->handler; |
239 WatchHandler *handler=watch->handler; |
| 240 Obj *obj=watch->obj; |
240 Obj *obj=watch->obj; |
| 241 |
241 |
| 242 watch->handler=NULL; |
242 watch->handler=NULL; |
| 243 |
243 |
| 244 if(obj==NULL) |
244 if(obj==NULL) |
| 245 return; |
245 return; |
| 246 |
246 |
| 247 UNLINK_ITEM(obj->obj_watches, watch, next, prev); |
247 UNLINK_ITEM(obj->obj_watches, watch, next, prev); |
| 248 watch->obj=NULL; |
248 watch->obj=NULL; |
| 249 |
249 |
| 250 if(call && handler!=NULL) |
250 if(call && handler!=NULL) |
| 251 handler(watch, obj); |
251 handler(watch, obj); |
| 252 } |
252 } |
| 253 |
253 |
| 254 |
254 |
| 255 void watch_reset(Watch *watch) |
255 void watch_reset(Watch *watch) |
| 256 { |
256 { |
| 257 do_watch_reset(watch, FALSE); |
257 do_watch_reset(watch, FALSE); |
| 258 } |
258 } |
| 259 |
259 |
| 260 |
260 |
| 261 bool watch_ok(Watch *watch) |
261 bool watch_ok(Watch *watch) |
| 262 { |
262 { |
| 263 return watch->obj!=NULL; |
263 return watch->obj!=NULL; |
| 264 } |
264 } |
| 265 |
265 |
| 266 |
266 |
| 267 static void do_watches(Obj *obj, bool call) |
267 static void do_watches(Obj *obj, bool call) |
| 268 { |
268 { |
| 269 Watch *watch, *next; |
269 Watch *watch, *next; |
| 270 |
270 |
| 271 watch=obj->obj_watches; |
271 watch=obj->obj_watches; |
| 272 |
272 |
| 273 while(watch!=NULL){ |
273 while(watch!=NULL){ |
| 274 next=watch->next; |
274 next=watch->next; |
| 275 do_watch_reset(watch, call); |
275 do_watch_reset(watch, call); |
| 276 watch=next; |
276 watch=next; |
| 277 } |
277 } |
| 278 } |
278 } |
| 279 |
279 |
| 280 |
280 |
| 281 void watch_call(Obj *obj) |
281 void watch_call(Obj *obj) |
| 282 { |
282 { |
| 283 do_watches(obj, FALSE); |
283 do_watches(obj, FALSE); |
| 284 } |
284 } |
| 285 |
285 |
| 286 |
286 |
| 287 void watch_init(Watch *watch) |
287 void watch_init(Watch *watch) |
| 288 { |
288 { |
| 289 watch->obj=NULL; |
289 watch->obj=NULL; |
| 290 watch->next=NULL; |
290 watch->next=NULL; |
| 291 watch->prev=NULL; |
291 watch->prev=NULL; |
| 292 watch->handler=NULL; |
292 watch->handler=NULL; |
| 293 } |
293 } |
| 294 |
294 |
| 295 |
295 |
| 296 /*}}}*/ |
296 /*}}}*/ |
| 297 |
297 |