Eo: Added support for class functions.

SVN revision: 71119
This commit is contained in:
Tom Hacohen 2012-05-15 14:16:58 +00:00
parent 90804082c0
commit 2cf5e56694
9 changed files with 337 additions and 59 deletions

View File

@ -37,6 +37,15 @@ _print2(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *list EINA_UN
printf("Hey2\n"); printf("Hey2\n");
} }
static void
_class_print(const Eo_Class *klass, va_list *list)
{
(void) list;
printf("Print %s-%s\n", eo_class_name_get(klass), eo_class_name_get(MY_CLASS));
fail_if(!eo_class_do_super(klass, simple_class_print()));
fail_if(eo_class_do_super(klass, simple_class_print2()));
}
static void static void
_class_constructor(Eo_Class *klass) _class_constructor(Eo_Class *klass)
{ {
@ -44,6 +53,7 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set), EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set),
EO_OP_FUNC(INHERIT2_ID(INHERIT2_SUB_ID_PRINT), _print), EO_OP_FUNC(INHERIT2_ID(INHERIT2_SUB_ID_PRINT), _print),
EO_OP_FUNC(INHERIT2_ID(INHERIT2_SUB_ID_PRINT2), _print2), EO_OP_FUNC(INHERIT2_ID(INHERIT2_SUB_ID_PRINT2), _print2),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_PRINT), _class_print),
EO_OP_FUNC_SENTINEL EO_OP_FUNC_SENTINEL
}; };

View File

@ -38,6 +38,15 @@ main(int argc, char *argv[])
fail_if(eo_do_super(obj, simple_a_print())); fail_if(eo_do_super(obj, simple_a_print()));
fail_if(eo_do(obj, simple_class_print()));
fail_if(!eo_class_do(SIMPLE_CLASS, simple_class_print()));
fail_if(!eo_class_do(INHERIT_CLASS, simple_class_print()));
fail_if(!eo_class_do(INHERIT2_CLASS, simple_class_print()));
fail_if(!eo_class_do(INHERIT3_CLASS, simple_class_print()));
fail_if(eo_class_do(SIMPLE_CLASS, simple_a_print()));
eo_constructor_super(obj); eo_constructor_super(obj);
eo_destructor_super(obj); eo_destructor_super(obj);

View File

@ -2,6 +2,7 @@
#include "simple.h" #include "simple.h"
#include "config.h" #include "config.h"
#include "../eunit_tests.h"
EAPI Eo_Op SIMPLE_BASE_ID = 0; EAPI Eo_Op SIMPLE_BASE_ID = 0;
@ -25,12 +26,30 @@ _a_print(const Eo *obj EINA_UNUSED, const void *class_data, va_list *list)
printf("Print %s %d\n", eo_class_name_get(MY_CLASS), pd->a); printf("Print %s %d\n", eo_class_name_get(MY_CLASS), pd->a);
} }
static void
_class_print(const Eo_Class *klass, va_list *list)
{
(void) list;
printf("Print %s-%s\n", eo_class_name_get(klass), eo_class_name_get(MY_CLASS));
fail_if(eo_class_do_super(klass, simple_class_print()));
fail_if(eo_class_do_super(klass, simple_class_print2()));
}
static void
_class_print2(const Eo_Class *klass, va_list *list)
{
(void) list;
printf("Print %s-%s\n", eo_class_name_get(klass), eo_class_name_get(MY_CLASS));
}
static void static void
_class_constructor(Eo_Class *klass) _class_constructor(Eo_Class *klass)
{ {
const Eo_Op_Func_Description func_desc[] = { const Eo_Op_Func_Description func_desc[] = {
EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set), EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set),
EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), _a_print), EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), _a_print),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_PRINT), _class_print),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_PRINT2), _class_print2),
EO_OP_FUNC_SENTINEL EO_OP_FUNC_SENTINEL
}; };
@ -40,6 +59,8 @@ _class_constructor(Eo_Class *klass)
static const Eo_Op_Description op_desc[] = { static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(SIMPLE_SUB_ID_A_SET, "i", "Set property A"), EO_OP_DESCRIPTION(SIMPLE_SUB_ID_A_SET, "i", "Set property A"),
EO_OP_DESCRIPTION_CONST(SIMPLE_SUB_ID_A_PRINT, "", "Print property A"), EO_OP_DESCRIPTION_CONST(SIMPLE_SUB_ID_A_PRINT, "", "Print property A"),
EO_OP_DESCRIPTION_CLASS(SIMPLE_SUB_ID_CLASS_PRINT, "", "Print class name."),
EO_OP_DESCRIPTION_CLASS(SIMPLE_SUB_ID_CLASS_PRINT2, "", "Print2 class name."),
EO_OP_DESCRIPTION_SENTINEL EO_OP_DESCRIPTION_SENTINEL
}; };

View File

@ -8,6 +8,8 @@ extern EAPI Eo_Op SIMPLE_BASE_ID;
enum { enum {
SIMPLE_SUB_ID_A_SET, SIMPLE_SUB_ID_A_SET,
SIMPLE_SUB_ID_A_PRINT, SIMPLE_SUB_ID_A_PRINT,
SIMPLE_SUB_ID_CLASS_PRINT,
SIMPLE_SUB_ID_CLASS_PRINT2,
SIMPLE_SUB_ID_LAST SIMPLE_SUB_ID_LAST
}; };
@ -20,6 +22,8 @@ typedef struct
#define simple_a_set(a) SIMPLE_ID(SIMPLE_SUB_ID_A_SET), EO_TYPECHECK(int, a) #define simple_a_set(a) SIMPLE_ID(SIMPLE_SUB_ID_A_SET), EO_TYPECHECK(int, a)
#define simple_a_print() SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT) #define simple_a_print() SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT)
#define simple_class_print() SIMPLE_ID(SIMPLE_SUB_ID_CLASS_PRINT)
#define simple_class_print2() SIMPLE_ID(SIMPLE_SUB_ID_CLASS_PRINT2)
extern const Eo_Event_Description _SIG_A_CHANGED; extern const Eo_Event_Description _SIG_A_CHANGED;
#define SIG_A_CHANGED (&(_SIG_A_CHANGED)) #define SIG_A_CHANGED (&(_SIG_A_CHANGED))

View File

@ -41,6 +41,24 @@
*/ */
EAPI extern Eina_Lock _eo_class_creation_lock; EAPI extern Eina_Lock _eo_class_creation_lock;
/**
* @internal
* An enum representing the possible types of an Op.
*/
enum _Eo_Op_Type
{
EO_OP_TYPE_REGULAR = 0, /**< Regular op. */
EO_OP_TYPE_CONST, /**< Const op - object should not change. */
EO_OP_TYPE_CLASS, /**< Class op - a class op. Like static in Java/C++. */
};
/**
* @internal
* @typedef Eo_Op_Type
* A convenience typedef for #_Eo_Op_Type.
*/
typedef enum _Eo_Op_Type Eo_Op_Type;
/** /**
* @defgroup Eo Eo Generic Object System * @defgroup Eo Eo Generic Object System
* *
@ -75,6 +93,13 @@ typedef struct _Eo Eo;
*/ */
typedef unsigned int Eo_Op; typedef unsigned int Eo_Op;
/**
* @typedef Eo_Class
* The basic Object class type.
* @ingroup Eo_Class
*/
typedef struct _Eo_Class Eo_Class;
/** /**
* @def EO_NOOP * @def EO_NOOP
* A special #Eo_Op meaning "No operation". * A special #Eo_Op meaning "No operation".
@ -100,6 +125,16 @@ typedef void (*eo_op_func_type)(Eo *, void *class_data, va_list *list);
*/ */
typedef void (*eo_op_func_type_const)(const Eo *, const void *class_data, va_list *list); typedef void (*eo_op_func_type_const)(const Eo *, const void *class_data, va_list *list);
/**
* @typedef eo_op_func_type_class
* The type of the class Op functions. This is the same as #eo_op_func_type,\
* exepct that it's for usage with class functions, and not with object
* functions.
*
* @see eo_op_func_type
*/
typedef void (*eo_op_func_type_class)(const Eo_Class *, va_list *list);
/** /**
* @addtogroup Eo_Events Eo's Event Handling * @addtogroup Eo_Events Eo's Event Handling
* @{ * @{
@ -141,12 +176,6 @@ typedef struct _Eo_Event_Description Eo_Event_Description;
* @{ * @{
*/ */
/**
* @typedef Eo_Class
* The basic Object class type.
*/
typedef struct _Eo_Class Eo_Class;
/** /**
* @def EO_DEFINE_CLASS(class_get_func_name, class_desc, parent_class, ...) * @def EO_DEFINE_CLASS(class_get_func_name, class_desc, parent_class, ...)
* A convenience macro to be used for creating the class_get function. This * A convenience macro to be used for creating the class_get function. This
@ -218,7 +247,7 @@ struct _Eo_Op_Func_Description
{ {
Eo_Op op; /**< The op */ Eo_Op op; /**< The op */
eo_op_func_type func; /**< The function to call for the op. */ eo_op_func_type func; /**< The function to call for the op. */
Eina_Bool constant; /**< @c EINA_TRUE if this function is a const. */ Eo_Op_Type op_type; /**< The type of the op */
}; };
/** /**
@ -234,7 +263,7 @@ typedef struct _Eo_Op_Func_Description Eo_Op_Func_Description;
* *
* @see EO_OP_FUNC_CONST * @see EO_OP_FUNC_CONST
*/ */
#define EO_OP_FUNC(op, func) { op, EO_TYPECHECK(eo_op_func_type, func), EINA_FALSE } #define EO_OP_FUNC(op, func) { op, EO_TYPECHECK(eo_op_func_type, func), EO_OP_TYPE_REGULAR }
/** /**
* @def EO_OP_FUNC_CONST(op, func) * @def EO_OP_FUNC_CONST(op, func)
@ -244,7 +273,17 @@ typedef struct _Eo_Op_Func_Description Eo_Op_Func_Description;
* *
* @see EO_OP_FUNC * @see EO_OP_FUNC
*/ */
#define EO_OP_FUNC_CONST(op, func) { op, (eo_op_func_type) EO_TYPECHECK(eo_op_func_type_const, func), EINA_TRUE } #define EO_OP_FUNC_CONST(op, func) { op, (eo_op_func_type) EO_TYPECHECK(eo_op_func_type_const, func), EO_OP_TYPE_CONST }
/**
* @def EO_OP_FUNC_CLASS(op, func)
* A convenience macro to be used when populating the #Eo_Op_Func_Description
* array.
* The same as #EO_OP_FUNC but for class functions.
*
* @see EO_OP_FUNC
*/
#define EO_OP_FUNC_CLASS(op, func) { op, (eo_op_func_type) EO_TYPECHECK(eo_op_func_type_class, func), EO_OP_TYPE_CLASS }
/** /**
* @def EO_OP_FUNC_SENTINEL * @def EO_OP_FUNC_SENTINEL
@ -263,7 +302,7 @@ struct _Eo_Op_Description
const char *name; /**< The name of the op. */ const char *name; /**< The name of the op. */
const char *type; /**< descripbes the Op's function signature. */ const char *type; /**< descripbes the Op's function signature. */
const char *doc; /**< Explanation about the Op. */ const char *doc; /**< Explanation about the Op. */
Eina_Bool constant; /**< @c EINA_TRUE if this op's implementation should not change the obj. */ Eo_Op_Type op_type; /**< The type of the Op. */
}; };
/** /**
@ -317,10 +356,11 @@ typedef struct _Eo_Class_Description Eo_Class_Description;
* @param type The type string for the op. * @param type The type string for the op.
* @param doc Additional doc for the op. * @param doc Additional doc for the op.
* @see Eo_Op_Description * @see Eo_Op_Description
* @see EO_OP_DESCRIPTION_CLASS
* @see EO_OP_DESCRIPTION_CONST * @see EO_OP_DESCRIPTION_CONST
* @see EO_OP_DESCRIPTION_SENTINEL * @see EO_OP_DESCRIPTION_SENTINEL
*/ */
#define EO_OP_DESCRIPTION(sub_id, type, doc) { sub_id, #sub_id, type, doc, EINA_FALSE } #define EO_OP_DESCRIPTION(sub_id, type, doc) { sub_id, #sub_id, type, doc, EO_OP_TYPE_REGULAR }
/** /**
* @def EO_OP_DESCRIPTION_CONST(op, type, doc) * @def EO_OP_DESCRIPTION_CONST(op, type, doc)
@ -334,7 +374,21 @@ typedef struct _Eo_Class_Description Eo_Class_Description;
* @see EO_OP_DESCRIPTION * @see EO_OP_DESCRIPTION
* @see EO_OP_DESCRIPTION_SENTINEL * @see EO_OP_DESCRIPTION_SENTINEL
*/ */
#define EO_OP_DESCRIPTION_CONST(sub_id, type, doc) { sub_id, #sub_id, type, doc, EINA_TRUE } #define EO_OP_DESCRIPTION_CONST(sub_id, type, doc) { sub_id, #sub_id, type, doc, EO_OP_TYPE_CONST }
/**
* @def EO_OP_DESCRIPTION_CLASS(op, type, doc)
* An helper macro to help populating #Eo_Op_Description
* This macro is the same as EO_OP_DESCRIPTION but indicates that the op's
* implementation is of type CLASS.
* @param sub_id The sub id of the op being described.
* @param type The type string for the op.
* @param doc Additional doc for the op.
* @see Eo_Op_Description
* @see EO_OP_DESCRIPTION
* @see EO_OP_DESCRIPTION_SENTINEL
*/
#define EO_OP_DESCRIPTION_CLASS(sub_id, type, doc) { sub_id, #sub_id, type, doc, EO_OP_TYPE_CLASS }
/** /**
* @def EO_OP_DESCRIPTION_SENTINEL * @def EO_OP_DESCRIPTION_SENTINEL
@ -412,9 +466,16 @@ EAPI Eina_Bool eo_shutdown(void);
#define eo_query(obj, ...) eo_do_internal((Eo *) EO_TYPECHECK(const Eo *, obj), EINA_TRUE, __VA_ARGS__, EO_NOOP) #define eo_query(obj, ...) eo_do_internal((Eo *) EO_TYPECHECK(const Eo *, obj), EINA_TRUE, __VA_ARGS__, EO_NOOP)
/** /**
* @brief Issues ops on an object. * @def eo_class_do
* A convenience wrapper around eo_class_do_internal()
* @see eo_class_do_internal
*/
#define eo_class_do(klass, ...) eo_class_do_internal(klass, __VA_ARGS__, EO_NOOP)
/**
* @brief Calls op functions of an object
* @param obj The object to work on * @param obj The object to work on
* @param constant @c EINA_TRUE if this call is on a constant object. * @param op_type The type of the ops that are passed.
* @param ... NULL terminated list of OPs and parameters. * @param ... NULL terminated list of OPs and parameters.
* @return @c EINA_TRUE on success. * @return @c EINA_TRUE on success.
* *
@ -423,7 +484,20 @@ EAPI Eina_Bool eo_shutdown(void);
* *
* @see #eo_do * @see #eo_do
*/ */
EAPI Eina_Bool eo_do_internal(Eo *obj, Eina_Bool constant, ...); EAPI Eina_Bool eo_do_internal(Eo *obj, Eo_Op_Type op_type, ...);
/**
* @brief Calls op functions of a class.
* @param klass The class to work on
* @param ... NULL terminated list of OPs and parameters.
* @return @c EINA_TRUE on success.
*
* Use the helper macros, don't pass the parameters manually.
* Use #eo_do instead of this function.
*
* @see #eo_class_do
*/
EAPI Eina_Bool eo_class_do_internal(const Eo_Class *klass, ...);
/** /**
* @brief Calls the super function for the specific op. * @brief Calls the super function for the specific op.
@ -455,10 +529,22 @@ EAPI Eina_Bool eo_do_internal(Eo *obj, Eina_Bool constant, ...);
*/ */
#define eo_do_super(obj, ...) eo_do_super_internal(obj, EINA_FALSE, __VA_ARGS__) #define eo_do_super(obj, ...) eo_do_super_internal(obj, EINA_FALSE, __VA_ARGS__)
/**
* @brief Calls the super function for the specific op.
* @param klass The klass to work on
* @param ... list of parameters.
* @return @c EINA_TRUE on success.
*
* Unlike eo_class_do(), this function only accepts one op.
*
* @see #eo_class_do
*/
#define eo_class_do_super(klass, ...) eo_class_do_super_internal(klass, __VA_ARGS__)
/** /**
* @brief Calls the super function for the specific op. * @brief Calls the super function for the specific op.
* @param obj The object to work on * @param obj The object to work on
* @param constant @c EINA_TRUE if this call is on a constant object. * @param op_type The type of the ops that are passed.
* @param op The wanted op. * @param op The wanted op.
* @param ... list of parameters. * @param ... list of parameters.
* @return @c EINA_TRUE on success. * @return @c EINA_TRUE on success.
@ -469,7 +555,21 @@ EAPI Eina_Bool eo_do_internal(Eo *obj, Eina_Bool constant, ...);
* @see #eo_do_super * @see #eo_do_super
* @see #eo_query_super * @see #eo_query_super
*/ */
EAPI Eina_Bool eo_do_super_internal(Eo *obj, Eina_Bool constant, Eo_Op op, ...); EAPI Eina_Bool eo_do_super_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, ...);
/**
* @brief Calls the super function for the specific op.
* @param klass The klass to work on
* @param op The wanted op.
* @param ... list of parameters.
* @return @c EINA_TRUE on success.
*
* Don't use this function, use the wrapping macros instead.
*
* @see #eo_class_do
* @see #eo_class_do_super
*/
EAPI Eina_Bool eo_class_do_super_internal(const Eo_Class *klass, Eo_Op op, ...);
/** /**
* @brief Gets the class of the object. * @brief Gets the class of the object.

View File

@ -113,6 +113,7 @@ struct _Eo_Class
size_t extn_data_size; size_t extn_data_size;
const Eo_Class **mro; const Eo_Class **mro;
Eo_Kls_Itr mro_itr;
size_t data_offset; /* < Offset of the data within object data. */ size_t data_offset; /* < Offset of the data within object data. */
@ -340,29 +341,62 @@ _eo_kls_itr_reached_end(const Eo_Kls_Itr *cur)
return !(*kls_itr && *(kls_itr + 1)); return !(*kls_itr && *(kls_itr + 1));
} }
static Eina_Bool static inline const op_type_funcs *
_eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list) _eo_kls_itr_func_get(const Eo_Class *klass, Eo_Kls_Itr *mro_itr, Eo_Op op, Eo_Kls_Itr *prev_state)
{ {
const Eo_Class *klass; _eo_kls_itr_init(klass, mro_itr, op, prev_state);
Eina_Bool ret = EINA_FALSE; klass = _eo_kls_itr_get(mro_itr);
const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
if (op_desc &&
((constant == EINA_TRUE) && (op_desc->constant == EINA_FALSE)))
{
ERR("Tried calling non-const or non-existant op '%s' (%d) from a const (query) function.", (op_desc) ? op_desc->name : NULL, op);
return EINA_FALSE;
}
Eo_Kls_Itr prev_state;
_eo_kls_itr_init(obj->klass, &obj->mro_itr, op, &prev_state);
klass = _eo_kls_itr_get(&obj->mro_itr);
if (klass) if (klass)
{ {
const op_type_funcs *func = _dich_func_get(klass, op); const op_type_funcs *func = _dich_func_get(klass, op);
if (func && func->func) if (func && func->func)
{
return func;
}
}
return NULL;
}
static void
_eo_op_err_no_op_print(Eo_Op op, const Eo_Class *klass)
{
const Eo_Class *op_klass = OP_CLASS_GET(op);
const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL;
ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.",
op, _eo_op_id_name_get(op), _dom_name,
(klass) ? klass->desc->name : NULL);
}
static Eina_Bool
_eo_op_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, va_list *p_list)
{
Eina_Bool ret = EINA_FALSE;
const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
if (op_desc)
{
if (op_desc->op_type == EO_OP_TYPE_CLASS)
{
ERR("Tried calling a class op '%s' (%d) from a non-class context.", (op_desc) ? op_desc->name : NULL, op);
return EINA_FALSE;
}
else if ((op_type == EO_OP_TYPE_CONST) &&
(op_desc->op_type != EO_OP_TYPE_CONST))
{
ERR("Tried calling non-const or non-existant op '%s' (%d) from a const (query) function.", (op_desc) ? op_desc->name : NULL, op);
return EINA_FALSE;
}
}
Eo_Kls_Itr prev_state;
{
const op_type_funcs *func =
_eo_kls_itr_func_get(obj->klass, &obj->mro_itr, op, &prev_state);
if (func)
{ {
func->func(obj, _eo_data_get(obj, func->src), p_list); func->func(obj, _eo_data_get(obj, func->src), p_list);
ret = EINA_TRUE; ret = EINA_TRUE;
@ -376,7 +410,7 @@ _eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list)
Eo *emb_obj; Eo *emb_obj;
EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj) EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
{ {
if (_eo_op_internal(emb_obj, constant, op, p_list)) if (_eo_op_internal(emb_obj, op_type, op, p_list))
{ {
ret = EINA_TRUE; ret = EINA_TRUE;
goto end; goto end;
@ -390,7 +424,7 @@ end:
} }
EAPI Eina_Bool EAPI Eina_Bool
eo_do_internal(Eo *obj, Eina_Bool constant, ...) eo_do_internal(Eo *obj, Eo_Op_Type op_type, ...)
{ {
Eina_Bool ret = EINA_TRUE; Eina_Bool ret = EINA_TRUE;
Eo_Op op = EO_NOOP; Eo_Op op = EO_NOOP;
@ -400,18 +434,14 @@ eo_do_internal(Eo *obj, Eina_Bool constant, ...)
_eo_ref(obj); _eo_ref(obj);
va_start(p_list, constant); va_start(p_list, op_type);
op = va_arg(p_list, Eo_Op); op = va_arg(p_list, Eo_Op);
while (op) while (op)
{ {
if (!_eo_op_internal(obj, constant, op, &p_list)) if (!_eo_op_internal(obj, op_type, op, &p_list))
{ {
const Eo_Class *op_klass = OP_CLASS_GET(op); _eo_op_err_no_op_print(op, obj->klass);
const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL;
ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.",
op, _eo_op_id_name_get(op), _dom_name,
obj->klass->desc->name);
ret = EINA_FALSE; ret = EINA_FALSE;
break; break;
} }
@ -425,27 +455,110 @@ eo_do_internal(Eo *obj, Eina_Bool constant, ...)
} }
EAPI Eina_Bool EAPI Eina_Bool
eo_do_super_internal(Eo *obj, Eina_Bool constant, Eo_Op op, ...) eo_do_super_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, ...)
{ {
const Eo_Class *obj_klass; const Eo_Class *nklass;
Eina_Bool ret = EINA_TRUE; Eina_Bool ret = EINA_TRUE;
va_list p_list; va_list p_list;
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE); EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
/* Advance the kls itr. */ /* Advance the kls itr. */
obj_klass = _eo_kls_itr_next(&obj->mro_itr, op); nklass = _eo_kls_itr_next(&obj->mro_itr, op);
if (obj->mro_itr.op != op) if (obj->mro_itr.op != op)
return EINA_FALSE; return EINA_FALSE;
va_start(p_list, op); va_start(p_list, op);
if (!_eo_op_internal(obj, constant, op, &p_list)) if (!_eo_op_internal(obj, op_type, op, &p_list))
{ {
const Eo_Class *op_klass = OP_CLASS_GET(op); _eo_op_err_no_op_print(op, nklass);
const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL; ret = EINA_FALSE;
ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.", }
op, _eo_op_id_name_get(op), _dom_name, va_end(p_list);
(obj_klass) ? obj_klass->desc->name : NULL);
return ret;
}
static Eina_Bool
_eo_class_op_internal(Eo_Class *klass, Eo_Op op, va_list *p_list)
{
Eina_Bool ret = EINA_FALSE;
const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
if (op_desc)
{
if (op_desc->op_type != EO_OP_TYPE_CLASS)
{
ERR("Tried calling an instant op '%s' (%d) from a class context.", (op_desc) ? op_desc->name : NULL, op);
return EINA_FALSE;
}
}
Eo_Kls_Itr prev_state;
{
const op_type_funcs *func =
_eo_kls_itr_func_get(klass, &klass->mro_itr, op, &prev_state);
if (func)
{
((eo_op_func_type_class) func->func)(klass, p_list);
ret = EINA_TRUE;
goto end;
}
}
end:
_eo_kls_itr_end(&klass->mro_itr, &prev_state);
return ret;
}
EAPI Eina_Bool
eo_class_do_internal(const Eo_Class *klass, ...)
{
Eina_Bool ret = EINA_TRUE;
Eo_Op op = EO_NOOP;
va_list p_list;
EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
va_start(p_list, klass);
op = va_arg(p_list, Eo_Op);
while (op)
{
if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
{
_eo_op_err_no_op_print(op, klass);
ret = EINA_FALSE;
break;
}
op = va_arg(p_list, Eo_Op);
}
va_end(p_list);
return ret;
}
EAPI Eina_Bool
eo_class_do_super_internal(const Eo_Class *klass, Eo_Op op, ...)
{
const Eo_Class *nklass;
Eina_Bool ret = EINA_TRUE;
va_list p_list;
EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
/* Advance the kls itr. */
nklass = _eo_kls_itr_next(&((Eo_Class *) klass)->mro_itr, op);
if (klass->mro_itr.op != op)
return EINA_FALSE;
va_start(p_list, op);
if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
{
_eo_op_err_no_op_print(op, nklass);
ret = EINA_FALSE; ret = EINA_FALSE;
} }
va_end(p_list); va_end(p_list);
@ -635,13 +748,13 @@ eo_class_funcs_set(Eo_Class *klass, const Eo_Op_Func_Description *func_descs)
{ {
const Eo_Op_Description *op_desc = _eo_op_id_desc_get(itr->op); const Eo_Op_Description *op_desc = _eo_op_id_desc_get(itr->op);
if (EINA_LIKELY(!op_desc || (itr->constant == op_desc->constant))) if (EINA_LIKELY(!op_desc || (itr->op_type == op_desc->op_type)))
{ {
_dich_func_set(klass, itr->op, itr->func); _dich_func_set(klass, itr->op, itr->func);
} }
else else
{ {
ERR("Set function's constant property (%d) is different than the one in the op description (%d) for op '%s' in class '%s'.", itr->constant, op_desc->constant, op_desc->name, klass->desc->name); ERR("Set function's op type (%d) is different than the one in the op description (%d) for op '%s' in class '%s'.", itr->op_type, op_desc->op_type, op_desc->name, klass->desc->name);
} }
} }
} }

View File

@ -25,12 +25,20 @@ _a_print(const Eo *obj EINA_UNUSED, const void *class_data, va_list *list)
printf("Print %s %d\n", eo_class_name_get(MY_CLASS), pd->a); printf("Print %s %d\n", eo_class_name_get(MY_CLASS), pd->a);
} }
static void
_class_hi_print(const Eo_Class *klass, va_list *list)
{
(void) list;
printf("Hi Print %s\n", eo_class_name_get(klass));
}
static void static void
_class_constructor(Eo_Class *klass) _class_constructor(Eo_Class *klass)
{ {
const Eo_Op_Func_Description func_desc[] = { const Eo_Op_Func_Description func_desc[] = {
EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set), EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _a_set),
EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), _a_print), EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), _a_print),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_HI_PRINT), _class_hi_print),
EO_OP_FUNC_SENTINEL EO_OP_FUNC_SENTINEL
}; };
@ -40,6 +48,7 @@ _class_constructor(Eo_Class *klass)
static const Eo_Op_Description op_desc[] = { static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(SIMPLE_SUB_ID_A_SET, "i", "Set property A"), EO_OP_DESCRIPTION(SIMPLE_SUB_ID_A_SET, "i", "Set property A"),
EO_OP_DESCRIPTION_CONST(SIMPLE_SUB_ID_A_PRINT, "", "Print property A"), EO_OP_DESCRIPTION_CONST(SIMPLE_SUB_ID_A_PRINT, "", "Print property A"),
EO_OP_DESCRIPTION_CLASS(SIMPLE_SUB_ID_CLASS_HI_PRINT, "", "Print Hi"),
EO_OP_DESCRIPTION_SENTINEL EO_OP_DESCRIPTION_SENTINEL
}; };

View File

@ -8,6 +8,7 @@ extern EAPI Eo_Op SIMPLE_BASE_ID;
enum { enum {
SIMPLE_SUB_ID_A_SET, SIMPLE_SUB_ID_A_SET,
SIMPLE_SUB_ID_A_PRINT, SIMPLE_SUB_ID_A_PRINT,
SIMPLE_SUB_ID_CLASS_HI_PRINT,
SIMPLE_SUB_ID_LAST SIMPLE_SUB_ID_LAST
}; };
@ -20,6 +21,7 @@ typedef struct
#define simple_a_set(a) SIMPLE_ID(SIMPLE_SUB_ID_A_SET), EO_TYPECHECK(int, a) #define simple_a_set(a) SIMPLE_ID(SIMPLE_SUB_ID_A_SET), EO_TYPECHECK(int, a)
#define simple_a_print() SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT) #define simple_a_print() SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT)
#define simple_class_hi_print() SIMPLE_ID(SIMPLE_SUB_ID_CLASS_HI_PRINT)
extern const Eo_Event_Description _SIG_A_CHANGED; extern const Eo_Event_Description _SIG_A_CHANGED;
#define SIG_A_CHANGED (&(_SIG_A_CHANGED)) #define SIG_A_CHANGED (&(_SIG_A_CHANGED))

View File

@ -309,19 +309,29 @@ _const_ops_a_print(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *l
_const_ops_counter++; _const_ops_counter++;
} }
static void
_const_ops_class_hi_print(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
{
_const_ops_counter++;
}
static void static void
_const_ops_class_constructor(Eo_Class *klass) _const_ops_class_constructor(Eo_Class *klass)
{ {
const Eo_Op_Func_Description func_desc[] = { const Eo_Op_Func_Description func_desc[] = {
EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), _const_ops_a_set), EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), (eo_op_func_type_const) _const_ops_a_set),
EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), _const_ops_a_print), EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), (eo_op_func_type) _const_ops_a_print),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_A_SET), (eo_op_func_type_class) _const_ops_a_set),
EO_OP_FUNC_CLASS(SIMPLE_ID(SIMPLE_SUB_ID_A_PRINT), (eo_op_func_type_class) _const_ops_a_print),
EO_OP_FUNC_CONST(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_HI_PRINT), (eo_op_func_type_const) _const_ops_class_hi_print),
EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_CLASS_HI_PRINT), (eo_op_func_type) _const_ops_class_hi_print),
EO_OP_FUNC_SENTINEL EO_OP_FUNC_SENTINEL
}; };
eo_class_funcs_set(klass, func_desc); eo_class_funcs_set(klass, func_desc);
} }
START_TEST(eo_const_ops) START_TEST(eo_op_types)
{ {
eo_init(); eo_init();
@ -343,7 +353,7 @@ START_TEST(eo_const_ops)
fail_if(!klass); fail_if(!klass);
Eo *obj = eo_add(klass, NULL); Eo *obj = eo_add(klass, NULL);
eo_do(obj, simple_a_set(7), simple_a_print()); eo_do(obj, simple_a_set(7), simple_a_print(), simple_class_hi_print());
fail_if(_const_ops_counter != 0); fail_if(_const_ops_counter != 0);
eo_unref(obj); eo_unref(obj);
@ -358,5 +368,5 @@ void eo_test_class_errors(TCase *tc)
tcase_add_test(tc, eo_inherit_errors); tcase_add_test(tc, eo_inherit_errors);
tcase_add_test(tc, eo_inconsistent_mro); tcase_add_test(tc, eo_inconsistent_mro);
tcase_add_test(tc, eo_bad_interface); tcase_add_test(tc, eo_bad_interface);
tcase_add_test(tc, eo_const_ops); tcase_add_test(tc, eo_op_types);
} }