summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2013-07-30 15:02:35 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2013-09-17 22:36:59 +0200
commit62ae579d049e9586f5d5e07bce6106ca780f24fd (patch)
tree54fcc305040202709d5f8ba35525add2cb96ecab
parent21460f135fe8adfdc5b15713a235ed8450630932 (diff)
downloadefl-62ae579d049e9586f5d5e07bce6106ca780f24fd.tar.gz
implement class function support
-rw-r--r--src/lib/eo/Eo.h68
-rw-r--r--src/lib/eo/eo.c107
2 files changed, 146 insertions, 29 deletions
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 4cab1b08ae..68832e700d 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -623,13 +623,15 @@ EAPI Eina_Bool eo_shutdown(void);
// to fetch internal function and object data at once
typedef struct _Eo2_Op_Call_Data
{
- Eo *obj_id;
- void *func;
- void *data;
+ Eo *obj_id;
+ Eo_Class *klass_id;
+ void *func;
+ void *data;
} Eo2_Op_Call_Data;
// to pass the internal function call to EO2_FUNC_BODY (as Func parameter)
#define EO2_FUNC_CALL(...) _func_(call.obj_id, call.data, __VA_ARGS__)
+#define EO2_CLASS_FUNC_CALL(...) _func_(call.klass_id, __VA_ARGS__)
// cache OP id, get real fct and object data then do the call
#define _EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \
@@ -640,6 +642,14 @@ typedef struct _Eo2_Op_Call_Data
__##Name##_func _func_ = (__##Name##_func) call.func; \
return Func; \
+#define _EO2_CLASS_FUNC_COMMON(Name, Ret, Func, DefRet, Class) \
+ static Eo_Op op = EO_NOOP; \
+ if ( op == EO_NOOP ) op = eo2_api_op_id_get((void*)Name, Class); \
+ Eo2_Op_Call_Data call; \
+ if (!eo2_call_resolve(op, &call)) return DefRet; \
+ __##Name##_func _func_ = (__##Name##_func) call.func; \
+ return Func; \
+
// to define an EAPI function
#define EO2_FUNC_BODY(Name, Ret, DefRet) \
Ret \
@@ -661,6 +671,27 @@ typedef struct _Eo2_Op_Call_Data
#define EO2_VOID_FUNC_BODYV(Name, Func, ...) EO2_FUNC_BODYV(Name, void, Func, , __VA_ARGS__)
+// to define a EAPI class function
+#define EO2_CLASS_FUNC_BODY(Name, Ret, DefRet, Class) \
+ Ret \
+ Name(void) \
+ { \
+ typedef Ret (*__##Name##_func)(Eo_Class *); \
+ _EO2_CLASS_FUNC_COMMON(Name, Ret, _func_(call.klass_id), DefRet, Class) \
+ }
+
+#define EO2_VOID_CLASS_FUNC_BODY(Name, Class) EO2_CLASS_FUNC_BODY(Name, void, , Class)
+
+#define EO2_CLASS_FUNC_BODYV(Name, Ret, Func, DefRet, Class, ...) \
+ Ret \
+ Name(__VA_ARGS__) \
+ { \
+ typedef Ret (*__##Name##_func)(Eo_Class *, __VA_ARGS__); \
+ _EO2_CLASS_FUNC_COMMON(Name, Ret, Func, DefRet, Class) \
+ }
+
+#define EO2_VOID_CLASS_FUNC_BODYV(Name, Func, Class, ...) EO2_CLASS_FUNC_BODYV(Name, void, Func, , Class, __VA_ARGS__)
+
// OP ID of an overriding function
#define EO2_OP_OVERRIDE ((Eo_Op) -1)
#define EO2_OP_VIRTUAL ((Eo_Op) -2)
@@ -668,6 +699,7 @@ typedef struct _Eo2_Op_Call_Data
#define EO2_OP_FUNC(_private, _api, _doc) {_private, _api, EO_NOOP, EO_OP_TYPE_REGULAR, _doc}
#define EO2_OP_CLASS_FUNC(_private, _api, _doc) {_private, _api, EO_NOOP, EO_OP_TYPE_CLASS, _doc}
#define EO2_OP_FUNC_OVERRIDE(_private, _api) {_private, _api, EO2_OP_OVERRIDE, EO_OP_TYPE_REGULAR, NULL}
+#define EO2_OP_CLASS_FUNC_OVERRIDE(_private, _api) {_private, _api, EO2_OP_OVERRIDE, EO_OP_TYPE_CLASS, NULL}
#define EO2_OP_FUNC_VIRTUAL(_api, _doc) {NULL, _api, EO2_OP_VIRTUAL, EO_OP_TYPE_REGULAR, _doc}
#define EO2_OP_SENTINEL { NULL, NULL, 0, EO_OP_TYPE_INVALID, NULL}
@@ -680,13 +712,16 @@ EAPI Eina_Bool eo2_call_resolve_internal(const Eo_Class *klass, Eo_Op op, Eo2_Op
// start of eo2_do barrier, gets the object pointer and ref it, put it on the stask
EAPI Eina_Bool eo2_do_start(Eo *obj_id, Eina_Bool do_super);
+EAPI Eina_Bool eo2_class_do_start(const Eo_Class *klass_id, Eina_Bool do_super);
// end of the eo2_do barrier, unref the obj, move the stack pointer
EAPI void eo2_do_end(Eo **ojb);
+EAPI void eo2_class_do_end(const Eo_Class **klass);
EAPI int eo2_call_stack_depth();
#define EO2_DO_CLEANUP __attribute__((cleanup(eo2_do_end)))
+#define EO2_CLASS_DO_CLEANUP __attribute__((cleanup(eo2_class_do_end)))
// eo object method calls batch,
#define eo2_do(objid, ...) \
@@ -713,11 +748,28 @@ EAPI int eo2_call_stack_depth();
} \
} while (0)
-// FIXME
-#define eo2_class_do(clsid, ...) \
- do \
- { \
- do { __VA_ARGS__ ; } while (0); \
+#define eo2_class_do(clsid, ...) \
+ do \
+ { \
+ const Eo_Class *_clsid_ = clsid; \
+ if (eo2_class_do_start(_clsid_, EINA_FALSE)) \
+ { \
+ const Eo_Class *_id_clean_ EO2_CLASS_DO_CLEANUP = _clsid_; \
+ __VA_ARGS__; \
+ (void) _id_clean_; \
+ } \
+ } while (0)
+
+#define eo2_class_super_do(clsid, ...) \
+ do \
+ { \
+ const Eo_Class *_clsid_ = clsid; \
+ if (eo2_class_do_start(_clsid_, EINA_TRUE)) \
+ { \
+ const Eo_Class *_id_clean_ EO2_CLASS_DO_CLEANUP = _clsid_; \
+ __VA_ARGS__; \
+ (void) _id_clean_; \
+ } \
} while (0)
/*****************************************************************************/
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index f47d408320..befc9fd451 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -276,7 +276,7 @@ typedef struct _Eo2_Stack_Frame
{
Eo *obj_id;
_Eo *obj;
- const _Eo_Class *cur_klass;
+ const _Eo_Class *klass;
void *obj_data;
} Eo2_Stack_Frame;
@@ -307,7 +307,7 @@ EAPI Eina_Bool
eo2_do_start(Eo *obj_id, Eina_Bool do_super)
{
_Eo * obj;
- const _Eo_Class *cur_klass;
+ const _Eo_Class *klass;
Eo2_Stack_Frame *fptr;
fptr = eo2_call_stack.frame_ptr;
@@ -315,9 +315,9 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super)
{
obj = fptr->obj;
if (do_super)
- cur_klass = _eo2_kls_itr_next(obj->klass, fptr->cur_klass);
+ klass = _eo2_kls_itr_next(obj->klass, fptr->klass);
else
- cur_klass = fptr->cur_klass;
+ klass = fptr->klass;
eo2_call_stack.frame_ptr++;
}
else
@@ -325,9 +325,9 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super)
obj = _eo_obj_pointer_get((Eo_Id)obj_id);
if (!obj) return EINA_FALSE;
if (do_super)
- cur_klass = _eo2_kls_itr_next(obj->klass, obj->klass);
+ klass = _eo2_kls_itr_next(obj->klass, obj->klass);
else
- cur_klass = obj->klass;
+ klass = obj->klass;
if (fptr == NULL)
eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0];
else
@@ -343,24 +343,65 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super)
fptr->obj = obj;
fptr->obj_id = obj_id;
- fptr->cur_klass = cur_klass;
+ fptr->klass = klass;
fptr->obj_data = EO2_INVALID_DATA;
return EINA_TRUE;
}
-EAPI void
-eo2_do_end(Eo **objid EINA_UNUSED)
+EAPI Eina_Bool
+eo2_class_do_start(const Eo_Class *klass_id, Eina_Bool do_super EINA_UNUSED)
+{
+ Eo2_Stack_Frame *fptr;
+ const _Eo_Class *klass;
+
+ fptr = eo2_call_stack.frame_ptr;
+ if ((fptr != NULL) && (fptr->klass->class_id == (Eo_Class_Id) klass_id))
+ {
+ if (do_super)
+ klass = _eo2_kls_itr_next(fptr->klass, fptr->klass);
+ else
+ klass = fptr->klass;
+ eo2_call_stack.frame_ptr++;
+ }
+ else
+ {
+ klass = _eo_class_pointer_get(klass_id);
+ EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
+ if (do_super)
+ klass = _eo2_kls_itr_next(klass, klass);
+ if (fptr == NULL)
+ eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0];
+ else
+ eo2_call_stack.frame_ptr++;
+ }
+
+ fptr = eo2_call_stack.frame_ptr;
+
+ if ((fptr - eo2_call_stack.stack) >= EO2_CALL_STACK_DEPTH)
+ ERR("eo2 call stack overflow !!!");
+
+ fptr->obj = NULL;
+ fptr->obj_id = NULL;
+ fptr->klass = klass;
+ fptr->obj_data = EO2_INVALID_DATA;
+
+ return EINA_TRUE;
+}
+
+static inline void
+_eo2_do_end(Eina_Bool obj_do)
{
Eo2_Stack_Frame *fptr;
fptr = eo2_call_stack.frame_ptr;
- _eo_unref(fptr->obj);
+ if(obj_do)
+ _eo_unref(fptr->obj);
fptr->obj = NULL;
fptr->obj_id = NULL;
- fptr->cur_klass = NULL;
+ fptr->klass = NULL;
fptr->obj_data = EO2_INVALID_DATA;
if (fptr == &eo2_call_stack.stack[0])
@@ -369,6 +410,18 @@ eo2_do_end(Eo **objid EINA_UNUSED)
eo2_call_stack.frame_ptr--;
}
+EAPI void
+eo2_do_end(Eo **obj_id EINA_UNUSED)
+{
+ _eo2_do_end(EINA_TRUE);
+}
+
+EAPI void
+eo2_class_do_end(const Eo_Class **klass_id EINA_UNUSED)
+{
+ _eo2_do_end(EINA_FALSE);
+}
+
EAPI Eina_Bool
eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call)
{
@@ -381,12 +434,17 @@ eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *
obj = fptr->obj;
if (klass_id)
- klass = _eo_class_pointer_get(klass_id);
+ {
+ klass = _eo_class_pointer_get(klass_id);
+ EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
+ }
else
- klass = fptr->cur_klass;
+ {
+ klass = fptr->klass;
+ if (!klass)
+ return EINA_FALSE;
+ }
- if (!klass)
- return EINA_FALSE;
func = _dich_func_get(klass, op);
if (EINA_LIKELY(func != NULL))
@@ -396,18 +454,24 @@ eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *
ERR("you called a pure virtual func");
return EINA_FALSE;
}
+ call->klass_id = (Eo_Class *) klass->class_id;
call->obj_id = fptr->obj_id;
call->func = func->func;
- if (func->src == obj->klass)
+ if (obj)
{
- if (fptr->obj_data == EO2_INVALID_DATA)
- fptr->obj_data = _eo_data_scope_get(obj, func->src);
+ if (func->src == obj->klass)
+ {
+ if (fptr->obj_data == EO2_INVALID_DATA)
+ fptr->obj_data = _eo_data_scope_get(obj, func->src);
- call->data = fptr->obj_data;
+ call->data = fptr->obj_data;
+ }
+ else
+ call->data = _eo_data_scope_get(obj, func->src);
}
else
- call->data = _eo_data_scope_get(obj, func->src);
+ call->data = NULL;
return EINA_TRUE;
}
@@ -493,6 +557,7 @@ _eo2_class_funcs_set(_Eo_Class *klass)
qsort((void*)op_descs, klass->desc->ops.count, sizeof(Eo2_Op_Description), eo2_api_funcs_cmp);
op_id = klass->base_id;
+ /* printf("elaborate class '%s' \n", klass->desc->name); */
for (op_desc = op_descs; op_desc->op_type != EO_OP_TYPE_INVALID; op_desc++)
{
if(op_desc->api_func == NULL)
@@ -530,7 +595,7 @@ _eo2_class_funcs_set(_Eo_Class *klass)
klass->desc->name, (unsigned long) (op_desc - op_descs));
}
- /* printf("%d %p %p %s\n", op_desc->op, op_desc->api_func, op_desc->func, op_desc->doc); */
+ /* printf(" %d %p %p %s\n", op_desc->op, op_desc->api_func, op_desc->func, op_desc->doc); */
_dich_func_set(klass, op_desc->op, op_desc->func);
}
}