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 |