tests/eo/suite/eo_test_event.c \
tests/eo/suite/eo_test_threaded_calls.c \
tests/eo/suite/eo_test_init.c \
-tests/eo/suite/eo_test_lifecycle.c
+tests/eo/suite/eo_test_lifecycle.c \
+tests/eo/suite/eo_test_reflection.c
tests_eo_eo_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \
void (*class_constructor)(Efl_Class *klass); /**< The constructor of the class. */
void (*class_destructor)(Efl_Class *klass); /**< The destructor of the class. */
};
+/**
+ * Setter type which is used to set an #Eina_Value, this function should access one particular property field
+ */
+typedef void (*Efl_Object_Property_Reflection_Setter)(Eo *obj, Eina_Value value);
+
+/**
+ * Getter type which is used to get an #Eina_Value, this function should access one particular property field
+ */
+typedef Eina_Value (*Efl_Object_Property_Reflection_Getter)(Eo *obj);
+
+/**
+ * @struct _Efl_Object_Property_Reflection
+ *
+ * This structure holds one line of the reflection table.
+ * The two fields get and set might be NULL,
+ * the property_name is a normal c string containing the name of the property
+ * that the get and set function changes.
+ */
+typedef struct _Efl_Object_Property_Reflection{
+ const char *property_name; /**< The name of the property */
+ Efl_Object_Property_Reflection_Setter set; /**< The function used to set a generic #Eina_Value on this property of the object. */
+ Efl_Object_Property_Reflection_Getter get; /**< The function used to retrieve a generic #Eina_Value from this property of the object. */
+} Efl_Object_Property_Reflection;
+
+/**
+ * @struct _Efl_Object_Property_Reflection_Ops
+ *
+ * This structure holds the reflection table and the size of this table.
+ */
+typedef struct _Efl_Object_Property_Reflection_Ops
+{
+ const Efl_Object_Property_Reflection *table; /**< The reflection table. */
+ size_t count; /**< Number of table lines descriptions. */
+} Efl_Object_Property_Reflection_Ops;
/**
* @typedef Efl_Class_Description
* @return True on success, False otherwise.
*
* This should only be called from within the initializer function.
- *
+ * The reflection_table contains a getter and setter per property name. Which are called when either
+ * efl_property_reflection_set() or efl_property_reflection_get() is called.
* @see #EFL_DEFINE_CLASS
*/
-EAPI 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);
+EAPI 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);
/**
* @brief Override Eo functions of this object.
EAPI Eina_Bool efl_destructed_is(const Eo *obj);
/**
+ * @brief Set the given #Eina_Value to the property with the specified \c property_name.
+ * @param obj The object to set the property on
+ * @param property_name The name of the property to modify.
+ * @param value The value to set, the value passed here will be flushed by the function
+ *
+ */
+EAPI void efl_property_reflection_set(Eo *obj, const char *property_name, Eina_Value value);
+
+/**
+ * @brief Retrieve an #Eina_Value containing the current value of the property specified with \c property_name.
+ * @param obj The object to set the property on
+ * @param property_name The name of the property to get.
+ *
+ * @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.
+ */
+EAPI Eina_Value efl_property_reflection_get(Eo *obj, const char *property_name);
+
+
+/**
* @addtogroup Efl_Class_Class Eo's Class class.
* @{
*/
}
EAPI 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)
+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)
{
EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
Efl_Object_Ops empty_ops = { 0 };
if (!class_ops) class_ops = &empty_ops;
+ klass->reflection = reflection_table;
+
klass->ops_count = object_ops->count + class_ops->count;
klass->base_id = _eo_ops_last_id;
};
EOAPI const Eina_Value_Type *EINA_VALUE_TYPE_OBJECT = &_EINA_VALUE_TYPE_OBJECT;
+
+static const Efl_Object_Property_Reflection*
+_efl_class_reflection_find(const _Efl_Class *klass, const char *property_name)
+{
+ const _Efl_Class **klass_iter = klass->extensions;
+ const Efl_Object_Property_Reflection_Ops *ref = klass->reflection;
+ unsigned int i;
+
+ for (i = 0; ref && i < ref->count; ++i)
+ {
+ if (eina_streq(property_name, ref->table[i].property_name))
+ return &ref->table[i];
+ }
+
+ if (klass->parent)
+ {
+ const Efl_Object_Property_Reflection *ref;
+
+ ref = _efl_class_reflection_find(klass->parent, property_name);
+ if (ref) return ref;
+ }
+
+ for (; *klass_iter; klass_iter++)
+ {
+ return _efl_class_reflection_find(*klass_iter, property_name);
+ }
+
+ return NULL;
+}
+
+EAPI void
+efl_property_reflection_set(Eo *obj_id, const char *property_name, Eina_Value value)
+{
+ EO_OBJ_POINTER_GOTO(obj_id, obj, end);
+ const Efl_Object_Property_Reflection *reflection = _efl_class_reflection_find(obj->klass, property_name);
+
+ if (!reflection || !reflection->set) goto end;
+
+ reflection->set(obj_id, value);
+ EO_OBJ_DONE(obj_id);
+ return;
+end:
+ eina_value_flush(&value);
+ EO_OBJ_DONE(obj_id);
+}
+
+EAPI Eina_Value
+efl_property_reflection_get(Eo *obj_id, const char *property_name)
+{
+ EO_OBJ_POINTER(obj_id, obj);
+ const Efl_Object_Property_Reflection *reflection = _efl_class_reflection_find(obj->klass, property_name);
+
+ if (!reflection || !reflection->get) goto end;
+
+ return reflection->get(obj_id);
+end:
+ EO_OBJ_DONE(obj_id);
+
+ return EINA_VALUE_EMPTY;
+}
const _Efl_Class **mro;
+ const Efl_Object_Property_Reflection_Ops *reflection;
+
/* cached object for faster allocation */
struct {
Eina_Trash *trash;
{ "Eo threaded eo calls", eo_test_threaded_calls },
{ "Eo event calls", eo_test_event},
{ "Eo lifecycle", eo_test_lifecycle},
+ { "Eo Reflection", eo_test_reflection},
{ NULL, NULL }
};
void eo_test_threaded_calls(TCase *tc);
void eo_test_event(TCase *tc);
void eo_test_lifecycle(TCase *tc);
+void eo_test_reflection(TCase *tc);
#endif /* _EO_SUITE_H */
efl_event_callback_legacy_call(obj, EV_A_CHANGED, &pd->a);
}
+static void
+_a_set_reflect(Eo *obj, Eina_Value value)
+{
+ int a;
+
+ eina_value_int_convert(&value, &a);
+ simple_a_set(obj, a);
+ eina_value_flush(&value);
+}
+
static int
_a_get(Eo *obj EINA_UNUSED, void *class_data)
{
return pd->a;
}
+static Eina_Value
+_a_get_reflect(Eo *obj)
+{
+ int a = simple_a_get(obj);
+
+ return eina_value_int_init(a);
+}
+
static Eina_Bool
_a_print(Eo *obj EINA_UNUSED, void *class_data)
{
EFL_OPS_DEFINE(cops,
EFL_OBJECT_OP_FUNC(simple_class_hi_print, _class_hi_print),
);
-
- return efl_class_functions_set(klass, &ops, &cops, NULL);
+ static const Efl_Object_Property_Reflection reflection_table[] = {
+ {"simple_a", _a_set_reflect, _a_get_reflect},
+ };
+ static const Efl_Object_Property_Reflection_Ops ref_ops = {
+ reflection_table, EINA_C_ARRAY_LENGTH(reflection_table)
+ };
+
+ return efl_class_functions_set(klass, &ops, &cops, &ref_ops);
}
static const Efl_Class_Description class_desc = {
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <Eo.h>
+
+#include "eo_suite.h"
+#include "eo_test_class_simple.h"
+
+
+EFL_START_TEST(eo_test_reflection_invalid)
+{
+ Eina_Value numb_val = eina_value_int_init(1337);
+ Eo *simple = efl_new(SIMPLE_CLASS);
+
+ simple_a_set(simple, 22);
+ efl_property_reflection_set(simple, "simple_a_asdf", numb_val);
+ fail_if(efl_property_reflection_get(simple, "simple_a_invalid").type != EINA_VALUE_EMPTY.type);
+}
+EFL_END_TEST
+
+EFL_START_TEST(eo_test_reflection_inherited)
+{
+ const int numb = 42;
+ int number_ref;
+ Eina_Value numb_val = eina_value_int_init(numb);
+ Eo *simple = efl_new(SIMPLE3_CLASS);
+
+ simple_a_set(simple, 22);
+ efl_property_reflection_set(simple, "simple_a", numb_val);
+ ck_assert_int_eq(simple_a_get(simple), numb);
+
+ simple_a_set(simple, 22);
+ Eina_Value res = efl_property_reflection_get(simple, "simple_a");
+ eina_value_int_convert(&res, &number_ref);
+ ck_assert_int_eq(number_ref, 22);
+
+}
+EFL_END_TEST
+
+EFL_START_TEST(eo_test_reflection_simple)
+{
+ const int numb = 42;
+ int number_ref;
+ Eina_Value numb_val = eina_value_int_init(numb);
+ Eo *simple = efl_new(SIMPLE_CLASS);
+
+ simple_a_set(simple, 22);
+ efl_property_reflection_set(simple, "simple_a", numb_val);
+ ck_assert_int_eq(simple_a_get(simple), numb);
+
+ simple_a_set(simple, 22);
+ Eina_Value res = efl_property_reflection_get(simple, "simple_a");
+ eina_value_int_convert(&res, &number_ref);
+ ck_assert_int_eq(number_ref, 22);
+}
+EFL_END_TEST
+
+void eo_test_reflection(TCase *tc)
+{
+ tcase_add_test(tc, eo_test_reflection_simple);
+ tcase_add_test(tc, eo_test_reflection_inherited);
+ tcase_add_test(tc, eo_test_reflection_invalid);
+}
'eo_test_event.c',
'eo_test_threaded_calls.c',
'eo_test_init.c',
- 'eo_test_lifecycle.c'
+ 'eo_test_lifecycle.c',
+ 'eo_test_reflection.c'
]
eo_suite = executable('eo_suite',