diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 47cb0a059e..ef43decad6 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -940,7 +940,8 @@ EAPI Eina_Bool eo_destructed_is(const Eo *obj); * @param parent the "parent" object. * @return EINA_TRUE if successfull. EINA_FALSE otherwise. * - * The class of comp_obj must be part of the extensions of the class of the parent. + * The class of comp_obj must be of the type EO_CLASS_TYPE_REGULAR + * and be part of the extensions of the class of the parent. * It is not possible to attach more then 1 composite of the same class. * This functions also sets the parent of comp_obj to parent. * @@ -953,13 +954,14 @@ EAPI Eina_Bool eo_composite_attach(Eo *comp_obj, Eo *parent); * @brief Detach a composite object from another object. * @param comp_obj the object attached to parent. * @param parent the "parent" object. + * @return EINA_TRUE if successfull. EINA_FALSE otherwise. * * This functions also sets the parent of comp_obj to @c NULL. * * @see eo_composite_attach() * @see eo_composite_is() */ -EAPI void eo_composite_detach(Eo *comp_obj, Eo *parent); +EAPI Eina_Bool eo_composite_detach(Eo *comp_obj, Eo *parent); /** * @brief Check if an object is a composite object. diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index bce20dd4a1..26a91d233d 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -311,18 +311,19 @@ _eo_op_internal(const char *file, int line, Eo_Base *eo_ptr, const _Eo_Class *cu /* Try composite objects */ if (op_type == EO_OP_TYPE_REGULAR) { - Eina_List *itr; - Eo *emb_obj_id; - EINA_LIST_FOREACH(((_Eo_Object *) eo_ptr)->composite_objects, itr, emb_obj_id) - { - /* FIXME: Clean this up a bit. */ - EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE); - if (_eo_op_internal(file, line, (Eo_Base *) emb_obj, emb_obj->klass, op_type, op, p_list)) - { - return EINA_TRUE; - } - } + const _Eo_Object **comp_itr = ((_Eo_Object *) eo_ptr)->composites; + if (!comp_itr) return EINA_FALSE; + + for (unsigned int i = 0; i < ((_Eo_Object *) eo_ptr)->klass->composites_count; i++, comp_itr++) + if (*comp_itr) + { + if (_eo_op_internal(file, line, (Eo_Base *) (*comp_itr), (*comp_itr)->klass, op_type, op, p_list)) + { + return EINA_TRUE; + } + } } + return EINA_FALSE; } @@ -921,6 +922,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...) EINA_LIST_FREE(extn_list, extn) { *(extn_itr++) = extn; + if (extn->desc->type == EO_CLASS_TYPE_REGULAR) + klass->composites_count += 1; DBG("Added '%s' extension", extn->desc->name); } @@ -963,6 +966,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...) } klass->obj_size = _eo_sz + extn_data_off; + if (klass->composites_count > 0) + klass->obj_size += (klass->composites_count * sizeof(_Eo_Object *)); if (getenv("EO_DEBUG")) { fprintf(stderr, "Eo class '%s' will take %u bytes per object.\n", @@ -1089,6 +1094,11 @@ eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent obj->refcount++; obj->klass = klass; + if (klass->composites_count == 0) + obj->composites = NULL; + else + obj->composites = (const _Eo_Object **) + ((char *) obj + klass->obj_size - (klass->composites_count * sizeof(_Eo_Object *))); #ifndef HAVE_EO_ID EINA_MAGIC_SET((Eo_Base *) obj, EO_EINA_MAGIC); @@ -1497,39 +1507,62 @@ eo_shutdown(void) EAPI Eina_Bool eo_composite_attach(Eo *comp_obj_id, Eo *parent_id) { + const _Eo_Object **comp_itr; + const _Eo_Object **comp_dst; + EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE); EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE); + if (!parent->composites) return EINA_FALSE; + if (comp_obj->klass->desc->type != EO_CLASS_TYPE_REGULAR) return EINA_FALSE; if (!eo_isa(parent_id, _eo_class_id_get(comp_obj->klass))) return EINA_FALSE; + comp_dst = NULL; + comp_itr = parent->composites; + for (unsigned int i = 0; i < parent->klass->composites_count; i++, comp_itr++) { - Eina_List *itr; - Eo *emb_obj_id; - EINA_LIST_FOREACH(parent->composite_objects, itr, emb_obj_id) + if (*comp_itr) { - EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE); - if(emb_obj->klass == comp_obj->klass) + if ((*comp_itr)->klass == comp_obj->klass) return EINA_FALSE; } + else if (!comp_dst) + comp_dst = comp_itr; } - comp_obj->composite = EINA_TRUE; - parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj_id); + if (!comp_dst) + return EINA_FALSE; + comp_obj->composite = EINA_TRUE; + *comp_dst = comp_obj; eo_do(comp_obj_id, eo_parent_set(parent_id)); return EINA_TRUE; } -EAPI void +EAPI Eina_Bool eo_composite_detach(Eo *comp_obj_id, Eo *parent_id) { - EO_OBJ_POINTER_RETURN(comp_obj_id, comp_obj); - EO_OBJ_POINTER_RETURN(parent_id, parent); + const _Eo_Object **comp_itr; - comp_obj->composite = EINA_FALSE; - parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj_id); - eo_do(comp_obj_id, eo_parent_set(NULL)); + EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE); + EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE); + + if (!parent->composites) return EINA_FALSE; + + comp_itr = parent->composites; + for (unsigned int i = 0; i < parent->klass->composites_count; i++, comp_itr++) + { + if (*comp_itr == comp_obj) + { + comp_obj->composite = EINA_FALSE; + *comp_itr = NULL; + eo_do(comp_obj_id, eo_parent_set(NULL)); + return EINA_TRUE; + } + } + + return EINA_FALSE; } EAPI Eina_Bool diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 2fd13a9dad..a985556b70 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -94,7 +94,7 @@ struct _Eo_Object Eina_Inlist *data_xrefs; #endif - Eina_List *composite_objects; + const _Eo_Object **composites; int refcount; int datarefcount; @@ -105,6 +105,8 @@ struct _Eo_Object Eina_Bool composite:1; Eina_Bool del:1; Eina_Bool manual_free:1; + /* data [parents, self, mixins]*/ + /* [composite*] */ }; typedef struct _Dich_Chain1 Dich_Chain1; @@ -158,6 +160,7 @@ struct _Eo_Class unsigned int chain_size; unsigned int base_id; unsigned int data_offset; /* < Offset of the data within object data. */ + unsigned int composites_count; Eina_Bool constructed : 1; /* [extensions*] + NULL */ @@ -229,11 +232,11 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj) /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */ { - Eina_List *itr, *itr_n; - Eo *emb_obj; - EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj) + const _Eo_Object **comp_itr = obj->composites; + for (unsigned int i = 0; i < obj->klass->composites_count; i++, comp_itr++) { - eo_composite_detach(emb_obj, _eo_id_get(obj)); + if (*comp_itr) + eo_composite_detach(_eo_id_get(*comp_itr), _eo_id_get(obj)); } } diff --git a/src/tests/eo/composite_objects/composite_objects_main.c b/src/tests/eo/composite_objects/composite_objects_main.c index 1d5b8c0474..ba96eb4a22 100644 --- a/src/tests/eo/composite_objects/composite_objects_main.c +++ b/src/tests/eo/composite_objects/composite_objects_main.c @@ -54,7 +54,8 @@ main(int argc, char *argv[]) fail_if(cb_called); fail_if(!eo_composite_is(simple)); - eo_composite_detach(simple, obj); + fail_if(!eo_composite_detach(simple, obj)); + fail_if(eo_composite_detach(simple, obj)); fail_if(eo_composite_is(simple)); fail_if(!eo_composite_attach(simple, obj)); fail_if(!eo_composite_is(simple));