forked from enlightenment/efl
eo: Change eo_override to avoid struct passing and GCC construct
This is a (minor) API & ABI break in Eo.h! I say minor as eo_override shouldn't be used yet (EO is unstable and this patch includes all the use cases in EFL). I'm not very happy about the new form of the macro, but it avoids two things: - passing in a struct (valid in C, but never used in EFL) - using a GCC construct to create structs on the fly It was inspired by the event array define, but I don't think we need the runtime memcpy here. See also: https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html
This commit is contained in:
parent
a9d4d7e836
commit
3029227fa1
|
@ -174,20 +174,17 @@ _custom_layout_update(Eo *pack, const void *data EINA_UNUSED)
|
||||||
eina_iterator_free(it);
|
eina_iterator_free(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Common Eo Class boilerplate. */
|
|
||||||
static const Eo_Op_Description custom_engine_op_desc[] = {
|
|
||||||
EO_OP_FUNC_OVERRIDE(efl_pack_layout_update, _custom_layout_update),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
custom_check_cb(void *data, const Eo_Event *event)
|
custom_check_cb(void *data, const Eo_Event *event)
|
||||||
{
|
{
|
||||||
|
EO_OVERRIDE_OPS_DEFINE(custom_layout_ops,
|
||||||
|
EO_OP_FUNC_OVERRIDE(efl_pack_layout_update, _custom_layout_update));
|
||||||
|
|
||||||
Eina_Bool chk = elm_check_selected_get(event->object);
|
Eina_Bool chk = elm_check_selected_get(event->object);
|
||||||
Eo *obj = data;
|
Eo *obj = data;
|
||||||
|
|
||||||
// Overriding just the one function we need
|
// Overriding just the one function we need
|
||||||
eo_override(obj, chk ? EO_OVERRIDE_OPS(custom_engine_op_desc)
|
eo_override(obj, chk ? &custom_layout_ops : NULL);
|
||||||
: ((Eo_Ops) { NULL, 0 }));
|
|
||||||
|
|
||||||
// Layout request is required as the pack object doesn't know the layout
|
// Layout request is required as the pack object doesn't know the layout
|
||||||
// function was just overridden.
|
// function was just overridden.
|
||||||
|
|
|
@ -449,10 +449,29 @@ EAPI const Eo_Class *eo_class_new(const Eo_Class_Description *desc, const Eo_Cla
|
||||||
*
|
*
|
||||||
* You are only allowed to override functions that are defined in the
|
* You are only allowed to override functions that are defined in the
|
||||||
* class or any of its interfaces (that is, eo_isa returning true).
|
* class or any of its interfaces (that is, eo_isa returning true).
|
||||||
|
*
|
||||||
|
* If @p ops is #NULL, this will revert the @p obj to its original class
|
||||||
|
* without any function overrides.
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool eo_override(Eo *obj, Eo_Ops ops);
|
EAPI Eina_Bool eo_override(Eo *obj, const Eo_Ops *ops);
|
||||||
|
|
||||||
#define EO_OVERRIDE_OPS(op_descs) ((Eo_Ops) { op_descs, EINA_C_ARRAY_LENGTH(op_descs) })
|
/**
|
||||||
|
* @brief Define an array of override functions for @ref eo_override
|
||||||
|
* @param ops A name for the Eo_Ops local variable to define
|
||||||
|
* @param ... A comma separated list of Eo_Op overrides, using
|
||||||
|
* #EO_OP_FUNC_OVERRIDE or #EO_OP_CLASS_FUNC_OVERRIDE
|
||||||
|
*
|
||||||
|
* This can be used as follows:
|
||||||
|
* @code
|
||||||
|
* EO_OVERRIDE_OPS_DEFINE(ops, EO_OP_FUNC_OVERRIDE(public_func, _my_func));
|
||||||
|
* eo_override(obj, &ops);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @see eo_override
|
||||||
|
*/
|
||||||
|
#define EO_OVERRIDE_OPS_DEFINE(ops, ...) \
|
||||||
|
const Eo_Op_Description _##ops##_descs[] = { __VA_ARGS__ }; \
|
||||||
|
const Eo_Ops ops = { _##ops##_descs, EINA_C_ARRAY_LENGTH(_##ops##_descs) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if an object "is a" klass.
|
* @brief Check if an object "is a" klass.
|
||||||
|
|
|
@ -1338,13 +1338,13 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
eo_override(Eo *eo_id, Eo_Ops ops)
|
eo_override(Eo *eo_id, const Eo_Ops *ops)
|
||||||
{
|
{
|
||||||
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE);
|
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE);
|
||||||
EO_CLASS_POINTER_RETURN_VAL(EO_OVERRIDE_CLASS, klass, EINA_FALSE);
|
EO_CLASS_POINTER_RETURN_VAL(EO_OVERRIDE_CLASS, klass, EINA_FALSE);
|
||||||
Eo_Vtable *previous = obj->vtable;
|
Eo_Vtable *previous = obj->vtable;
|
||||||
|
|
||||||
if (!ops.descs)
|
if (!ops)
|
||||||
{
|
{
|
||||||
if (obj->vtable != &obj->klass->vtable)
|
if (obj->vtable != &obj->klass->vtable)
|
||||||
{
|
{
|
||||||
|
@ -1361,7 +1361,7 @@ eo_override(Eo *eo_id, Eo_Ops ops)
|
||||||
_vtable_copy_all(obj->vtable, previous);
|
_vtable_copy_all(obj->vtable, previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_eo_class_funcs_set(obj->vtable, &ops, obj->klass, klass, EINA_TRUE))
|
if (!_eo_class_funcs_set(obj->vtable, ops, obj->klass, klass, EINA_TRUE))
|
||||||
{
|
{
|
||||||
ERR("Failed to override functions for %p", eo_id);
|
ERR("Failed to override functions for %p", eo_id);
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
|
|
@ -66,10 +66,6 @@ START_TEST(eo_override_tests)
|
||||||
{
|
{
|
||||||
eo_init();
|
eo_init();
|
||||||
|
|
||||||
Eo_Op_Description override_descs[] = {
|
|
||||||
EO_OP_FUNC_OVERRIDE(simple_a_get, _simple_obj_override_a_get),
|
|
||||||
};
|
|
||||||
|
|
||||||
Eo *obj = eo_add(SIMPLE_CLASS, NULL);
|
Eo *obj = eo_add(SIMPLE_CLASS, NULL);
|
||||||
fail_if(!obj);
|
fail_if(!obj);
|
||||||
|
|
||||||
|
@ -77,7 +73,10 @@ START_TEST(eo_override_tests)
|
||||||
* make sure we don't cache. */
|
* make sure we don't cache. */
|
||||||
ck_assert_int_eq(simple_a_get(obj), 0);
|
ck_assert_int_eq(simple_a_get(obj), 0);
|
||||||
|
|
||||||
fail_if(!eo_override(obj, EO_OVERRIDE_OPS(override_descs)));
|
EO_OVERRIDE_OPS_DEFINE(
|
||||||
|
overrides,
|
||||||
|
EO_OP_FUNC_OVERRIDE(simple_a_get, _simple_obj_override_a_get));
|
||||||
|
fail_if(!eo_override(obj, &overrides));
|
||||||
|
|
||||||
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A);
|
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A);
|
||||||
|
|
||||||
|
@ -85,24 +84,20 @@ START_TEST(eo_override_tests)
|
||||||
simple_a_set(obj, OVERRIDE_A_SIMPLE);
|
simple_a_set(obj, OVERRIDE_A_SIMPLE);
|
||||||
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + OVERRIDE_A_SIMPLE);
|
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + OVERRIDE_A_SIMPLE);
|
||||||
|
|
||||||
|
|
||||||
/* Override again. */
|
/* Override again. */
|
||||||
Eo_Op_Description override_descs2[] = {
|
EO_OVERRIDE_OPS_DEFINE(
|
||||||
EO_OP_FUNC_OVERRIDE(simple_a_set, _simple_obj_override_a_double_set),
|
overrides2,
|
||||||
};
|
EO_OP_FUNC_OVERRIDE(simple_a_set, _simple_obj_override_a_double_set));
|
||||||
|
fail_if(!eo_override(obj, &overrides2));
|
||||||
fail_if(!eo_override(obj, EO_OVERRIDE_OPS(override_descs2)));
|
|
||||||
|
|
||||||
simple_a_set(obj, OVERRIDE_A_SIMPLE);
|
simple_a_set(obj, OVERRIDE_A_SIMPLE);
|
||||||
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + (OVERRIDE_A_SIMPLE * 2));
|
ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + (OVERRIDE_A_SIMPLE * 2));
|
||||||
|
|
||||||
|
|
||||||
/* Try introducing a new function */
|
/* Try introducing a new function */
|
||||||
Eo_Op_Description override_descs3[] = {
|
EO_OVERRIDE_OPS_DEFINE(
|
||||||
EO_OP_FUNC(simple2_class_beef_get, _simple_obj_override_a_double_set),
|
overrides3,
|
||||||
};
|
EO_OP_FUNC(simple2_class_beef_get, _simple_obj_override_a_double_set));
|
||||||
|
fail_if(eo_override(obj, &overrides3));
|
||||||
fail_if(eo_override(obj, EO_OVERRIDE_OPS(override_descs3)));
|
|
||||||
|
|
||||||
eo_unref(obj);
|
eo_unref(obj);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue