summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-02-05 15:40:41 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-02-07 14:43:25 +0100
commit0f32bb90476703f81fd08800eda0a0d89321f80f (patch)
tree97f71bd6fedc72e0609e0e807527de0da4a54072
parent0709bdea6f94149b6b319461edd27b7a0035552d (diff)
eo: here comes reflection API
this adds support in eo to generate a reflection API. To get the actaul reflection to the klass, the API efl_class_reflection_table_set needs to be called, the table in the end can be generated by eolian. Reflection API is inherited by the extended class. This means, if you have two reflection tables, first, the most upperst is called, then the next lower one is called. For now this API accepts NULL setter or getter, and will ignore them silently when they are called. fix T7681 Differential Revision: https://phab.enlightenment.org/D7879
-rw-r--r--src/Makefile_Eo.am3
-rw-r--r--src/lib/eo/Eo.h58
-rw-r--r--src/lib/eo/eo.c64
-rw-r--r--src/lib/eo/eo_private.h2
-rw-r--r--src/tests/eo/suite/eo_suite.c1
-rw-r--r--src/tests/eo/suite/eo_suite.h1
-rw-r--r--src/tests/eo/suite/eo_test_class_simple.c28
-rw-r--r--src/tests/eo/suite/eo_test_reflection.c66
-rw-r--r--src/tests/eo/suite/meson.build3
9 files changed, 219 insertions, 7 deletions
diff --git a/src/Makefile_Eo.am b/src/Makefile_Eo.am
index 43778be897..5b602af246 100644
--- a/src/Makefile_Eo.am
+++ b/src/Makefile_Eo.am
@@ -149,7 +149,8 @@ tests/eo/suite/eo_test_value.c \
149tests/eo/suite/eo_test_event.c \ 149tests/eo/suite/eo_test_event.c \
150tests/eo/suite/eo_test_threaded_calls.c \ 150tests/eo/suite/eo_test_threaded_calls.c \
151tests/eo/suite/eo_test_init.c \ 151tests/eo/suite/eo_test_init.c \
152tests/eo/suite/eo_test_lifecycle.c 152tests/eo/suite/eo_test_lifecycle.c \
153tests/eo/suite/eo_test_reflection.c
153 154
154tests_eo_eo_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 155tests_eo_eo_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
155-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \ 156-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 1406984964..d258a47df4 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -826,6 +826,40 @@ struct _Efl_Class_Description
826 void (*class_constructor)(Efl_Class *klass); /**< The constructor of the class. */ 826 void (*class_constructor)(Efl_Class *klass); /**< The constructor of the class. */
827 void (*class_destructor)(Efl_Class *klass); /**< The destructor of the class. */ 827 void (*class_destructor)(Efl_Class *klass); /**< The destructor of the class. */
828}; 828};
829/**
830 * Setter type which is used to set an #Eina_Value, this function should access one particular property field
831 */
832typedef void (*Efl_Object_Property_Reflection_Setter)(Eo *obj, Eina_Value value);
833
834/**
835 * Getter type which is used to get an #Eina_Value, this function should access one particular property field
836 */
837typedef Eina_Value (*Efl_Object_Property_Reflection_Getter)(Eo *obj);
838
839/**
840 * @struct _Efl_Object_Property_Reflection
841 *
842 * This structure holds one line of the reflection table.
843 * The two fields get and set might be NULL,
844 * the property_name is a normal c string containing the name of the property
845 * that the get and set function changes.
846 */
847typedef struct _Efl_Object_Property_Reflection{
848 const char *property_name; /**< The name of the property */
849 Efl_Object_Property_Reflection_Setter set; /**< The function used to set a generic #Eina_Value on this property of the object. */
850 Efl_Object_Property_Reflection_Getter get; /**< The function used to retrieve a generic #Eina_Value from this property of the object. */
851} Efl_Object_Property_Reflection;
852
853/**
854 * @struct _Efl_Object_Property_Reflection_Ops
855 *
856 * This structure holds the reflection table and the size of this table.
857 */
858typedef struct _Efl_Object_Property_Reflection_Ops
859{
860 const Efl_Object_Property_Reflection *table; /**< The reflection table. */
861 size_t count; /**< Number of table lines descriptions. */
862} Efl_Object_Property_Reflection_Ops;
829 863
830/** 864/**
831 * @typedef Efl_Class_Description 865 * @typedef Efl_Class_Description
@@ -860,10 +894,11 @@ EAPI const Efl_Class *efl_class_new(const Efl_Class_Description *desc, const Efl
860 * @return True on success, False otherwise. 894 * @return True on success, False otherwise.
861 * 895 *
862 * This should only be called from within the initializer function. 896 * This should only be called from within the initializer function.
863 * 897 * The reflection_table contains a getter and setter per property name. Which are called when either
898 * efl_property_reflection_set() or efl_property_reflection_get() is called.
864 * @see #EFL_DEFINE_CLASS 899 * @see #EFL_DEFINE_CLASS
865 */ 900 */
866EAPI Eina_Bool efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ops, const Efl_Object_Ops *class_ops, const void *reflection_table); 901EAPI Eina_Bool efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ops, const Efl_Object_Ops *class_ops, const Efl_Object_Property_Reflection_Ops *reflection_table);
867 902
868/** 903/**
869 * @brief Override Eo functions of this object. 904 * @brief Override Eo functions of this object.
@@ -1946,6 +1981,25 @@ EAPI Eina_Bool efl_manual_free(Eo *obj);
1946EAPI Eina_Bool efl_destructed_is(const Eo *obj); 1981EAPI Eina_Bool efl_destructed_is(const Eo *obj);
1947 1982
1948/** 1983/**
1984 * @brief Set the given #Eina_Value to the property with the specified \c property_name.
1985 * @param obj The object to set the property on
1986 * @param property_name The name of the property to modify.
1987 * @param value The value to set, the value passed here will be flushed by the function
1988 *
1989 */
1990EAPI void efl_property_reflection_set(Eo *obj, const char *property_name, Eina_Value value);
1991
1992/**
1993 * @brief Retrieve an #Eina_Value containing the current value of the property specified with \c property_name.
1994 * @param obj The object to set the property on
1995 * @param property_name The name of the property to get.
1996 *
1997 * @return The value that got returned by the actual property in form of a generic Eina_Value. The user of this API is owning the returned Value.
1998 */
1999EAPI Eina_Value efl_property_reflection_get(Eo *obj, const char *property_name);
2000
2001
2002/**
1949 * @addtogroup Efl_Class_Class Eo's Class class. 2003 * @addtogroup Efl_Class_Class Eo's Class class.
1950 * @{ 2004 * @{
1951 */ 2005 */
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 0d1ae5b64c..beed05914d 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -819,7 +819,7 @@ _eo_class_funcs_set(Eo_Vtable *vtable, const Efl_Object_Ops *ops, const _Efl_Cla
819} 819}
820 820
821EAPI Eina_Bool 821EAPI Eina_Bool
822efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ops, const Efl_Object_Ops *class_ops, const void *reflection_table) 822efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ops, const Efl_Object_Ops *class_ops, const Efl_Object_Property_Reflection_Ops *reflection_table)
823{ 823{
824 EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass); 824 EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
825 Efl_Object_Ops empty_ops = { 0 }; 825 Efl_Object_Ops empty_ops = { 0 };
@@ -832,6 +832,8 @@ efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_
832 832
833 if (!class_ops) class_ops = &empty_ops; 833 if (!class_ops) class_ops = &empty_ops;
834 834
835 klass->reflection = reflection_table;
836
835 klass->ops_count = object_ops->count + class_ops->count; 837 klass->ops_count = object_ops->count + class_ops->count;
836 838
837 klass->base_id = _eo_ops_last_id; 839 klass->base_id = _eo_ops_last_id;
@@ -3597,3 +3599,63 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_OBJECT = {
3597}; 3599};
3598 3600
3599EOAPI const Eina_Value_Type *EINA_VALUE_TYPE_OBJECT = &_EINA_VALUE_TYPE_OBJECT; 3601EOAPI const Eina_Value_Type *EINA_VALUE_TYPE_OBJECT = &_EINA_VALUE_TYPE_OBJECT;
3602
3603static const Efl_Object_Property_Reflection*
3604_efl_class_reflection_find(const _Efl_Class *klass, const char *property_name)
3605{
3606 const _Efl_Class **klass_iter = klass->extensions;
3607 const Efl_Object_Property_Reflection_Ops *ref = klass->reflection;
3608 unsigned int i;
3609
3610 for (i = 0; ref && i < ref->count; ++i)
3611 {
3612 if (eina_streq(property_name, ref->table[i].property_name))
3613 return &ref->table[i];
3614 }
3615
3616 if (klass->parent)
3617 {
3618 const Efl_Object_Property_Reflection *ref;
3619
3620 ref = _efl_class_reflection_find(klass->parent, property_name);
3621 if (ref) return ref;
3622 }
3623
3624 for (; *klass_iter; klass_iter++)
3625 {
3626 return _efl_class_reflection_find(*klass_iter, property_name);
3627 }
3628
3629 return NULL;
3630}
3631
3632EAPI void
3633efl_property_reflection_set(Eo *obj_id, const char *property_name, Eina_Value value)
3634{
3635 EO_OBJ_POINTER_GOTO(obj_id, obj, end);
3636 const Efl_Object_Property_Reflection *reflection = _efl_class_reflection_find(obj->klass, property_name);
3637
3638 if (!reflection || !reflection->set) goto end;
3639
3640 reflection->set(obj_id, value);
3641 EO_OBJ_DONE(obj_id);
3642 return;
3643end:
3644 eina_value_flush(&value);
3645 EO_OBJ_DONE(obj_id);
3646}
3647
3648EAPI Eina_Value
3649efl_property_reflection_get(Eo *obj_id, const char *property_name)
3650{
3651 EO_OBJ_POINTER(obj_id, obj);
3652 const Efl_Object_Property_Reflection *reflection = _efl_class_reflection_find(obj->klass, property_name);
3653
3654 if (!reflection || !reflection->get) goto end;
3655
3656 return reflection->get(obj_id);
3657end:
3658 EO_OBJ_DONE(obj_id);
3659
3660 return EINA_VALUE_EMPTY;
3661}
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 7145faaea2..7c7ae9e4a8 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -185,6 +185,8 @@ struct _Efl_Class
185 185
186 const _Efl_Class **mro; 186 const _Efl_Class **mro;
187 187
188 const Efl_Object_Property_Reflection_Ops *reflection;
189
188 /* cached object for faster allocation */ 190 /* cached object for faster allocation */
189 struct { 191 struct {
190 Eina_Trash *trash; 192 Eina_Trash *trash;
diff --git a/src/tests/eo/suite/eo_suite.c b/src/tests/eo/suite/eo_suite.c
index 57b7c613f3..fe8e419e0f 100644
--- a/src/tests/eo/suite/eo_suite.c
+++ b/src/tests/eo/suite/eo_suite.c
@@ -20,6 +20,7 @@ static const Efl_Test_Case etc[] = {
20 { "Eo threaded eo calls", eo_test_threaded_calls }, 20 { "Eo threaded eo calls", eo_test_threaded_calls },
21 { "Eo event calls", eo_test_event}, 21 { "Eo event calls", eo_test_event},
22 { "Eo lifecycle", eo_test_lifecycle}, 22 { "Eo lifecycle", eo_test_lifecycle},
23 { "Eo Reflection", eo_test_reflection},
23 { NULL, NULL } 24 { NULL, NULL }
24}; 25};
25 26
diff --git a/src/tests/eo/suite/eo_suite.h b/src/tests/eo/suite/eo_suite.h
index 700325c465..84da2054f8 100644
--- a/src/tests/eo/suite/eo_suite.h
+++ b/src/tests/eo/suite/eo_suite.h
@@ -12,4 +12,5 @@ void eo_test_value(TCase *tc);
12void eo_test_threaded_calls(TCase *tc); 12void eo_test_threaded_calls(TCase *tc);
13void eo_test_event(TCase *tc); 13void eo_test_event(TCase *tc);
14void eo_test_lifecycle(TCase *tc); 14void eo_test_lifecycle(TCase *tc);
15void eo_test_reflection(TCase *tc);
15#endif /* _EO_SUITE_H */ 16#endif /* _EO_SUITE_H */
diff --git a/src/tests/eo/suite/eo_test_class_simple.c b/src/tests/eo/suite/eo_test_class_simple.c
index dfba73f669..8d82b1eb11 100644
--- a/src/tests/eo/suite/eo_test_class_simple.c
+++ b/src/tests/eo/suite/eo_test_class_simple.c
@@ -23,6 +23,16 @@ _a_set(Eo *obj EINA_UNUSED, void *class_data, int a)
23 efl_event_callback_legacy_call(obj, EV_A_CHANGED, &pd->a); 23 efl_event_callback_legacy_call(obj, EV_A_CHANGED, &pd->a);
24} 24}
25 25
26static void
27_a_set_reflect(Eo *obj, Eina_Value value)
28{
29 int a;
30
31 eina_value_int_convert(&value, &a);
32 simple_a_set(obj, a);
33 eina_value_flush(&value);
34}
35
26static int 36static int
27_a_get(Eo *obj EINA_UNUSED, void *class_data) 37_a_get(Eo *obj EINA_UNUSED, void *class_data)
28{ 38{
@@ -31,6 +41,14 @@ _a_get(Eo *obj EINA_UNUSED, void *class_data)
31 return pd->a; 41 return pd->a;
32} 42}
33 43
44static Eina_Value
45_a_get_reflect(Eo *obj)
46{
47 int a = simple_a_get(obj);
48
49 return eina_value_int_init(a);
50}
51
34static Eina_Bool 52static Eina_Bool
35_a_print(Eo *obj EINA_UNUSED, void *class_data) 53_a_print(Eo *obj EINA_UNUSED, void *class_data)
36{ 54{
@@ -103,8 +121,14 @@ _class_initializer(Efl_Class *klass)
103 EFL_OPS_DEFINE(cops, 121 EFL_OPS_DEFINE(cops,
104 EFL_OBJECT_OP_FUNC(simple_class_hi_print, _class_hi_print), 122 EFL_OBJECT_OP_FUNC(simple_class_hi_print, _class_hi_print),
105 ); 123 );
106 124 static const Efl_Object_Property_Reflection reflection_table[] = {
107 return efl_class_functions_set(klass, &ops, &cops, NULL); 125 {"simple_a", _a_set_reflect, _a_get_reflect},
126 };
127 static const Efl_Object_Property_Reflection_Ops ref_ops = {
128 reflection_table, EINA_C_ARRAY_LENGTH(reflection_table)
129 };
130
131 return efl_class_functions_set(klass, &ops, &cops, &ref_ops);
108} 132}
109 133
110static const Efl_Class_Description class_desc = { 134static const Efl_Class_Description class_desc = {
diff --git a/src/tests/eo/suite/eo_test_reflection.c b/src/tests/eo/suite/eo_test_reflection.c
new file mode 100644
index 0000000000..ae1e11b214
--- /dev/null
+++ b/src/tests/eo/suite/eo_test_reflection.c
@@ -0,0 +1,66 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdio.h>
6
7#include <Eo.h>
8
9#include "eo_suite.h"
10#include "eo_test_class_simple.h"
11
12
13EFL_START_TEST(eo_test_reflection_invalid)
14{
15 Eina_Value numb_val = eina_value_int_init(1337);
16 Eo *simple = efl_new(SIMPLE_CLASS);
17
18 simple_a_set(simple, 22);
19 efl_property_reflection_set(simple, "simple_a_asdf", numb_val);
20 fail_if(efl_property_reflection_get(simple, "simple_a_invalid").type != EINA_VALUE_EMPTY.type);
21}
22EFL_END_TEST
23
24EFL_START_TEST(eo_test_reflection_inherited)
25{
26 const int numb = 42;
27 int number_ref;
28 Eina_Value numb_val = eina_value_int_init(numb);
29 Eo *simple = efl_new(SIMPLE3_CLASS);
30
31 simple_a_set(simple, 22);
32 efl_property_reflection_set(simple, "simple_a", numb_val);
33 ck_assert_int_eq(simple_a_get(simple), numb);
34
35 simple_a_set(simple, 22);
36 Eina_Value res = efl_property_reflection_get(simple, "simple_a");
37 eina_value_int_convert(&res, &number_ref);
38 ck_assert_int_eq(number_ref, 22);
39
40}
41EFL_END_TEST
42
43EFL_START_TEST(eo_test_reflection_simple)
44{
45 const int numb = 42;
46 int number_ref;
47 Eina_Value numb_val = eina_value_int_init(numb);
48 Eo *simple = efl_new(SIMPLE_CLASS);
49
50 simple_a_set(simple, 22);
51 efl_property_reflection_set(simple, "simple_a", numb_val);
52 ck_assert_int_eq(simple_a_get(simple), numb);
53
54 simple_a_set(simple, 22);
55 Eina_Value res = efl_property_reflection_get(simple, "simple_a");
56 eina_value_int_convert(&res, &number_ref);
57 ck_assert_int_eq(number_ref, 22);
58}
59EFL_END_TEST
60
61void eo_test_reflection(TCase *tc)
62{
63 tcase_add_test(tc, eo_test_reflection_simple);
64 tcase_add_test(tc, eo_test_reflection_inherited);
65 tcase_add_test(tc, eo_test_reflection_invalid);
66}
diff --git a/src/tests/eo/suite/meson.build b/src/tests/eo/suite/meson.build
index 6e7f4ba6f7..39f73787e7 100644
--- a/src/tests/eo/suite/meson.build
+++ b/src/tests/eo/suite/meson.build
@@ -17,7 +17,8 @@ eo_suite_src = [
17 'eo_test_event.c', 17 'eo_test_event.c',
18 'eo_test_threaded_calls.c', 18 'eo_test_threaded_calls.c',
19 'eo_test_init.c', 19 'eo_test_init.c',
20 'eo_test_lifecycle.c' 20 'eo_test_lifecycle.c',
21 'eo_test_reflection.c'
21] 22]
22 23
23eo_suite = executable('eo_suite', 24eo_suite = executable('eo_suite',