From 3029227fa1aeaefce7973042b5d2389c2b643814 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 19 Jul 2016 17:21:36 +0900 Subject: [PATCH] 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 --- src/bin/elementary/test_ui_box.c | 11 ++++------- src/lib/eo/Eo.h | 23 +++++++++++++++++++++-- src/lib/eo/eo.c | 6 +++--- src/tests/eo/suite/eo_test_general.c | 29 ++++++++++++----------------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/bin/elementary/test_ui_box.c b/src/bin/elementary/test_ui_box.c index e5e1a35..fbfaf6e 100644 --- a/src/bin/elementary/test_ui_box.c +++ b/src/bin/elementary/test_ui_box.c @@ -174,20 +174,17 @@ _custom_layout_update(Eo *pack, const void *data EINA_UNUSED) 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 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); Eo *obj = data; // Overriding just the one function we need - eo_override(obj, chk ? EO_OVERRIDE_OPS(custom_engine_op_desc) - : ((Eo_Ops) { NULL, 0 })); + eo_override(obj, chk ? &custom_layout_ops : NULL); // Layout request is required as the pack object doesn't know the layout // function was just overridden. diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index c8d050f..58c26b4 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -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 * 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. diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 014d859..52ba754 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -1338,13 +1338,13 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...) } 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_CLASS_POINTER_RETURN_VAL(EO_OVERRIDE_CLASS, klass, EINA_FALSE); Eo_Vtable *previous = obj->vtable; - if (!ops.descs) + if (!ops) { if (obj->vtable != &obj->klass->vtable) { @@ -1361,7 +1361,7 @@ eo_override(Eo *eo_id, Eo_Ops ops) _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); return EINA_FALSE; diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c index 0848066..dcbf73f 100644 --- a/src/tests/eo/suite/eo_test_general.c +++ b/src/tests/eo/suite/eo_test_general.c @@ -66,10 +66,6 @@ START_TEST(eo_override_tests) { 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); fail_if(!obj); @@ -77,7 +73,10 @@ START_TEST(eo_override_tests) * make sure we don't cache. */ 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); @@ -85,24 +84,20 @@ START_TEST(eo_override_tests) simple_a_set(obj, OVERRIDE_A_SIMPLE); ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + OVERRIDE_A_SIMPLE); - /* Override again. */ - Eo_Op_Description override_descs2[] = { - EO_OP_FUNC_OVERRIDE(simple_a_set, _simple_obj_override_a_double_set), - }; - - fail_if(!eo_override(obj, EO_OVERRIDE_OPS(override_descs2))); + EO_OVERRIDE_OPS_DEFINE( + overrides2, + EO_OP_FUNC_OVERRIDE(simple_a_set, _simple_obj_override_a_double_set)); + fail_if(!eo_override(obj, &overrides2)); simple_a_set(obj, OVERRIDE_A_SIMPLE); ck_assert_int_eq(simple_a_get(obj), OVERRIDE_A + (OVERRIDE_A_SIMPLE * 2)); - /* Try introducing a new function */ - Eo_Op_Description override_descs3[] = { - EO_OP_FUNC(simple2_class_beef_get, _simple_obj_override_a_double_set), - }; - - fail_if(eo_override(obj, EO_OVERRIDE_OPS(override_descs3))); + EO_OVERRIDE_OPS_DEFINE( + overrides3, + EO_OP_FUNC(simple2_class_beef_get, _simple_obj_override_a_double_set)); + fail_if(eo_override(obj, &overrides3)); eo_unref(obj); -- 2.7.4