}
static inline const op_type_funcs *
-_eo_kls_itr_next(const _Efl_Class *orig_kls, const _Efl_Class *cur_klass, Efl_Object_Op op)
+_eo_kls_itr_next(const _Efl_Class *orig_kls, const _Efl_Class *cur_klass,
+ Efl_Object_Op op, Eina_Bool super)
{
const _Efl_Class **kls_itr = NULL;
if (*kls_itr)
{
- kls_itr++;
+ if (super) kls_itr++;
while (*kls_itr)
{
const op_type_funcs *fsrc = _vtable_func_get(&(*kls_itr)->vtable, op);
static EFL_FUNC_TLS _Efl_Class *_super_klass = NULL;
-EAPI Eo *
-efl_super(const Eo *eo_id, const Efl_Class *cur_klass)
+static Eo *
+_efl_super_cast(const Eo *eo_id, const Efl_Class *cur_klass, Eina_Bool super)
{
EO_CLASS_POINTER_GOTO(cur_klass, super_klass, err);
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
obj->cur_klass = super_klass;
- obj->super = EINA_TRUE;
+ obj->super = super;
EO_OBJ_DONE(eo_id);
return (Eo *) eo_id;
do_klass:
// efl_super(Class) is extremely rarely used, so TLS write is fine
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(super, NULL);
_super_klass = super_klass;
return (Eo *) eo_id;
#endif
}
+EAPI Eo *
+efl_super(const Eo *eo_id, const Efl_Class *cur_klass)
+{
+ return _efl_super_cast(eo_id, cur_klass, EINA_TRUE);
+}
+
+EAPI Eo *
+efl_cast(const Eo *eo_id, const Efl_Class *cur_klass)
+{
+ return _efl_super_cast(eo_id, cur_klass, EINA_FALSE);
+}
+
EAPI Eina_Bool
_efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Data *call, Efl_Object_Call_Cache *cache, const char *file, int line)
{
const op_type_funcs *func;
Eina_Bool is_obj;
Eina_Bool is_override = EINA_FALSE;
+ Eina_Bool super = EINA_TRUE;
if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE;
if (_obj->cur_klass)
{
cur_klass = _obj->cur_klass;
+ super = _obj->super;
_obj->cur_klass = NULL;
}
- if (_obj_is_override(obj) && cur_klass &&
+ if (_obj_is_override(obj) && cur_klass && super &&
(_eo_class_id_get(cur_klass) == EFL_OBJECT_OVERRIDE_CLASS))
{
/* Doing a efl_super(obj, EFL_OBJECT_OVERRIDE_CLASS) should result in calling
// yes - special "move out of hot path" code blobs with goto's for
// speed reasons to have intr prefetches work better and miss less
ok_cur_klass:
- func = _eo_kls_itr_next(klass, cur_klass, cache->op);
+ func = _eo_kls_itr_next(klass, cur_klass, cache->op, super);
if (!func) goto end;
klass = func->src;
goto ok_cur_klass_back;
}
END_TEST
+
+static int
+_inherit_value_1(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
+{
+ return 1;
+}
+
+static int
+_inherit_value_2(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
+{
+ return 2;
+}
+
+EFL_FUNC_BODY(inherit_value, int, 0);
+
+static Eina_Bool
+_cast_inherit_class_initializer_1(Efl_Class *klass)
+{
+ EFL_OPS_DEFINE(ops, EFL_OBJECT_OP_FUNC(inherit_value, _inherit_value_1), );
+ return efl_class_functions_set(klass, &ops, NULL);
+}
+
+static Eina_Bool
+_cast_inherit_class_initializer_2(Efl_Class *klass)
+{
+ EFL_OPS_DEFINE(ops, EFL_OBJECT_OP_FUNC(inherit_value, _inherit_value_2), );
+ return efl_class_functions_set(klass, &ops, NULL);
+}
+
+START_TEST(efl_cast_test)
+{
+ efl_object_init();
+
+ static const Efl_Class_Description class_desc_1 = {
+ EO_VERSION,
+ "FirstInherit",
+ EFL_CLASS_TYPE_REGULAR,
+ 0,
+ _cast_inherit_class_initializer_1,
+ NULL,
+ NULL
+ };
+
+ static const Efl_Class_Description class_desc_2 = {
+ EO_VERSION,
+ "SecondInherit",
+ EFL_CLASS_TYPE_REGULAR,
+ 0,
+ _cast_inherit_class_initializer_2,
+ NULL,
+ NULL
+ };
+
+ const Efl_Class *klass1 = efl_class_new(&class_desc_1, SIMPLE_CLASS, NULL);
+ fail_if(!klass1);
+
+ const Efl_Class *klass2 = efl_class_new(&class_desc_2, klass1, NULL);
+ fail_if(!klass2);
+
+ Eo *obj;
+
+ // Testing normal calls
+ obj = efl_add(SIMPLE_CLASS, NULL);
+ fail_if(!obj);
+ ck_assert_int_eq(inherit_value(obj), 0);
+ efl_unref(obj);
+
+ obj = efl_add(klass1, NULL);
+ fail_if(!obj);
+ ck_assert_int_eq(inherit_value(obj), 1);
+ efl_unref(obj);
+
+ obj = efl_add(klass2, NULL);
+ fail_if(!obj);
+ ck_assert_int_eq(inherit_value(obj), 2);
+ efl_unref(obj);
+
+ // Testing efl_super
+ obj = efl_add(klass2, NULL);
+ fail_if(!obj);
+ ck_assert_int_eq(inherit_value(efl_super(obj, klass2)), 1);
+ ck_assert_int_eq(inherit_value(efl_super(obj, klass1)), 0);
+ efl_unref(obj);
+
+ // Testing efl_cast
+ obj = efl_add(klass2, NULL);
+ fail_if(!obj);
+ ck_assert_int_eq(inherit_value(efl_cast(obj, klass2)), 2);
+ ck_assert_int_eq(inherit_value(efl_cast(obj, klass1)), 1);
+ ck_assert_int_eq(inherit_value(efl_cast(obj, SIMPLE_CLASS)), 0);
+ efl_unref(obj);
+
+ efl_object_shutdown();
+}
+END_TEST
+
void eo_test_general(TCase *tc)
{
tcase_add_test(tc, eo_simple);
tcase_add_test(tc, eo_comment);
tcase_add_test(tc, eo_rec_interface);
tcase_add_test(tc, eo_domain);
+ tcase_add_test(tc, efl_cast_test);
}