jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=b96722cfb8baf5761295c487faf7396a873a2428

commit b96722cfb8baf5761295c487faf7396a873a2428
Author: Jean-Philippe Andre <[email protected]>
Date:   Wed Jun 14 13:40:46 2017 +0900

    eo: Add API efl_data_scope_safe_get
    
    This is a safe version of efl_data_scope_get, meaning that it will
    return NULL if the object is not of the required type, or if there
    is no data for that class, or if the given class was used as an
    interface (and isn't a mixin).
    
    @feature
---
 src/lib/eo/Eo.h                           | 29 +++++++++++++++++++++++++++++
 src/lib/eo/eo.c                           | 23 +++++++++++++++++++++--
 src/tests/eo/suite/eo_test_class_simple.c | 22 +++++++++++++++++++++-
 src/tests/eo/suite/eo_test_class_simple.h |  4 ++++
 src/tests/eo/suite/eo_test_general.c      | 24 ++++++++++++++++++++++++
 5 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 32c132edaa..03230015bd 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -1225,18 +1225,47 @@ EAPI Eo * _efl_add_internal_start(const char *file, int 
line, const Efl_Class *k
 
 /**
  * @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()
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 55f00e1006..e4f767b687 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -1102,7 +1102,6 @@ _vtable_init(Eo_Vtable *vtable, size_t size)
    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)
 {
@@ -1116,7 +1115,6 @@ _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)
@@ -2003,6 +2001,27 @@ err_klass:
 }
 
 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;
diff --git a/src/tests/eo/suite/eo_test_class_simple.c 
b/src/tests/eo/suite/eo_test_class_simple.c
index 56620c68a2..281549c629 100644
--- a/src/tests/eo/suite/eo_test_class_simple.c
+++ b/src/tests/eo/suite/eo_test_class_simple.c
@@ -142,7 +142,7 @@ static const Efl_Class_Description class_desc2 = {
      EO_VERSION,
      "Simple2",
      EFL_CLASS_TYPE_REGULAR,
-     0,
+     sizeof(Simple_Public_Data),
      _class_initializer2,
      NULL,
      NULL
@@ -150,6 +150,26 @@ static const Efl_Class_Description class_desc2 = {
 
 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)
 {
diff --git a/src/tests/eo/suite/eo_test_class_simple.h 
b/src/tests/eo/suite/eo_test_class_simple.h
index 7d7432b5a0..9023119577 100644
--- a/src/tests/eo/suite/eo_test_class_simple.h
+++ b/src/tests/eo/suite/eo_test_class_simple.h
@@ -29,6 +29,10 @@ EAPI int simple2_class_beef_get(const Efl_Class *obj);
 #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);
 
diff --git a/src/tests/eo/suite/eo_test_general.c 
b/src/tests/eo/suite/eo_test_general.c
index 8798e2a80e..0d6f322f1f 100644
--- a/src/tests/eo/suite/eo_test_general.c
+++ b/src/tests/eo/suite/eo_test_general.c
@@ -304,6 +304,29 @@ START_TEST(efl_data_fetch)
 }
 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();
@@ -1687,6 +1710,7 @@ void eo_test_general(TCase *tc)
    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);

-- 


Reply via email to