summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2016-12-07 13:55:13 +0000
committerTom Hacohen <tom@stosb.com>2016-12-07 13:55:13 +0000
commit5424cdbd810042ba59e71bec6b8d91cb6a2c3e9c (patch)
tree638c5b421fbae88c53fc73d7397cf8a3c7cdfe79
parent900b1726e6c8205c8f6c9c74ffa6579e2c15809f (diff)
downloadefl-5424cdbd810042ba59e71bec6b8d91cb6a2c3e9c.tar.gz
Eo: Fix efl_isa() sometimes returning wrong results with extensions
This fixes an issue where efl_isa() wouldn't work for extensions or ancestors of extensions of a class. Example: Class A implements interface F2 F2 inherits from interface F1 obj is of class A Before this patch efl_isa(obj, F1) would return false, now it returns true as expected. This is just one example, there is a whole array of variations to this issue that are now fixed. Thanks to Gustavo for reminding me of this. @fix
-rw-r--r--src/lib/eo/eo.c45
-rw-r--r--src/tests/eo/interface/interface_main.c3
2 files changed, 26 insertions, 22 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index c4c6a5f0b7..20cf56d25d 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -228,14 +228,14 @@ _eo_op_class_get(Efl_Object_Op op)
}
static inline Eina_Bool
-_vtable_func_set(Eo_Vtable *vtable, const _Efl_Class *klass, Efl_Object_Op op, Eo_Op_Func_Type func)
+_vtable_func_set(Eo_Vtable *vtable, const _Efl_Class *klass, Efl_Object_Op op, Eo_Op_Func_Type func, Eina_Bool allow_same_override)
{
op_type_funcs *fsrc;
size_t idx1 = DICH_CHAIN1(op);
Dich_Chain1 *chain1 = &vtable->chain[idx1];
_vtable_chain_write_prepare(chain1);
fsrc = &chain1->chain2->funcs[DICH_CHAIN_LAST(op)];
- if (fsrc->src == klass)
+ if (!allow_same_override && (fsrc->src == klass))
{
const _Efl_Class *op_kls = _eo_op_class_get(op);
ERR("Class '%s': Overriding already set func %p for op %d (%s) with %p.",
@@ -746,7 +746,7 @@ _eo_class_funcs_set(Eo_Vtable *vtable, const Efl_Object_Ops *ops, const _Efl_Cla
DBG("%p->%p '%s'", op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc));
- if (!_vtable_func_set(vtable, klass, op, op_desc->func))
+ if (!_vtable_func_set(vtable, klass, op, op_desc->func, EINA_FALSE))
return EINA_FALSE;
last_api_func = op_desc->api_func;
@@ -1224,6 +1224,25 @@ _eo_class_isa_func(Eo *eo_id EINA_UNUSED, void *class_data EINA_UNUSED)
/* Do nonthing. */
}
+static void
+_eo_class_isa_recursive_set(_Efl_Class *klass, const _Efl_Class *cur)
+{
+ const _Efl_Class **extn_itr;
+
+ _vtable_func_set(&klass->vtable, klass, cur->base_id + cur->ops_count,
+ _eo_class_isa_func, EINA_TRUE);
+
+ for (extn_itr = cur->extensions ; *extn_itr ; extn_itr++)
+ {
+ _eo_class_isa_recursive_set(klass, *extn_itr);
+ }
+
+ if (cur->parent)
+ {
+ _eo_class_isa_recursive_set(klass, cur->parent);
+ }
+}
+
static inline void
_eo_classes_release(void)
{
@@ -1509,25 +1528,7 @@ efl_class_new(const Efl_Class_Description *desc, const Efl_Class *parent_id, ...
/* Mark which classes we implement */
if (klass->vtable.size)
{
- const _Efl_Class **extn_itr;
-
- for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
- {
- const _Efl_Class *extn = *extn_itr;
- /* Set it in the dich. */
- _vtable_func_set(&klass->vtable, klass, extn->base_id +
- extn->ops_count, _eo_class_isa_func);
- }
-
- _vtable_func_set(&klass->vtable, klass, klass->base_id + klass->ops_count,
- _eo_class_isa_func);
-
- if (klass->parent)
- {
- _vtable_func_set(&klass->vtable, klass,
- klass->parent->base_id + klass->parent->ops_count,
- _eo_class_isa_func);
- }
+ _eo_class_isa_recursive_set(klass, klass);
}
_eo_class_constructor(klass);
diff --git a/src/tests/eo/interface/interface_main.c b/src/tests/eo/interface/interface_main.c
index e9e145bd75..8f07bb29e6 100644
--- a/src/tests/eo/interface/interface_main.c
+++ b/src/tests/eo/interface/interface_main.c
@@ -35,6 +35,9 @@ main(int argc, char *argv[])
sum = interface2_ab_sum_get2(obj);
fail_if(sum != a + b + 1);
+ fail_if(!efl_isa(obj, INTERFACE_CLASS));
+ fail_if(!efl_isa(obj, INTERFACE2_CLASS));
+
efl_unref(obj);
efl_object_shutdown();
return 0;