Eobj: Fixed a bug in event_callback_del.
[profile/ivi/eobj.git] / lib / eobj.c
index 0ce4a22..26552a8 100644 (file)
@@ -218,12 +218,17 @@ typedef struct
 static inline Eina_Bool
 _eobj_kls_itr_init(Eobj *obj, Eobj_Op op)
 {
-   if (obj->kls_itr &&
-         EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eobj_Kls_Itr_Node))
+   if (obj->kls_itr)
      {
-        return EINA_FALSE;
+        Eobj_Kls_Itr_Node *node =
+           EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eobj_Kls_Itr_Node);
+        if (node->op == op)
+          {
+             return EINA_FALSE;
+          }
      }
-   else
+
+
      {
         Eobj_Kls_Itr_Node *node = calloc(1, sizeof(*node));
         node->op = op;
@@ -249,6 +254,15 @@ _eobj_kls_itr_end(Eobj *obj, Eobj_Op op)
 }
 
 static inline const Eobj_Class *
+_eobj_kls_itr_get(Eobj *obj)
+{
+   Eobj_Kls_Itr_Node *node =
+      EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eobj_Kls_Itr_Node);
+
+   return (node) ? *(node->kls_itr) : NULL;
+}
+
+static inline const Eobj_Class *
 _eobj_kls_itr_next(Eobj *obj)
 {
    Eobj_Kls_Itr_Node *node =
@@ -305,70 +319,50 @@ _eobj_op_id_desc_get(Eobj_Op op)
 }
 
 static Eina_Bool
-_eobj_op_internal(Eobj *obj, const Eobj_Class *obj_klass, Eobj_Op op, va_list *p_list, Eina_Bool recursive)
+_eobj_op_internal(Eobj *obj, Eobj_Op op, va_list *p_list)
 {
-   const Eobj_Class *klass = obj_klass;
-   eobj_op_func_type func;
-
-   if (!obj_klass)
-      return EINA_FALSE;
+   const Eobj_Class *klass;
+   Eina_Bool ret = EINA_FALSE;
+   Eina_Bool _itr_init;
 
+   _itr_init = _eobj_kls_itr_init(obj, op);
+   klass = _eobj_kls_itr_get(obj);
    while (klass)
      {
-        func = dich_func_get(klass, op);
+        eobj_op_func_type func = dich_func_get(klass, op);
 
         if (func)
           {
              func(obj, op, p_list);
-             return EINA_TRUE;
-          }
-        else
-          {
-             klass = klass->parent;
+             ret = EINA_TRUE;
+             goto end;
           }
-     }
 
-   if (!recursive)
-      return EINA_FALSE;
+        klass = _eobj_kls_itr_next(obj);
+     }
 
-   if (!klass)
+   /* Try composite objects */
      {
-        klass = obj_klass;
-        /* FIXME: Should probably flatten everything. to be faster. */
-          {
-             /* Try MIXINS */
-             Eobj_Extension_Node *itr;
-             EINA_INLIST_FOREACH(klass->extensions, itr)
-               {
-                  if (_eobj_op_internal(obj, itr->klass, op, p_list, recursive))
-                    {
-                       return EINA_TRUE;
-                    }
-               }
-          }
-
-        /* Try composite objects */
+        Eina_List *itr;
+        Eobj *emb_obj;
+        EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
           {
-             Eina_List *itr;
-             Eobj *emb_obj;
-             EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
+             if (_eobj_op_internal(emb_obj, op, p_list))
                {
-                  if (_eobj_op_internal(emb_obj, eobj_class_get(emb_obj), op, p_list, recursive))
-                    {
-                       return EINA_TRUE;
-                    }
+                  ret = EINA_TRUE;
+                  goto end;
                }
           }
-
-        /* If haven't found anything, return FALSE */
-        return EINA_FALSE;
      }
 
-   return EINA_TRUE;
+end:
+
+   if (_itr_init) _eobj_kls_itr_end(obj, op);
+   return ret;
 }
 
 static inline Eina_Bool
-_eobj_ops_internal(Eobj *obj, const Eobj_Class *obj_klass, va_list *p_list)
+_eobj_ops_internal(Eobj *obj, va_list *p_list)
 {
    Eina_Bool ret = EINA_TRUE;
    Eobj_Op op = 0;
@@ -376,7 +370,7 @@ _eobj_ops_internal(Eobj *obj, const Eobj_Class *obj_klass, va_list *p_list)
    op = va_arg(*p_list, Eobj_Op);
    while (op)
      {
-        if (!_eobj_op_internal(obj, obj_klass, op, p_list, EINA_TRUE))
+        if (!_eobj_op_internal(obj, op, p_list))
           {
              const Eobj_Op_Description *desc = _eobj_op_id_desc_get(op);
              const char *_id_name = (desc) ? desc->name : NULL;
@@ -384,7 +378,7 @@ _eobj_ops_internal(Eobj *obj, const Eobj_Class *obj_klass, va_list *p_list)
              const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL;
              ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.",
                    op, _id_name, _dom_name,
-                   obj_klass->desc->name);
+                   obj->klass->desc->name);
              ret = EINA_FALSE;
              break;
           }
@@ -400,7 +394,7 @@ eobj_do_internal(Eobj *obj, ...)
    Eina_Bool ret;
    va_list p_list;
    va_start(p_list, obj);
-   ret = _eobj_ops_internal(obj, eobj_class_get(obj), &p_list);
+   ret = _eobj_ops_internal(obj, &p_list);
    va_end(p_list);
    return ret;
 }
@@ -409,16 +403,14 @@ EAPI Eina_Bool
 eobj_super_do(Eobj *obj, Eobj_Op op, ...)
 {
    const Eobj_Class *obj_klass;
-
    Eina_Bool ret = EINA_TRUE;
    va_list p_list;
-   Eina_Bool kls_itr_end = _eobj_kls_itr_init(obj, op);
-   obj_klass = _eobj_kls_itr_next(obj);
-
-   if (!obj_klass) goto end;
 
    va_start(p_list, op);
-   if (!_eobj_op_internal(obj, obj_klass, op, &p_list, EINA_FALSE))
+
+   /* Advance the kls itr. */
+   obj_klass = _eobj_kls_itr_next(obj);
+   if (!_eobj_op_internal(obj, op, &p_list))
      {
         const Eobj_Op_Description *desc = _eobj_op_id_desc_get(op);
         const char *_id_name = (desc) ? desc->name : NULL;
@@ -426,13 +418,11 @@ eobj_super_do(Eobj *obj, Eobj_Op op, ...)
         const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL;
         ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.",
               op, _id_name, _dom_name,
-              obj_klass->desc->name);
+              (obj_klass) ? obj_klass->desc->name : NULL);
         ret = EINA_FALSE;
      }
    va_end(p_list);
 
-end:
-   if (kls_itr_end) _eobj_kls_itr_end(obj, op);
    return ret;
 }
 
@@ -584,14 +574,6 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
 
    klass = calloc(1, sizeof(Eobj_Class));
    klass->parent = parent;
-   klass->class_id = ++_eobj_classes_last_id;
-     {
-        /* FIXME: Handle errors. */
-        Eobj_Class **tmp;
-        tmp = realloc(_eobj_classes, _eobj_classes_last_id * sizeof(*_eobj_classes));
-        _eobj_classes = tmp;
-        _eobj_classes[klass->class_id - 1] = klass;
-     }
 
    /* Handle class extensions */
      {
@@ -624,9 +606,36 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
 
    klass->desc = desc;
 
-   /* If we have a class parent, update the current offset. */
+   /* Handle the inheritance */
    if (klass->parent)
      {
+        /* Verify the inheritance is allowed. */
+        switch (klass->desc->type)
+          {
+           case EOBJ_CLASS_TYPE_REGULAR:
+           case EOBJ_CLASS_TYPE_REGULAR_NO_INSTANT:
+              if ((klass->parent->desc->type != EOBJ_CLASS_TYPE_REGULAR) &&
+                    (klass->parent->desc->type != EOBJ_CLASS_TYPE_REGULAR_NO_INSTANT))
+                {
+                   /* FIXME: Actually handle it. */
+                   ERR("Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
+                   goto cleanup;
+                }
+              break;
+           case EOBJ_CLASS_TYPE_INTERFACE:
+           case EOBJ_CLASS_TYPE_MIXIN:
+              if ((klass->parent->desc->type != EOBJ_CLASS_TYPE_REGULAR) &&
+                    (klass->parent->desc->type != EOBJ_CLASS_TYPE_REGULAR_NO_INSTANT))
+                {
+                   /* FIXME: Actually handle it. */
+                   ERR("Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
+                   goto cleanup;
+                }
+              break;
+          }
+
+
+        /* Update the current offset. */
         /* FIXME: Make sure this alignment is enough. */
         klass->data_offset = klass->parent->data_offset +
            klass->parent->desc->private_size +
@@ -634,6 +643,15 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
                   (klass->parent->desc->private_size % sizeof(void *)));
      }
 
+   klass->class_id = ++_eobj_classes_last_id;
+     {
+        /* FIXME: Handle errors. */
+        Eobj_Class **tmp;
+        tmp = realloc(_eobj_classes, _eobj_classes_last_id * sizeof(*_eobj_classes));
+        _eobj_classes = tmp;
+        _eobj_classes[klass->class_id - 1] = klass;
+     }
+
    _eobj_class_base_op_init(klass);
 
    /* FIXME: Shouldn't be called here - should be called from eobj_add. */
@@ -642,6 +660,10 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
    va_end(p_list);
 
    return klass;
+
+cleanup:
+   eobj_class_free(klass);
+   return NULL;
 }
 #undef _CLS_NEW_CHECK
 
@@ -1007,6 +1029,10 @@ eobj_composite_is(Eobj *emb_obj)
    Eobj *obj = eobj_parent_get(emb_obj);
    Eina_List *itr;
    Eobj *tmp;
+
+   if (!obj)
+      return EINA_FALSE;
+
    EINA_LIST_FOREACH(obj->composite_objects, itr, tmp)
      {
         if (tmp == emb_obj)
@@ -1124,11 +1150,13 @@ eobj_event_callback_del(Eobj *obj, const Eobj_Event_Description *desc, Eobj_Even
              cb->delete_me = EINA_TRUE;
              _eobj_callbacks_clear(obj);
              ret = data;
-             goto end;
+             goto found;
           }
      }
 
-end:
+   return NULL;
+
+found:
    eobj_event_callback_call(obj, EOBJ_SIG_CALLBACK_DEL, desc);
    return ret;
 }
@@ -1149,11 +1177,13 @@ eobj_event_callback_del_full(Eobj *obj, const Eobj_Event_Description *desc, Eobj
              cb->delete_me = EINA_TRUE;
              _eobj_callbacks_clear(obj);
              ret = data;
-             goto end;
+             goto found;
           }
      }
 
-end:
+   return NULL;
+
+found:
    eobj_event_callback_call(obj, EOBJ_SIG_CALLBACK_DEL, desc);
    return ret;
 }