obj.c

changeset 62
aae5facf9fc5
parent 60
a4033700e35c
equal deleted inserted replaced
61:fc585645ad05 62:aae5facf9fc5
25 /*{{{ Destroy */ 25 /*{{{ Destroy */
26 26
27 27
28 void destroy_obj(Obj *obj) 28 void destroy_obj(Obj *obj)
29 { 29 {
30 ClassDescr *d; 30 ClassDescr *d;
31 31
32 if(OBJ_IS_BEING_DESTROYED(obj)) 32 if(OBJ_IS_BEING_DESTROYED(obj))
33 return; 33 return;
34 34
35 obj->flags|=OBJ_DEST; 35 obj->flags|=OBJ_DEST;
36 36
37 do_watches(obj, TRUE); 37 do_watches(obj, TRUE);
38 38
39 d=obj->obj_type; 39 d=obj->obj_type;
40 40
41 while(d!=NULL){ 41 while(d!=NULL){
42 if(d->destroy_fn!=NULL){ 42 if(d->destroy_fn!=NULL){
43 d->destroy_fn(obj); 43 d->destroy_fn(obj);
44 break; 44 break;
45 } 45 }
46 d=d->ancestor; 46 d=d->ancestor;
47 } 47 }
48 48
49 do_watches(obj, FALSE); 49 do_watches(obj, FALSE);
50 50
51 free(obj); 51 free(obj);
52 } 52 }
53 53
54 54
55 /*}}}*/ 55 /*}}}*/
56 56
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

mercurial