91a90a7b160a5cb1ddb605822b7e27016c15314b
[profile/ivi/eobj.git] / lib / eo.c
1 #include <Eina.h>
2
3 #include "Eo.h"
4 #include "eo_private.h"
5
6 #include "config.h"
7
8 /* The last id that should be reserved for statically allocated classes. */
9 #define EO_STATIC_IDS_LAST 10
10
11 /* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
12 EAPI Eina_Lock _eo_class_creation_lock;
13 int _eo_log_dom = -1;
14
15 static Eo_Class **_eo_classes;
16 static Eo_Class_Id _eo_classes_last_id;
17 static Eina_Bool _eo_init_count = 0;
18
19 static void _eo_condtor_reset(Eo *obj);
20 static inline Eina_Bool _eo_error_get(const Eo *obj);
21 static inline void _eo_error_unset(Eo *obj);
22 static inline void *_eo_data_get(const Eo *obj, const Eo_Class *klass);
23 static inline Eo *_eo_ref(Eo *obj);
24 static inline void _eo_unref(Eo *obj);
25
26 typedef struct
27 {
28    Eo_Op op;
29    const Eo_Class **kls_itr;
30 } Eo_Kls_Itr;
31
32 struct _Eo {
33      EINA_MAGIC
34      EINA_INLIST;
35      Eo *parent;
36      Eina_Inlist *children;
37      const Eo_Class *klass;
38      int refcount;
39 #ifndef NDEBUG
40      Eina_Inlist *xrefs;
41 #endif
42
43      Eina_List *composite_objects;
44
45      Eo_Kls_Itr mro_itr;
46
47      Eina_Bool construct_error:1;
48      Eina_Bool condtor_done:1;
49
50      Eina_Bool composite:1;
51      Eina_Bool del:1;
52      Eina_Bool manual_free:1;
53 };
54
55 /* Start of Dich */
56 /* Dich search, split to 0xff 0xff 0xffff */
57
58 #define DICH_CHAIN1_MASK (0xffff)
59 #define DICH_CHAIN_LAST_MASK (0xffff)
60 #define DICH_CHAIN1(x) (((x) >> 16) & DICH_CHAIN1_MASK)
61 #define DICH_CHAIN_LAST(x) ((x) & DICH_CHAIN_LAST_MASK)
62
63 #define OP_CLASS_OFFSET_GET(x) (((x) >> EO_OP_CLASS_OFFSET) & 0xffff)
64 #define OP_CLASS_GET(op) ({ \
65       Eo_Class_Id tmp = OP_CLASS_OFFSET_GET(op); \
66       ID_CLASS_GET(tmp); \
67       })
68 #define OP_SUB_ID_GET(op) ((op) & 0xffff)
69
70 #define ID_CLASS_GET(id) ({ \
71       (Eo_Class *) ((id <= _eo_classes_last_id) && (id > 0)) ? \
72       (_eo_classes[id - 1]) : NULL; \
73       })
74
75 #define EO_ALIGN_SIZE(size) \
76         ((size) + (sizeof(void *) - ((size) % sizeof(void *))))
77
78 /* Structure of Eo_Op is:
79  * 16bit: class
80  * 16bit: op.
81  */
82
83 typedef struct _Dich_Chain1 Dich_Chain1;
84
85 typedef struct
86 {
87    eo_op_func_type func;
88    const Eo_Class *src;
89 } op_type_funcs;
90
91 struct _Dich_Chain1
92 {
93    op_type_funcs *funcs;
94 };
95
96 typedef struct
97 {
98      EINA_INLIST;
99      const Eo_Class *klass;
100 } Eo_Extension_Node;
101
102 typedef struct
103 {
104      const Eo_Class *klass;
105      size_t offset;
106 } Eo_Extension_Data_Offset;
107
108 struct _Eo_Class
109 {
110    EINA_MAGIC
111    Eo_Class_Id class_id;
112    const Eo_Class *parent;
113    const Eo_Class_Description *desc;
114    Dich_Chain1 *chain; /**< The size is class_id */
115    Eina_Inlist *extensions;
116
117    Eo_Extension_Data_Offset *extn_data_off;
118    size_t extn_data_size;
119
120    const Eo_Class **mro;
121    Eo_Kls_Itr mro_itr;
122
123    size_t data_offset; /* < Offset of the data within object data. */
124
125    Eina_Bool constructed : 1;
126 };
127
128 static inline void
129 _dich_chain_alloc(Dich_Chain1 *chain1, size_t num_ops)
130 {
131    if (!chain1->funcs)
132      {
133         chain1->funcs = calloc(num_ops, sizeof(*(chain1->funcs)));
134      }
135 }
136
137 static inline void
138 _dich_copy_all(Eo_Class *dst, const Eo_Class *src)
139 {
140    if (!src->chain) return;
141
142    if (!dst->chain)
143      {
144         dst->chain = calloc(dst->class_id, sizeof(*dst->chain));
145      }
146
147    Eo_Class_Id i;
148    const Dich_Chain1 *sc1 = src->chain;
149    Dich_Chain1 *dc1 = dst->chain;
150    for (i = 0 ; i < src->class_id ; i++, sc1++, dc1++)
151      {
152         if (sc1->funcs)
153           {
154              size_t j;
155              const Eo_Class *op_klass = ID_CLASS_GET(i + 1);
156              /* Can be NULL because of future static classes. */
157              if (!op_klass)
158                 continue;
159
160              size_t num_ops = op_klass->desc->ops.count;
161              _dich_chain_alloc(dc1, num_ops);
162
163              const op_type_funcs *sf = sc1->funcs;
164              op_type_funcs *df = dc1->funcs;
165              for (j = 0 ; j < num_ops ; j++, df++, sf++)
166                {
167                   if (sf->func)
168                     {
169                        memcpy(df, sf, sizeof(*df));
170                     }
171                }
172           }
173      }
174 }
175
176 static inline const op_type_funcs *
177 _dich_func_get(const Eo_Class *klass, Eo_Op op)
178 {
179    if (!klass->chain) return NULL;
180
181    size_t idx1 = DICH_CHAIN1(op) - 1;
182    if (idx1 >= klass->class_id) return NULL;
183    const Dich_Chain1 *chain1 = &klass->chain[idx1];
184    if (!chain1->funcs) return NULL;
185
186    size_t idxl = DICH_CHAIN_LAST(op);
187    /* num_ops is calculated from the class. */
188    const Eo_Class *op_klass = ID_CLASS_GET(idx1 + 1);
189    if (!op_klass || (idxl >= op_klass->desc->ops.count))
190       return NULL;
191
192    return &chain1->funcs[idxl];
193 }
194
195 static inline void
196 _dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func)
197 {
198    const Eo_Class *op_klass = OP_CLASS_GET(op);
199    size_t num_ops;
200
201    /* Verify op is valid. */
202    if (op_klass)
203      {
204         /* num_ops is calculated from the class. */
205         num_ops = op_klass->desc->ops.count;
206         if (DICH_CHAIN_LAST(op) >= num_ops)
207           {
208              ERR("OP %x is too big for the domain '%s', expected value < %x.",
209                    op, op_klass->desc->name, op_klass->desc->ops.count);
210              return;
211           }
212      }
213    else
214      {
215         ERR("OP %x is from an illegal class.", op);
216         return;
217      }
218
219    if (!klass->chain)
220      {
221         klass->chain = calloc(klass->class_id, sizeof(*klass->chain));
222      }
223
224    size_t idx1 = DICH_CHAIN1(op) - 1;
225    Dich_Chain1 *chain1 = &klass->chain[idx1];
226    _dich_chain_alloc(chain1, num_ops);
227    chain1->funcs[DICH_CHAIN_LAST(op)].func = func;
228    chain1->funcs[DICH_CHAIN_LAST(op)].src = klass;
229 }
230
231 static inline void
232 _dich_func_clean_all(Eo_Class *klass)
233 {
234    size_t i;
235    Dich_Chain1 *chain1 = klass->chain;
236
237    if (!chain1)
238       return;
239
240    for (i = 0 ; i < klass->class_id ; i++, chain1++)
241      {
242         if (chain1->funcs)
243            free(chain1->funcs);
244      }
245    free(klass->chain);
246    klass->chain = NULL;
247 }
248
249 /* END OF DICH */
250
251 static const Eo_Op_Description noop_desc =
252         EO_OP_DESCRIPTION(EO_NOOP, "No operation.");
253
254 static const Eo_Op_Description *
255 _eo_op_id_desc_get(Eo_Op op)
256 {
257    const Eo_Class *klass = OP_CLASS_GET(op);
258    Eo_Op sub_id = OP_SUB_ID_GET(op);
259
260    if (op == EO_NOOP)
261       return &noop_desc;
262
263    if (klass && (sub_id < klass->desc->ops.count))
264       return klass->desc->ops.descs + sub_id;
265
266    return NULL;
267 }
268
269 static const char *
270 _eo_op_id_name_get(Eo_Op op)
271 {
272    const Eo_Op_Description *desc = _eo_op_id_desc_get(op);
273    return (desc) ? desc->name : NULL;
274 }
275
276 static inline void
277 _eo_kls_itr_init(const Eo_Class *obj_klass, Eo_Kls_Itr *cur, Eo_Op op, Eo_Kls_Itr *prev_state)
278 {
279    prev_state->op = cur->op;
280    prev_state->kls_itr = cur->kls_itr;
281
282    /* If we are in a constructor/destructor or we changed an op - init. */
283    if ((cur->op == EO_NOOP) || (cur->op != op))
284      {
285         cur->op = op;
286         cur->kls_itr = obj_klass->mro;
287      }
288 }
289
290 static inline void
291 _eo_kls_itr_end(Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state)
292 {
293    if (cur->op != prev_state->op)
294      {
295         cur->op = prev_state->op;
296         cur->kls_itr = prev_state->kls_itr;
297      }
298 }
299
300 static inline const Eo_Class *
301 _eo_kls_itr_get(Eo_Kls_Itr *cur)
302 {
303    return (cur->kls_itr) ? *(cur->kls_itr) : NULL;
304 }
305
306 static inline const Eo_Class *
307 _eo_kls_itr_next(Eo_Kls_Itr *cur, Eo_Op op)
308 {
309    if (cur->op != op)
310      {
311         Eo_Op node_op = cur->op;
312         ERR("Called with op %x ('%s') while expecting: %x ('%s'). This probaly means you called eo_*_super functions from a wrong place.",
313               op, _eo_op_id_name_get(op),
314               node_op, _eo_op_id_name_get(node_op));
315         return NULL;
316      }
317
318    const Eo_Class **kls_itr = cur->kls_itr;
319    if (*kls_itr)
320      {
321         const op_type_funcs *fsrc = _dich_func_get(*kls_itr, op);
322
323         while (*kls_itr && (*(kls_itr++) != fsrc->src))
324            ;
325
326         cur->kls_itr = kls_itr;
327         return *kls_itr;
328      }
329    else
330      {
331         return NULL;
332      }
333 }
334
335 static inline const op_type_funcs *
336 _eo_kls_itr_func_get(const Eo_Class *klass, Eo_Kls_Itr *mro_itr, Eo_Op op, Eo_Kls_Itr *prev_state)
337 {
338    _eo_kls_itr_init(klass, mro_itr, op, prev_state);
339    klass = _eo_kls_itr_get(mro_itr);
340    if (klass)
341      {
342         const op_type_funcs *func = _dich_func_get(klass, op);
343
344         if (func && func->func)
345           {
346              return func;
347           }
348      }
349
350    return NULL;
351 }
352
353 #define _EO_OP_ERR_NO_OP_PRINT(op, klass) \
354    do \
355       { \
356          const Eo_Class *op_klass = OP_CLASS_GET(op); \
357          const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL; \
358          ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.", \
359                op, _eo_op_id_name_get(op), _dom_name, \
360                (klass) ? klass->desc->name : NULL); \
361       } \
362    while (0)
363
364 static Eina_Bool
365 _eo_op_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, va_list *p_list)
366 {
367    Eina_Bool ret = EINA_FALSE;
368
369 #ifndef NDEBUG
370    const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
371
372    if (op_desc)
373      {
374         if (op_desc->op_type == EO_OP_TYPE_CLASS)
375           {
376              ERR("Tried calling a class op '%s' (%x) from a non-class context.", (op_desc) ? op_desc->name : NULL, op);
377              return EINA_FALSE;
378           }
379         else if ((op_type == EO_OP_TYPE_CONST) &&
380               (op_desc->op_type != EO_OP_TYPE_CONST))
381           {
382              ERR("Tried calling non-const or non-existant op '%s' (%x) from a const (query) function.", (op_desc) ? op_desc->name : NULL, op);
383              return EINA_FALSE;
384           }
385      }
386 #endif
387
388    Eo_Kls_Itr prev_state;
389
390      {
391         const op_type_funcs *func =
392            _eo_kls_itr_func_get(obj->klass, &obj->mro_itr, op, &prev_state);
393         if (func)
394           {
395              func->func(obj, _eo_data_get(obj, func->src), p_list);
396              ret = EINA_TRUE;
397              goto end;
398           }
399      }
400
401    /* Try composite objects */
402      {
403         Eina_List *itr;
404         Eo *emb_obj;
405         EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
406           {
407              if (_eo_op_internal(emb_obj, op_type, op, p_list))
408                {
409                   ret = EINA_TRUE;
410                   goto end;
411                }
412           }
413      }
414
415 end:
416    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
417    return ret;
418 }
419
420 EAPI Eina_Bool
421 eo_do_internal(Eo *obj, Eo_Op_Type op_type, ...)
422 {
423    Eina_Bool ret = EINA_TRUE;
424    Eo_Op op = EO_NOOP;
425    va_list p_list;
426
427    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
428
429    _eo_ref(obj);
430
431    va_start(p_list, op_type);
432
433    op = va_arg(p_list, Eo_Op);
434    while (op)
435      {
436         if (!_eo_op_internal(obj, op_type, op, &p_list))
437           {
438              _EO_OP_ERR_NO_OP_PRINT(op, obj->klass);
439              ret = EINA_FALSE;
440              break;
441           }
442         op = va_arg(p_list, Eo_Op);
443      }
444
445    va_end(p_list);
446
447    _eo_unref(obj);
448    return ret;
449 }
450
451 EAPI Eina_Bool
452 eo_do_super_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, ...)
453 {
454    const Eo_Class *nklass;
455    Eina_Bool ret = EINA_TRUE;
456    va_list p_list;
457    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
458
459    /* Advance the kls itr. */
460    nklass = _eo_kls_itr_next(&obj->mro_itr, op);
461
462    if (obj->mro_itr.op != op)
463       return EINA_FALSE;
464
465    va_start(p_list, op);
466    if (!_eo_op_internal(obj, op_type, op, &p_list))
467      {
468         _EO_OP_ERR_NO_OP_PRINT(op, nklass);
469         ret = EINA_FALSE;
470      }
471    va_end(p_list);
472
473    return ret;
474 }
475
476 static Eina_Bool
477 _eo_class_op_internal(Eo_Class *klass, Eo_Op op, va_list *p_list)
478 {
479    Eina_Bool ret = EINA_FALSE;
480
481 #ifndef NDEBUG
482    const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
483
484    if (op_desc)
485      {
486         if (op_desc->op_type != EO_OP_TYPE_CLASS)
487           {
488              ERR("Tried calling an instance op '%s' (%x) from a class context.", (op_desc) ? op_desc->name : NULL, op);
489              return EINA_FALSE;
490           }
491      }
492 #endif
493
494    Eo_Kls_Itr prev_state;
495
496      {
497         const op_type_funcs *func =
498            _eo_kls_itr_func_get(klass, &klass->mro_itr, op, &prev_state);
499         if (func)
500           {
501              ((eo_op_func_type_class) func->func)(klass, p_list);
502              ret = EINA_TRUE;
503              goto end;
504           }
505      }
506
507 end:
508    _eo_kls_itr_end(&klass->mro_itr, &prev_state);
509    return ret;
510 }
511
512 EAPI Eina_Bool
513 eo_class_do_internal(const Eo_Class *klass, ...)
514 {
515    Eina_Bool ret = EINA_TRUE;
516    Eo_Op op = EO_NOOP;
517    va_list p_list;
518
519    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
520
521    va_start(p_list, klass);
522
523    op = va_arg(p_list, Eo_Op);
524    while (op)
525      {
526         if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
527           {
528              _EO_OP_ERR_NO_OP_PRINT(op, klass);
529              ret = EINA_FALSE;
530              break;
531           }
532         op = va_arg(p_list, Eo_Op);
533      }
534
535    va_end(p_list);
536
537    return ret;
538 }
539
540 EAPI Eina_Bool
541 eo_class_do_super_internal(const Eo_Class *klass, Eo_Op op, ...)
542 {
543    const Eo_Class *nklass;
544    Eina_Bool ret = EINA_TRUE;
545    va_list p_list;
546    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
547
548    /* Advance the kls itr. */
549    nklass = _eo_kls_itr_next(&((Eo_Class *) klass)->mro_itr, op);
550
551    if (klass->mro_itr.op != op)
552       return EINA_FALSE;
553
554    va_start(p_list, op);
555    if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
556      {
557         _EO_OP_ERR_NO_OP_PRINT(op, nklass);
558         ret = EINA_FALSE;
559      }
560    va_end(p_list);
561
562    return ret;
563 }
564
565 EAPI const Eo_Class *
566 eo_class_get(const Eo *obj)
567 {
568    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
569
570    return obj->klass;
571 }
572
573 EAPI const char *
574 eo_class_name_get(const Eo_Class *klass)
575 {
576    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
577
578    return klass->desc->name;
579 }
580
581 static void
582 _eo_class_base_op_init(Eo_Class *klass)
583 {
584    const Eo_Class_Description *desc = klass->desc;
585    if (!desc || !desc->ops.base_op_id)
586       return;
587
588    *(desc->ops.base_op_id) = EO_CLASS_ID_TO_BASE_ID(klass->class_id);
589 }
590
591 #ifndef NDEBUG
592 static Eina_Bool
593 _eo_class_mro_has(const Eo_Class *klass, const Eo_Class *find)
594 {
595    const Eo_Class **itr;
596    for (itr = klass->mro ; *itr ; itr++)
597      {
598         if (*itr == find)
599           {
600              return EINA_TRUE;
601           }
602      }
603
604    return EINA_FALSE;
605 }
606 #endif
607
608 static Eina_List *
609 _eo_class_mro_add(Eina_List *mro, const Eo_Class *klass)
610 {
611    Eina_List *extn_pos = NULL;
612    Eina_Bool check_consistency = !mro;
613    if (!klass)
614       return mro;
615
616    mro = eina_list_append(mro, klass);
617
618    /* Recursively add extenions. */
619      {
620         Eo_Extension_Node *extn;
621         EINA_INLIST_FOREACH(klass->extensions, extn)
622           {
623              mro = _eo_class_mro_add(mro, extn->klass);
624              /* Not possible: if (!mro) return NULL; */
625
626              if (check_consistency)
627                {
628                   extn_pos = eina_list_append(extn_pos, eina_list_last(mro));
629                }
630           }
631      }
632
633    /* Check if we can create a consistent mro. We only do it for the class
634     * we are working on (i.e no parents). */
635    if (check_consistency)
636      {
637         Eo_Extension_Node *extn;
638
639         Eina_List *itr = extn_pos;
640         EINA_INLIST_FOREACH(klass->extensions, extn)
641           {
642              /* Get the first one after the extension. */
643              Eina_List *extn_list = eina_list_next(eina_list_data_get(itr));
644
645              /* If we found the extension again. */
646              if (eina_list_data_find_list(extn_list, extn->klass))
647                {
648                   eina_list_free(mro);
649                   ERR("Cannot create a consistent method resolution order for class '%s' because of '%s'.", klass->desc->name, extn->klass->desc->name);
650                   return NULL;
651                }
652
653              itr = eina_list_next(itr);
654           }
655      }
656
657
658    mro = _eo_class_mro_add(mro, klass->parent);
659
660    return mro;
661 }
662
663 static Eina_Bool
664 _eo_class_mro_init(Eo_Class *klass)
665 {
666    Eina_List *mro = NULL;
667
668    DBG("Started creating MRO for class '%s'", klass->desc->name);
669    mro = _eo_class_mro_add(mro, klass);
670
671    if (!mro)
672       return EINA_FALSE;
673
674    /* Remove duplicates and make them the right order. */
675      {
676         Eina_List *itr1, *itr2, *itr2n;
677
678         itr1 = eina_list_last(mro);
679         while (itr1)
680           {
681              itr2 = eina_list_prev(itr1);
682
683              while (itr2)
684                {
685                   itr2n = eina_list_prev(itr2);
686
687                   if (eina_list_data_get(itr1) == eina_list_data_get(itr2))
688                     {
689                        mro = eina_list_remove_list(mro, itr2);
690                     }
691
692                   itr2 = itr2n;
693                }
694
695              itr1 = eina_list_prev(itr1);
696           }
697      }
698
699    /* Copy the mro and free the list. */
700      {
701         const Eo_Class *kls_itr;
702         const Eo_Class **mro_itr;
703         klass->mro = calloc(sizeof(*klass->mro), eina_list_count(mro) + 1);
704
705         mro_itr = klass->mro;
706
707         EINA_LIST_FREE(mro, kls_itr)
708           {
709              *(mro_itr++) = kls_itr;
710
711              DBG("Added '%s' to MRO", kls_itr->desc->name);
712           }
713         *(mro_itr) = NULL;
714      }
715
716    DBG("Finished creating MRO for class '%s'", klass->desc->name);
717
718    return EINA_TRUE;
719 }
720
721 static void
722 _eo_class_constructor(Eo_Class *klass)
723 {
724    if (klass->constructed)
725       return;
726
727    klass->constructed = EINA_TRUE;
728
729    if (klass->desc->class_constructor)
730       klass->desc->class_constructor(klass);
731 }
732
733 EAPI void
734 eo_class_funcs_set(Eo_Class *klass, const Eo_Op_Func_Description *func_descs)
735 {
736    EO_MAGIC_RETURN(klass, EO_CLASS_EINA_MAGIC);
737
738    const Eo_Op_Func_Description *itr;
739    itr = func_descs;
740    if (itr)
741      {
742         for ( ; itr->op_type != EO_OP_TYPE_INVALID ; itr++)
743           {
744              const Eo_Op_Description *op_desc = _eo_op_id_desc_get(itr->op);
745
746              if (EINA_UNLIKELY(!op_desc || (itr->op == EO_NOOP)))
747                {
748                   ERR("Setting implementation for non-existent op %x for class '%s'. Func index: %d", itr->op, klass->desc->name, itr - func_descs);
749                }
750              else if (EINA_LIKELY(itr->op_type == op_desc->op_type))
751                {
752                   _dich_func_set(klass, itr->op, itr->func);
753                }
754              else
755                {
756                   ERR("Set function's op type (%x) is different than the one in the op description (%d) for op '%s' in class '%s'. Func index: %d",
757                         itr->op_type,
758                         (op_desc) ? op_desc->op_type : EO_OP_TYPE_REGULAR,
759                         (op_desc) ? op_desc->name : NULL,
760                         klass->desc->name,
761                         itr - func_descs);
762                }
763           }
764      }
765 }
766
767 static void
768 eo_class_free(Eo_Class *klass)
769 {
770    if (klass->constructed)
771      {
772         if (klass->desc->class_destructor)
773            klass->desc->class_destructor(klass);
774
775         _dich_func_clean_all(klass);
776      }
777
778      {
779         Eina_Inlist *itrn;
780         Eo_Extension_Node *extn = NULL;
781         EINA_INLIST_FOREACH_SAFE(klass->extensions, itrn, extn)
782           {
783              free(extn);
784           }
785      }
786
787    if (klass->mro)
788       free(klass->mro);
789
790    if (klass->extn_data_off)
791       free(klass->extn_data_off);
792
793    free(klass);
794 }
795
796 /* DEVCHECK */
797 static Eina_Bool
798 _eo_class_check_op_descs(const Eo_Class *klass, Eo_Class_Id id)
799 {
800    const Eo_Class_Description *desc = klass->desc;
801    const Eo_Op_Description *itr;
802    size_t i;
803
804    if (desc->ops.count > 0)
805      {
806         if (((id == 0) || (id > EO_STATIC_IDS_LAST)) && !desc->ops.base_op_id)
807           {
808              ERR("Class '%s' has a non-zero ops count, but base_id is NULL.",
809                    desc->name);
810              return EINA_FALSE;
811           }
812
813         if (!desc->ops.descs)
814           {
815              ERR("Class '%s' has a non-zero ops count, but there are no descs.",
816                    desc->name);
817              return EINA_FALSE;
818           }
819      }
820
821    itr = desc->ops.descs;
822    for (i = 0 ; i < desc->ops.count ; i++, itr++)
823      {
824         if (itr->sub_op != i)
825           {
826              if (itr->name)
827                {
828                   ERR("Wrong order in Ops description for class '%s'. Expected %x and got %x", desc->name, i, itr->sub_op);
829                }
830              else
831                {
832                   ERR("Found too few Ops description for class '%s'. Expected %x descriptions, but found %x.", desc->name, desc->ops.count, i);
833                }
834              return EINA_FALSE;
835           }
836      }
837
838    if (itr && itr->name)
839      {
840         ERR("Found extra Ops description for class '%s'. Expected %d descriptions, but found more.", desc->name, desc->ops.count);
841         return EINA_FALSE;
842      }
843
844    return EINA_TRUE;
845 }
846
847 EAPI const Eo_Class *
848 eo_class_new(const Eo_Class_Description *desc, Eo_Class_Id id, const Eo_Class *parent, ...)
849 {
850    Eo_Class *klass;
851    va_list p_list;
852
853    if (parent && !EINA_MAGIC_CHECK(parent, EO_CLASS_EINA_MAGIC))
854      {
855         EINA_MAGIC_FAIL(parent, EO_CLASS_EINA_MAGIC);
856         return NULL;
857      }
858
859    if (id > EO_STATIC_IDS_LAST)
860      {
861         ERR("Tried creating a class with the static id %d while the maximum static id is %d. Aborting.", id, EO_STATIC_IDS_LAST);
862         return NULL;
863      }
864
865    va_start(p_list, parent);
866
867    EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
868    EINA_SAFETY_ON_NULL_RETURN_VAL(desc->name, NULL);
869
870    /* Check restrictions on Interface types. */
871    if (desc->type == EO_CLASS_TYPE_INTERFACE)
872      {
873         EINA_SAFETY_ON_FALSE_RETURN_VAL(!desc->class_constructor, NULL);
874         EINA_SAFETY_ON_FALSE_RETURN_VAL(!desc->class_destructor, NULL);
875         EINA_SAFETY_ON_FALSE_RETURN_VAL(!desc->data_size, NULL);
876      }
877
878    klass = calloc(1, sizeof(Eo_Class));
879    klass->parent = parent;
880
881    /* Handle class extensions */
882      {
883         Eo_Class *extn = NULL;
884
885         extn = va_arg(p_list, Eo_Class *);
886         while (extn)
887           {
888              switch (extn->desc->type)
889                {
890                 case EO_CLASS_TYPE_REGULAR:
891                 case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
892                    /* Use it like an interface. */
893                 case EO_CLASS_TYPE_INTERFACE:
894                    break;
895                 case EO_CLASS_TYPE_MIXIN:
896                      {
897                         Eo_Extension_Node *node = calloc(1, sizeof(*node));
898                         node->klass = extn;
899                         klass->extensions =
900                            eina_inlist_append(klass->extensions,
901                                  EINA_INLIST_GET(node));
902                      }
903                    break;
904                }
905
906              extn = va_arg(p_list, Eo_Class *);
907           }
908      }
909
910    klass->desc = desc;
911
912    /* Handle the inheritance */
913    if (klass->parent)
914      {
915         /* Verify the inheritance is allowed. */
916         switch (klass->desc->type)
917           {
918            case EO_CLASS_TYPE_REGULAR:
919            case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
920               if ((klass->parent->desc->type != EO_CLASS_TYPE_REGULAR) &&
921                     (klass->parent->desc->type != EO_CLASS_TYPE_REGULAR_NO_INSTANT))
922                 {
923                    ERR("Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
924                    goto cleanup;
925                 }
926               break;
927            case EO_CLASS_TYPE_INTERFACE:
928            case EO_CLASS_TYPE_MIXIN:
929               if ((klass->parent->desc->type != EO_CLASS_TYPE_INTERFACE) &&
930                     (klass->parent->desc->type != EO_CLASS_TYPE_MIXIN))
931                 {
932                    ERR("Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
933                    goto cleanup;
934                 }
935               break;
936           }
937
938
939         /* Update the current offset. */
940         /* FIXME: Make sure this alignment is enough. */
941         klass->data_offset = klass->parent->data_offset +
942            EO_ALIGN_SIZE(klass->parent->desc->data_size);
943      }
944
945    if (!_eo_class_check_op_descs(klass, id))
946      {
947         goto cleanup;
948      }
949
950    if (!_eo_class_mro_init(klass))
951      {
952         goto cleanup;
953      }
954
955    /* create MIXIN offset table. */
956      {
957         const Eo_Class **mro_itr = klass->mro;
958         Eo_Extension_Data_Offset *extn_data_itr;
959         size_t extn_num = 0;
960         size_t extn_data_off = klass->data_offset +
961            EO_ALIGN_SIZE(klass->desc->data_size);
962
963         /* FIXME: Make faster... */
964         while (*mro_itr)
965           {
966              if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
967                    ((*mro_itr)->desc->data_size > 0))
968                {
969                   extn_num++;
970                }
971              mro_itr++;
972           }
973
974         klass->extn_data_off = calloc(extn_num + 1,
975               sizeof(*klass->extn_data_off));
976
977         extn_data_itr = klass->extn_data_off;
978         mro_itr = klass->mro;
979         while (*mro_itr)
980           {
981              if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
982                    ((*mro_itr)->desc->data_size > 0))
983                {
984                   extn_data_itr->klass = *mro_itr;
985                   extn_data_itr->offset = extn_data_off;
986
987                   extn_data_off += EO_ALIGN_SIZE(extn_data_itr->klass->desc->data_size);
988                   extn_data_itr++;
989                }
990              mro_itr++;
991           }
992
993         klass->extn_data_size = extn_data_off;
994      }
995
996    eina_lock_take(&_eo_class_creation_lock);
997
998    if (id == 0)
999      {
1000         klass->class_id = ++_eo_classes_last_id;
1001      }
1002    else
1003      {
1004 #ifndef NDEBUG
1005         if (_eo_classes && _eo_classes[id - 1])
1006           {
1007              ERR("A class with id %d was already defined (%s). Aborting.", id,
1008                    _eo_classes[id - 1]->desc->name);
1009              eina_lock_release(&_eo_class_creation_lock);
1010              goto cleanup;
1011           }
1012 #endif
1013         klass->class_id = id;
1014      }
1015
1016
1017      {
1018         /* FIXME: Handle errors. */
1019         size_t arrsize = _eo_classes_last_id * sizeof(*_eo_classes);
1020         Eo_Class **tmp;
1021         tmp = realloc(_eo_classes, arrsize);
1022
1023         /* If it's the first allocation, memset. */
1024         if (!_eo_classes)
1025            memset(tmp, 0, arrsize);
1026
1027         _eo_classes = tmp;
1028         _eo_classes[klass->class_id - 1] = klass;
1029      }
1030    eina_lock_release(&_eo_class_creation_lock);
1031
1032    EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC);
1033
1034    /* Flatten the function array */
1035      {
1036         const Eo_Class **mro_itr = klass->mro;
1037         for (  ; *mro_itr ; mro_itr++)
1038            ;
1039
1040         /* Skip ourselves. */
1041         for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--)
1042           {
1043              _dich_copy_all(klass, *mro_itr);
1044           }
1045      }
1046
1047    _eo_class_base_op_init(klass);
1048
1049    _eo_class_constructor(klass);
1050
1051    va_end(p_list);
1052
1053    return klass;
1054
1055 cleanup:
1056    eo_class_free(klass);
1057    return NULL;
1058 }
1059
1060 EAPI Eina_Bool
1061 eo_parent_set(Eo *obj, const Eo *parent)
1062 {
1063    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
1064    if (parent)
1065       EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, EINA_FALSE);
1066
1067    if (obj->parent == parent)
1068       return EINA_TRUE;
1069
1070    _eo_ref(obj);
1071
1072    if (eo_composite_is(obj))
1073      {
1074         eo_composite_object_detach(obj->parent, obj);
1075      }
1076
1077    if (obj->parent)
1078      {
1079         obj->parent->children =
1080            eina_inlist_remove(obj->parent->children, EINA_INLIST_GET(obj));
1081         eo_xunref(obj, obj->parent);
1082      }
1083
1084    obj->parent = (Eo *) parent;
1085    if (obj->parent)
1086      {
1087         obj->parent->children =
1088            eina_inlist_append(obj->parent->children, EINA_INLIST_GET(obj));
1089         eo_xref(obj, obj->parent);
1090      }
1091
1092    _eo_unref(obj);
1093
1094    return EINA_TRUE;
1095 }
1096
1097 EAPI Eo *
1098 eo_add(const Eo_Class *klass, Eo *parent)
1099 {
1100    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1101
1102    if (parent) EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, NULL);
1103
1104    if (EINA_UNLIKELY(klass->desc->type != EO_CLASS_TYPE_REGULAR))
1105      {
1106         ERR("Class '%s' is not instantiate-able. Aborting.", klass->desc->name);
1107         return NULL;
1108      }
1109
1110    Eo *obj = calloc(1, EO_ALIGN_SIZE(sizeof(*obj)) +
1111          (klass->data_offset + EO_ALIGN_SIZE(klass->desc->data_size)) +
1112          klass->extn_data_size);
1113    EINA_MAGIC_SET(obj, EO_EINA_MAGIC);
1114    obj->refcount++;
1115    obj->klass = klass;
1116
1117    eo_parent_set(obj, parent);
1118
1119    Eo_Kls_Itr prev_state;
1120
1121    _eo_kls_itr_init(klass, &obj->mro_itr, EO_NOOP, &prev_state);
1122    _eo_error_unset(obj);
1123    _eo_condtor_reset(obj);
1124
1125    _eo_ref(obj);
1126    eo_do(obj, eo_constructor());
1127
1128    if (EINA_UNLIKELY(_eo_error_get(obj)))
1129      {
1130         ERR("Object of class '%s' - One of the object constructors have failed.", klass->desc->name);
1131         goto fail;
1132      }
1133
1134    if (!obj->condtor_done)
1135      {
1136         const Eo_Class *cur_klass = _eo_kls_itr_get(&obj->mro_itr);
1137         ERR("Object of class '%s' - Not all of the object constructors have been executed, last constructor was of class: '%s'", klass->desc->name, cur_klass->desc->name);
1138         goto fail;
1139      }
1140    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1141    _eo_unref(obj);
1142
1143    return obj;
1144
1145 fail:
1146    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1147    /* Unref twice, once for the ref above, and once for the basic object ref. */
1148    _eo_unref(obj);
1149    _eo_unref(obj);
1150    return NULL;
1151 }
1152
1153 typedef struct
1154 {
1155    EINA_INLIST;
1156    const Eo *ref_obj;
1157    const char *file;
1158    int line;
1159 } Eo_Xref_Node;
1160
1161 EAPI Eo *
1162 eo_xref_internal(Eo *obj, const Eo *ref_obj, const char *file, int line)
1163 {
1164    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1165
1166    _eo_ref(obj);
1167
1168 #ifndef NDEBUG
1169    Eo_Xref_Node *xref = calloc(1, sizeof(*xref));
1170    xref->ref_obj = ref_obj;
1171    xref->file = file;
1172    xref->line = line;
1173
1174    obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
1175 #else
1176    (void) ref_obj;
1177    (void) file;
1178    (void) line;
1179 #endif
1180
1181    return obj;
1182 }
1183
1184 EAPI void
1185 eo_xunref(Eo *obj, const Eo *ref_obj)
1186 {
1187    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1188 #ifndef NDEBUG
1189    Eo_Xref_Node *xref = NULL;
1190    EINA_INLIST_FOREACH(obj->xrefs, xref)
1191      {
1192         if (xref->ref_obj == ref_obj)
1193            break;
1194      }
1195
1196    if (xref)
1197      {
1198         obj->xrefs = eina_inlist_remove(obj->xrefs, EINA_INLIST_GET(xref));
1199         free(xref);
1200      }
1201    else
1202      {
1203         ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj, obj);
1204         return;
1205      }
1206 #else
1207    (void) ref_obj;
1208 #endif
1209    _eo_unref(obj);
1210 }
1211
1212 static inline Eo *
1213 _eo_ref(Eo *obj)
1214 {
1215    obj->refcount++;
1216    return obj;
1217 }
1218
1219 EAPI Eo *
1220 eo_ref(const Eo *_obj)
1221 {
1222    Eo *obj = (Eo *) _obj;
1223    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1224
1225    return _eo_ref(obj);
1226 }
1227
1228 static inline void
1229 _eo_del_internal(Eo *obj)
1230 {
1231    /* We need that for the event callbacks that may ref/unref. */
1232    obj->refcount++;
1233
1234    eo_do(obj, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
1235
1236    const Eo_Class *klass = eo_class_get(obj);
1237    Eo_Kls_Itr prev_state;
1238
1239    _eo_kls_itr_init(klass, &obj->mro_itr, EO_NOOP, &prev_state);
1240    _eo_error_unset(obj);
1241    _eo_condtor_reset(obj);
1242
1243    eo_do(obj, eo_destructor());
1244    if (_eo_error_get(obj))
1245      {
1246         ERR("Object of class '%s' - One of the object destructors have failed.", klass->desc->name);
1247      }
1248
1249    if (!obj->condtor_done)
1250      {
1251         const Eo_Class *cur_klass = _eo_kls_itr_get(&obj->mro_itr);
1252         ERR("Object of class '%s' - Not all of the object destructors have been executed, last destructor was of class: '%s'", klass->desc->name, cur_klass->desc->name);
1253      }
1254    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1255    /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
1256
1257      {
1258         Eina_List *itr, *itr_n;
1259         Eo *emb_obj;
1260         EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
1261           {
1262              eo_composite_object_detach(obj, emb_obj);
1263           }
1264      }
1265
1266    while (obj->children)
1267      {
1268         eo_parent_set(EINA_INLIST_CONTAINER_GET(obj->children, Eo), NULL);
1269      }
1270
1271    obj->del = EINA_TRUE;
1272    obj->refcount--;
1273 }
1274
1275 static inline void
1276 _eo_free(Eo *obj)
1277 {
1278    EINA_MAGIC_SET(obj, EO_FREED_EINA_MAGIC);
1279    free(obj);
1280 }
1281
1282 static inline void
1283 _eo_unref(Eo *obj)
1284 {
1285    if (--(obj->refcount) == 0)
1286      {
1287         if (obj->del)
1288           {
1289              ERR("Object %p already deleted.", obj);
1290              return;
1291           }
1292
1293         _eo_del_internal(obj);
1294
1295 #ifndef NDEBUG
1296         /* If for some reason it's not empty, clear it. */
1297         while (obj->xrefs)
1298           {
1299              WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
1300              Eina_Inlist *nitr = obj->xrefs->next;
1301              free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
1302              obj->xrefs = nitr;
1303           }
1304 #endif
1305
1306         if (!obj->manual_free)
1307            _eo_free(obj);
1308         else
1309            _eo_ref(obj); /* If we manual free, we keep a phantom ref. */
1310      }
1311 }
1312
1313 EAPI void
1314 eo_unref(const Eo *_obj)
1315 {
1316    Eo *obj = (Eo *) _obj;
1317    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1318
1319    _eo_unref(obj);
1320 }
1321
1322 EAPI void
1323 eo_del(const Eo *obj)
1324 {
1325    eo_parent_set((Eo *) obj, NULL);
1326    eo_unref(obj);
1327 }
1328
1329 EAPI int
1330 eo_ref_get(const Eo *obj)
1331 {
1332    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, 0);
1333
1334    return obj->refcount;
1335 }
1336
1337 EAPI Eo *
1338 eo_parent_get(const Eo *obj)
1339 {
1340    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1341
1342    return obj->parent;
1343 }
1344
1345 EAPI void
1346 eo_error_set_internal(const Eo *obj, const char *file, int line)
1347 {
1348    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1349
1350    ERR("Error with obj '%p' at %s:%d", obj, file, line);
1351
1352    ((Eo *) obj)->construct_error = EINA_TRUE;
1353 }
1354
1355 static inline void
1356 _eo_error_unset(Eo *obj)
1357 {
1358    obj->construct_error = EINA_FALSE;
1359 }
1360
1361 void
1362 _eo_condtor_done(Eo *obj)
1363 {
1364    if (obj->condtor_done)
1365      {
1366         ERR("Object %p is already constructed at this point.", obj);
1367         return;
1368      }
1369
1370    obj->condtor_done = EINA_TRUE;
1371 }
1372
1373 static void
1374 _eo_condtor_reset(Eo *obj)
1375 {
1376    obj->condtor_done = EINA_FALSE;
1377 }
1378
1379 /**
1380  * @internal
1381  * @brief Check if there was an error when constructing, destructing or calling a function of the object.
1382  * @param obj the object to work on.
1383  * @return @c EINA_TRUE if there was an error.
1384  */
1385 static inline Eina_Bool
1386 _eo_error_get(const Eo *obj)
1387 {
1388    return obj->construct_error;
1389 }
1390
1391 static inline void *
1392 _eo_data_get(const Eo *obj, const Eo_Class *klass)
1393 {
1394    if (EINA_LIKELY(klass->desc->data_size > 0))
1395      {
1396         if (EINA_UNLIKELY(klass->desc->type == EO_CLASS_TYPE_MIXIN))
1397           {
1398              Eo_Extension_Data_Offset *doff_itr =
1399                 eo_class_get(obj)->extn_data_off;
1400
1401              if (!doff_itr)
1402                 return NULL;
1403
1404              while (doff_itr->klass)
1405                {
1406                   if (doff_itr->klass == klass)
1407                      return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1408                            doff_itr->offset;
1409                   doff_itr++;
1410                }
1411           }
1412         else
1413           {
1414           return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1415              klass->data_offset;
1416           }
1417      }
1418
1419    return NULL;
1420 }
1421
1422 EAPI void *
1423 eo_data_get(const Eo *obj, const Eo_Class *klass)
1424 {
1425    void *ret;
1426    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1427
1428 #ifndef NDEBUG
1429    if (!_eo_class_mro_has(obj->klass, klass))
1430      {
1431         ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
1432         return NULL;
1433      }
1434 #endif
1435
1436    ret = _eo_data_get(obj, klass);
1437
1438 #ifndef NDEBUG
1439    if (!ret && (klass->desc->data_size == 0))
1440      {
1441         ERR("Tried getting data of class '%s', but it has none..", klass->desc->name);
1442      }
1443 #endif
1444
1445    return ret;
1446 }
1447
1448 EAPI Eina_Bool
1449 eo_init(void)
1450 {
1451    const char *log_dom = "eo";
1452    if (_eo_init_count++ > 0)
1453       return EINA_TRUE;
1454
1455    eina_init();
1456
1457    _eo_classes = NULL;
1458    _eo_classes_last_id = EO_STATIC_IDS_LAST;
1459    _eo_log_dom = eina_log_domain_register(log_dom, EINA_COLOR_LIGHTBLUE);
1460    if (_eo_log_dom < 0)
1461      {
1462         EINA_LOG_ERR("Could not register log domain: %s", log_dom);
1463         return EINA_FALSE;
1464      }
1465
1466    if (!eina_lock_new(&_eo_class_creation_lock))
1467      {
1468         EINA_LOG_ERR("Could not init lock.");
1469         return EINA_FALSE;
1470      }
1471
1472    eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
1473    eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
1474          EO_FREED_EINA_MAGIC_STR);
1475    eina_magic_string_static_set(EO_CLASS_EINA_MAGIC,
1476          EO_CLASS_EINA_MAGIC_STR);
1477
1478    return EINA_TRUE;
1479 }
1480
1481 EAPI Eina_Bool
1482 eo_shutdown(void)
1483 {
1484    size_t i;
1485    Eo_Class **cls_itr = _eo_classes;
1486
1487    if (--_eo_init_count > 0)
1488       return EINA_TRUE;
1489
1490    for (i = 0 ; i < _eo_classes_last_id ; i++, cls_itr++)
1491      {
1492         if (*cls_itr)
1493            eo_class_free(*cls_itr);
1494      }
1495
1496    if (_eo_classes)
1497       free(_eo_classes);
1498
1499    eina_lock_free(&_eo_class_creation_lock);
1500
1501    eina_log_domain_unregister(_eo_log_dom);
1502    _eo_log_dom = -1;
1503
1504    eina_shutdown();
1505    return EINA_TRUE;
1506 }
1507
1508 EAPI void
1509 eo_composite_object_attach(Eo *obj, Eo *emb_obj)
1510 {
1511    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1512    EO_MAGIC_RETURN(emb_obj, EO_EINA_MAGIC);
1513
1514    emb_obj->composite = EINA_TRUE;
1515    eo_parent_set(emb_obj, obj);
1516    obj->composite_objects = eina_list_prepend(obj->composite_objects, emb_obj);
1517 }
1518
1519 EAPI void
1520 eo_composite_object_detach(Eo *obj, Eo *emb_obj)
1521 {
1522    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1523    EO_MAGIC_RETURN(emb_obj, EO_EINA_MAGIC);
1524
1525    emb_obj->composite = EINA_FALSE;
1526    obj->composite_objects = eina_list_remove(obj->composite_objects, emb_obj);
1527    eo_parent_set(emb_obj, NULL);
1528 }
1529
1530 EAPI Eina_Bool
1531 eo_composite_is(const Eo *emb_obj)
1532 {
1533    if (!EINA_MAGIC_CHECK(emb_obj, EO_EINA_MAGIC))
1534      {
1535         EINA_MAGIC_FAIL(emb_obj, EO_EINA_MAGIC);
1536         return EINA_FALSE;
1537      }
1538
1539    return emb_obj->composite;
1540 }
1541
1542 EAPI void
1543 eo_manual_free_set(Eo *obj, Eina_Bool manual_free)
1544 {
1545    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1546    obj->manual_free = manual_free;
1547 }
1548
1549 EAPI void
1550 eo_manual_free(Eo *obj)
1551 {
1552    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1553
1554    if (EINA_FALSE == obj->manual_free)
1555      {
1556         ERR("Tried to manually free the object %p while the option has not been set; see eo_manual_free_set for more information.", obj);
1557         return;
1558      }
1559
1560    if (!obj->del)
1561      {
1562         ERR("Tried deleting the object %p while still referenced(%d).", obj, eo_ref_get(obj));
1563         return;
1564      }
1565
1566    _eo_free(obj);
1567 }
1568