From 473609e1d31a9638a751c5d545b4f3ea5a969f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Wed, 25 Dec 2013 14:51:52 +0100 Subject: [PATCH] eo2: eliminate the need of OPID and Eo_Op_Func_Description 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 | 45 +++++++++++++++++++++++++++---------- src/lib/eo/eo.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index c639cc0f84..2760a3d924 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -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) diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 532dbcd850..feb41f392b 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -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 \ { \