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.
This commit is contained in:
Jérémy Zurcher 2013-12-25 14:51:52 +01:00 committed by Tom Hacohen
parent d0153fabc1
commit 473609e1d3
2 changed files with 92 additions and 12 deletions

View 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)

View 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 \
{ \