eo2: eliminate the need of OPID and Eo_Op_Func_Description
authorJérémy Zurcher <jeremy@asynk.ch>
Wed, 25 Dec 2013 13:51:52 +0000 (14:51 +0100)
committerTom Hacohen <tom@stosb.com>
Thu, 10 Apr 2014 03:20:15 +0000 (04:20 +0100)
at class elaboration, sort the op descriptions using the function pointer.
when calling a function, do a dichotomic search in the
class op descriptions to find the corresponding OP_ID,
then keep it in a static variable.

src/lib/eo/Eo.h
src/lib/eo/eo.c

index c639cc0..2760a3d 100644 (file)
@@ -448,6 +448,15 @@ typedef struct _Eo_Op_Description Eo_Op_Description;
  */
 #define EO_VERSION 1
 
+typedef struct _Eo2_Op_Description
+{
+   void *func;             /**< The static function to call for the op. */
+   void *api_func;         /**< The EAPI function offering this op. */
+   Eo_Op op;               /**< The op. */
+   Eo_Op_Type op_type;     /**< The type of the Op. */
+   const char *doc;        /**< Explanation about the Op. */
+} Eo2_Op_Description;
+
 /**
  * @struct _Eo_Class_Description
  * This struct holds the description of a class.
@@ -604,32 +613,44 @@ typedef struct _Eo2_Op_Call_Data
 #define EO_FUNC_CALLV(...) func(objid, call.data, __VA_ARGS__)
 
 /* XXX: Essential, because we need to adjust objid for comp objects. */
-#define EO_FUNC_BODY(Name, Ret, Id, Func, DefRet)                       \
+#define EO_FUNC_BODY(Name, Ret, Func, DefRet, OpDescs)                  \
   Ret                                                                   \
   Name(_Eo *obj, Eo *objid)                                             \
   {                                                                     \
+     static Eo_Op op = EO_NOOP;                                         \
+     if ( op == EO_NOOP ) op = eo2_get_op_id(OpDescs, (void*)Name);     \
      typedef Ret (*__##Name##_func)(Eo *, void *obj_data);              \
      Eo2_Op_Call_Data call;                                             \
-     if (!eo2_call_resolve(obj, Id(Name), &call)) return DefRet;        \
-     __##Name##_func func = (__##Name##_func) call.func;               \
+     if (!eo2_call_resolve(obj, op, &call)) return DefRet;              \
+     __##Name##_func func = (__##Name##_func) call.func;                \
      return Func;                                                       \
   }
 
-#define EO_FUNC_BODYV(Name, Ret, Id, Func, DefRet, ...)                        \
-  Ret                                                                  \
-  Name(_Eo *obj, Eo *objid, __VA_ARGS__)                               \
-  {                                                                    \
-     typedef Ret (*__##Name##_func)(Eo *, void *obj_data, __VA_ARGS__);        \
-     Eo2_Op_Call_Data call;                                            \
-     if (!eo2_call_resolve(obj, Id(Name), &call)) return DefRet;        \
-     __##Name##_func func = (__##Name##_func) call.func;               \
-     return Func;                                                      \
+#define EO_FUNC_BODYV(Name, Ret, Func, DefRet, OpDescs, ...)            \
+  Ret                                                                   \
+  Name(_Eo *obj, Eo *objid, __VA_ARGS__)                                \
+  {                                                                     \
+     static Eo_Op op = EO_NOOP;                                         \
+     if ( op == EO_NOOP ) op = eo2_get_op_id(OpDescs, (void*)Name);     \
+     typedef Ret (*__##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
+     Eo2_Op_Call_Data call;                                             \
+     if (!eo2_call_resolve(obj, op, &call)) return DefRet;              \
+     __##Name##_func func = (__##Name##_func) call.func;                \
+     return Func;                                                       \
   }
 
 EAPI _Eo * eo2_do_start(Eo *obj_id);
+
 #define eo2_call_resolve(obj_id, op, call) eo2_call_resolve_internal(obj_id, NULL, op, call)
 EAPI Eina_Bool eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass, Eo_Op op, Eo2_Op_Call_Data *call);
 
+EAPI Eo_Op eo2_get_op_id(Eo2_Op_Description *op_descs, void *api_func);
+
+#define OP_DESC_SIZE(desc) (sizeof(desc)/sizeof(Eo2_Op_Description) -1 )
+
+EAPI void
+eo2_class_funcs_set(Eo_Class *klass_id, Eo2_Op_Description *op_descs, int n);
+
 /* FIXME: Don't use this unref, use an internal one. Reduce id resolution. */
 
 #define eo2_do_end(obj) eo_unref(obj)
index 532dbcd..feb41f3 100644 (file)
@@ -287,6 +287,65 @@ eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_C
    return EINA_FALSE;
 }
 
+
+EAPI Eo_Op
+eo2_get_op_id(Eo2_Op_Description *op_descs, void *api_func)
+{
+   Eo2_Op_Description *op_desc;
+
+   /* should do a binary search */
+   for (op_desc = op_descs; op_desc->op != EO_NOOP; op_desc++)
+     {
+        if (op_desc->api_func == api_func)
+          return op_desc->op;
+     }
+
+   return EO_NOOP;
+}
+
+static int
+eo2_fct_cmp(const void *p1, const void *p2)
+{
+   const Eo2_Op_Description *op1, *op2;
+   op1 = (Eo2_Op_Description *) p1;
+   op2 = (Eo2_Op_Description *) p2;
+   if (op1->api_func > op2->api_func) return -1;
+   else if (op1->api_func < op2->api_func) return 1;
+   else return 0;
+}
+
+EAPI void
+eo2_class_funcs_set(Eo_Class *klass_id, Eo2_Op_Description *op_descs, int n)
+{
+   int i, base_op_id;
+   _Eo_Class *klass;
+   Eo2_Op_Description *op_desc;
+
+   klass = _eo_class_pointer_get(klass_id);
+   EO_MAGIC_RETURN(klass, EO_CLASS_EINA_MAGIC);
+
+   base_op_id = *klass->desc->ops.base_op_id;
+
+   /* so that eo2_get_op_id can do a binary search to get the OP from the api_func */
+   qsort((void*)op_descs, n, sizeof(Eo2_Op_Description), eo2_fct_cmp);
+
+   i = 0;
+   for (op_desc = op_descs; op_desc->op_type != EO_OP_TYPE_INVALID; op_desc++)
+     {
+        // take care of overriding, maybe ok ??
+        if (op_desc->op == EO_NOOP)
+          {
+            op_desc->op = base_op_id + i;
+            i++;
+          }
+        /* printf("%d %p %p\n", op_desc->op, op_desc->api_func, op_desc->func); */
+        // no need to check func->op_type != op_desc->op_type
+        // as op_descs wourd replace op_desc
+        // what about func->op == EO_NOOP ??
+        _dich_func_set(klass, op_desc->op, op_desc->func);
+     }
+}
+
 #define _EO_OP_ERR_NO_OP_PRINT(file, line, op, klass) \
    do \
       { \