Eobj: Added mixin data support.
authortasn <tasn>
Thu, 19 Apr 2012 08:52:25 +0000 (08:52 +0000)
committertasn <tasn@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 19 Apr 2012 08:52:25 +0000 (08:52 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/PROTO/eobj@70324 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

examples/mixin/main.c
examples/mixin/mixin2.c
examples/mixin/mixin2.h
examples/mixin/mixin3.c
examples/mixin/mixin3.h
lib/eobj.c

index 8063bc0..966e474 100644 (file)
@@ -1,6 +1,8 @@
 #include "Eobj.h"
 #include "simple.h"
 #include "mixin.h"
+#include "mixin2.h"
+#include "mixin3.h"
 
 #include "../eunit_tests.h"
 
@@ -19,6 +21,14 @@ main(int argc, char *argv[])
    eobj_do(obj, SIMPLE_A_GET(&a), SIMPLE_B_GET(&b),  MIXIN_AB_SUM_GET(&sum));
    fail_if(sum != a + b + 2); /* 2 for the two mixins... */
 
+   eobj_do(obj, MIXIN_AB_SUM_GET(&sum), MIXIN_AB_SUM_GET(&sum));
+
+   Mixin2_Public_Data *pd2 = eobj_data_get(obj, MIXIN2_CLASS);
+   fail_if(pd2->count != 6);
+
+   Mixin3_Public_Data *pd3 = eobj_data_get(obj, MIXIN3_CLASS);
+   fail_if(pd3->count != 9);
+
    eobj_unref(obj);
    eobj_shutdown();
    return 0;
index b3e2cfa..4250615 100644 (file)
 static const Eobj_Class *_my_class = NULL;
 
 static void
-_ab_sum_get(Eobj *obj, void *class_data __UNUSED__, va_list *list)
+_ab_sum_get(Eobj *obj, void *class_data, va_list *list)
 {
+   Mixin2_Public_Data *pd = class_data;
    int *sum = va_arg(*list, int *);
    printf("%s %s\n", eobj_class_name_get(_my_class), __func__);
    eobj_do_super(obj, MIXIN_AB_SUM_GET(sum));
 
    ++*sum;
+   pd->count += 2;
 
      {
         int _a, _b;
@@ -58,7 +60,7 @@ mixin2_class_get(void)
         EOBJ_CLASS_TYPE_MIXIN,
         EOBJ_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
         NULL,
-        0,
+        sizeof(Mixin2_Public_Data),
         _constructor,
         _destructor,
         _class_constructor,
index 26d22d2..1a73fd4 100644 (file)
@@ -3,6 +3,11 @@
 
 #include "Eobj.h"
 
+typedef struct
+{
+   int count;
+} Mixin2_Public_Data;
+
 #define MIXIN2_CLASS mixin2_class_get()
 const Eobj_Class *mixin2_class_get(void) EINA_CONST;
 
index a992cb9..802b024 100644 (file)
@@ -12,11 +12,13 @@ static const Eobj_Class *_my_class = NULL;
 static void
 _ab_sum_get(Eobj *obj, void *class_data __UNUSED__, va_list *list)
 {
+   Mixin3_Public_Data *pd = class_data;
    int *sum = va_arg(*list, int *);
    printf("%s %s\n", eobj_class_name_get(_my_class), __func__);
    eobj_do_super(obj, MIXIN_AB_SUM_GET(sum));
 
    ++*sum;
+   pd->count += 3;
 
      {
         int _a, _b;
@@ -58,7 +60,7 @@ mixin3_class_get(void)
         EOBJ_CLASS_TYPE_MIXIN,
         EOBJ_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
         NULL,
-        0,
+        sizeof(Mixin3_Public_Data),
         _constructor,
         _destructor,
         _class_constructor,
index 12193fb..d2ce840 100644 (file)
@@ -3,6 +3,11 @@
 
 #include "Eobj.h"
 
+typedef struct
+{
+   int count;
+} Mixin3_Public_Data;
+
 #define MIXIN3_CLASS mixin3_class_get()
 const Eobj_Class *mixin3_class_get(void) EINA_CONST;
 
index aeae1bf..2eccaa7 100644 (file)
@@ -63,6 +63,9 @@ struct _Eobj {
       })
 #define OP_SUB_ID_GET(op) ((op) & 0xffff)
 
+#define EOBJ_ALIGN_SIZE(size) \
+        ((size) + (sizeof(void *) - ((size) % sizeof(void *))))
+
 /* Structure of Eobj_Op is:
  * 16bit: class
  * 16bit: op.
@@ -91,6 +94,12 @@ typedef struct
      const Eobj_Class *klass;
 } Eobj_Extension_Node;
 
+typedef struct
+{
+     const Eobj_Class *klass;
+     size_t offset;
+} Eobj_Extension_Data_Offset;
+
 struct _Eobj_Class
 {
    Eobj_Class_Id class_id;
@@ -99,6 +108,9 @@ struct _Eobj_Class
    Dich_Chain1 chain[DICH_CHAIN1_SIZE];
    Eina_Inlist *extensions;
 
+   Eobj_Extension_Data_Offset *extn_data_off;
+   size_t extn_data_size;
+
    const Eobj_Class **mro;
 
    size_t data_offset; /* < Offset of the data within object data. */
@@ -600,7 +612,11 @@ eobj_class_free(Eobj_Class *klass)
           }
      }
 
-   free(klass->mro);
+   if (klass->mro)
+      free(klass->mro);
+
+   if (klass->extn_data_off)
+      free(klass->extn_data_off);
 
    free(klass);
 }
@@ -742,9 +758,7 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
         /* Update the current offset. */
         /* FIXME: Make sure this alignment is enough. */
         klass->data_offset = klass->parent->data_offset +
-           klass->parent->desc->data_size +
-           (sizeof(void *) -
-                  (klass->parent->desc->data_size % sizeof(void *)));
+           EOBJ_ALIGN_SIZE(klass->parent->desc->data_size);
      }
 
    if (!_eobj_class_check_op_descs(klass))
@@ -757,6 +771,47 @@ eobj_class_new(const Eobj_Class_Description *desc, const Eobj_Class *parent, ...
         goto cleanup;
      }
 
+   /* create MIXIN offset table. */
+     {
+        const Eobj_Class **mro_itr = klass->mro;
+        Eobj_Extension_Data_Offset *extn_data_itr;
+        size_t extn_num = 0;
+        size_t extn_data_off = klass->data_offset +
+           EOBJ_ALIGN_SIZE(klass->desc->data_size);
+
+        /* FIXME: Make faster... */
+        while (*mro_itr)
+          {
+             if (((*mro_itr)->desc->type == EOBJ_CLASS_TYPE_MIXIN) &&
+                   ((*mro_itr)->desc->data_size > 0))
+               {
+                  extn_num++;
+               }
+             mro_itr++;
+          }
+
+        klass->extn_data_off = calloc(extn_num + 1,
+              sizeof(*klass->extn_data_off));
+
+        extn_data_itr = klass->extn_data_off;
+        mro_itr = klass->mro;
+        while (*mro_itr)
+          {
+             if (((*mro_itr)->desc->type == EOBJ_CLASS_TYPE_MIXIN) &&
+                   ((*mro_itr)->desc->data_size > 0))
+               {
+                  extn_data_itr->klass = *mro_itr;
+                  extn_data_itr->offset = extn_data_off;
+
+                  extn_data_off += EOBJ_ALIGN_SIZE(extn_data_itr->klass->desc->data_size);
+                  extn_data_itr++;
+               }
+             mro_itr++;
+          }
+
+        klass->extn_data_size = extn_data_off;
+     }
+
    klass->class_id = ++_eobj_classes_last_id;
      {
         /* FIXME: Handle errors. */
@@ -796,7 +851,8 @@ eobj_add(const Eobj_Class *klass, Eobj *parent)
 
    obj->refcount++;
 
-   obj->data_blob = calloc(1, klass->data_offset + klass->desc->data_size);
+   obj->data_blob = calloc(1, klass->data_offset + klass->desc->data_size +
+         klass->extn_data_size);
 
    _eobj_kls_itr_init(obj, EOBJ_NOOP);
    eobj_constructor_error_unset(obj);
@@ -1089,9 +1145,29 @@ eobj_data_get(Eobj *obj, const Eobj_Class *klass)
    /* FIXME: Add a check that this is of the right klass and we don't seg.
     * Probably just return NULL. */
    if (klass->desc->data_size > 0)
-      return ((char *) obj->data_blob) + klass->data_offset;
-   else
-      return NULL;
+     {
+        if (klass->desc->type == EOBJ_CLASS_TYPE_MIXIN)
+          {
+             Eobj_Extension_Data_Offset *doff_itr =
+                eobj_class_get(obj)->extn_data_off;
+
+             if (!doff_itr)
+                return NULL;
+
+             while (doff_itr->klass)
+               {
+                  if (doff_itr->klass == klass)
+                     return ((char *) obj->data_blob) + doff_itr->offset;
+                  doff_itr++;
+               }
+          }
+        else
+          {
+             return ((char *) obj->data_blob) + klass->data_offset;
+          }
+     }
+
+   return NULL;
 }
 
 EAPI Eina_Bool