/**
* @brief Get a pointer to the data of an object for a specific class.
+ *
* The data reference count is not incremented. The pointer must be used only
* in the scope of the function and its callees.
+ *
* @param obj the object to work on.
* @param klass the klass associated with the data.
* @return a pointer to the data.
*
* @see efl_data_ref()
* @see efl_data_unref()
+ * @see efl_data_scope_safe_get()
*/
EAPI void *efl_data_scope_get(const Eo *obj, const Efl_Class *klass);
/**
+ * @brief Safely get a pointer to the data of an object for a specific class.
+ *
+ * This call runs a dynamic check and returns NULL if there is no valid data
+ * to return.
+ *
+ * The data reference count is not incremented. The pointer must be used only
+ * in the scope of the function and its callees. This function will return NULL
+ * if there is no data for this class, or if this object is not an instance of
+ * the given class. The function will return NULL if the data size is 0.
+ * Note that objects of class A inheriting from another class C as an
+ * interface (like: class A(B, C) {} ) will have no data for class C. This
+ * means that efl_isa(a, C) will return true but there is no data for C. This
+ * function's behaviour is similar to efl_data_scope_get() when running in
+ * debug mode (but this prints less error logs).
+ *
+ * @param obj the object to work on.
+ * @param klass the klass associated with the data.
+ * @return a pointer to the data or NULL in case of error or $obj was NULL.
+ *
+ * @see efl_data_scope_get()
+ *
+ * @since 1.20
+ */
+EAPI void *efl_data_scope_safe_get(const Eo *obj, const Efl_Class *klass);
+
+/**
* @def efl_data_xref(obj, klass, ref_obj)
* Use this macro if you want to associate a referencer object.
* Convenience macro around efl_data_xref_internal()
vtable->chain = calloc(vtable->size, sizeof(*vtable->chain));
}
-#ifdef EO_DEBUG
static Eina_Bool
_eo_class_mro_has(const _Efl_Class *klass, const _Efl_Class *find)
{
}
return EINA_FALSE;
}
-#endif
static Eina_List *
_eo_class_list_remove_duplicates(Eina_List* list)
}
EAPI void *
+efl_data_scope_safe_get(const Eo *obj_id, const Efl_Class *klass_id)
+{
+#ifndef EO_DEBUG
+ void *ret = NULL;
+
+ if (!obj_id) return NULL;
+ EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
+ EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
+
+ if (_eo_class_mro_has(obj->klass, klass))
+ ret = _efl_data_scope_safe_get(obj, klass);
+
+err_klass:
+ EO_OBJ_DONE(obj_id);
+ return ret;
+#else
+ return efl_data_scope_get(obj_id, klass_id);
+#endif
+}
+
+EAPI void *
efl_data_xref_internal(const char *file, int line, const Eo *obj_id, const Efl_Class *klass_id, const Eo *ref_obj_id)
{
void *ret = NULL;
EO_VERSION,
"Simple2",
EFL_CLASS_TYPE_REGULAR,
- 0,
+ sizeof(Simple_Public_Data),
_class_initializer2,
NULL,
NULL
EFL_DEFINE_CLASS(simple2_class_get, &class_desc2, EO_CLASS, NULL)
+
+static Eina_Bool
+_class_initializer3(Efl_Class *klass)
+{
+ return efl_class_functions_set(klass, NULL, NULL);
+}
+
+static const Efl_Class_Description class_desc3 = {
+ EO_VERSION,
+ "Simple3",
+ EFL_CLASS_TYPE_REGULAR,
+ sizeof(Simple_Public_Data),
+ _class_initializer3,
+ NULL,
+ NULL
+};
+
+EFL_DEFINE_CLASS(simple3_class_get, &class_desc3, SIMPLE_CLASS, SIMPLE2_CLASS, NULL)
+
+
static Efl_Object*
_interface_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const Efl_Object *klass)
{
#define SIMPLE2_CLASS simple2_class_get()
const Efl_Class *simple2_class_get(void);
+// simple3(simple, simple2)
+#define SIMPLE3_CLASS simple3_class_get()
+const Efl_Class *simple3_class_get(void);
+
#define SEARCHABLE_CLASS searchable_class_get()
const Efl_Class *searchable_class_get(void);
}
END_TEST
+START_TEST(efl_data_safe_fetch)
+{
+ efl_object_init();
+
+ Eo *obj = efl_add(SIMPLE2_CLASS, NULL);
+ fail_if(!obj || !efl_data_scope_safe_get(obj, SIMPLE2_CLASS));
+ efl_unref(obj);
+
+ obj = efl_add(SIMPLE3_CLASS, NULL);
+ fail_if(!obj);
+ fail_if(!efl_isa(obj, SIMPLE_CLASS));
+ fail_if(!efl_isa(obj, SIMPLE2_CLASS));
+ fail_if(!efl_isa(obj, SIMPLE3_CLASS));
+ fail_if(!efl_data_scope_safe_get(obj, SIMPLE_CLASS));
+ fail_if(!efl_data_scope_safe_get(obj, SIMPLE3_CLASS));
+ fail_if(efl_data_scope_safe_get(obj, SIMPLE2_CLASS) != NULL);
+ fail_if(efl_data_scope_safe_get(NULL, EFL_OBJECT_CLASS) != NULL);
+ efl_unref(obj);
+
+ efl_object_shutdown();
+}
+END_TEST
+
START_TEST(efl_isa_tests)
{
efl_object_init();
tcase_add_test(tc, efl_object_override_tests);
tcase_add_test(tc, eo_signals);
tcase_add_test(tc, efl_data_fetch);
+ tcase_add_test(tc, efl_data_safe_fetch);
tcase_add_test(tc, efl_isa_tests);
tcase_add_test(tc, efl_composite_tests);
tcase_add_test(tc, eo_man_free);