forked from enlightenment/efl
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:
parent
d0153fabc1
commit
473609e1d3
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
{ \
|
||||
|
|
Loading…
Reference in New Issue