forked from enlightenment/efl
302 lines
8.1 KiB
C
302 lines
8.1 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "Eolian_Aux.h"
|
|
|
|
static void
|
|
_hashlist_free(void *ptr)
|
|
{
|
|
eina_list_free((Eina_List *)ptr);
|
|
}
|
|
|
|
EAPI Eina_Hash *
|
|
eolian_aux_state_class_children_find(const Eolian_State *state)
|
|
{
|
|
if (!state)
|
|
return NULL;
|
|
|
|
Eina_Hash *h = eina_hash_pointer_new(_hashlist_free);
|
|
Eina_Iterator *itr = eolian_state_classes_get(state);
|
|
if (!itr)
|
|
return h;
|
|
|
|
const Eolian_Class *cl;
|
|
EINA_ITERATOR_FOREACH(itr, cl)
|
|
{
|
|
const Eolian_Class *icl = eolian_class_parent_get(cl);
|
|
if (icl)
|
|
eina_hash_set(h, &icl, eina_list_append(eina_hash_find(h, &icl), cl));
|
|
Eina_Iterator *iitr = eolian_class_extensions_get(cl);
|
|
EINA_ITERATOR_FOREACH(iitr, icl)
|
|
{
|
|
eina_hash_set(h, &icl,
|
|
eina_list_append(eina_hash_find(h, &icl), cl));
|
|
}
|
|
eina_iterator_free(iitr);
|
|
}
|
|
eina_iterator_free(itr);
|
|
|
|
return h;
|
|
}
|
|
|
|
static size_t
|
|
_callables_find_body(const Eolian_Class *pcl,
|
|
Eina_List **funcs, Eina_List **events,
|
|
Eina_Hash *written)
|
|
{
|
|
Eina_Iterator *iitr;
|
|
const Eolian_Implement *imp;
|
|
const Eolian_Event *ev;
|
|
size_t total = 0;
|
|
|
|
if (!funcs)
|
|
goto justevs;
|
|
|
|
iitr = eolian_class_implements_get(pcl);
|
|
EINA_ITERATOR_FOREACH(iitr, imp)
|
|
{
|
|
const Eolian_Function *ifn =
|
|
eolian_implement_function_get(imp, NULL);
|
|
if (eina_hash_find(written, &ifn))
|
|
continue;
|
|
*funcs = eina_list_append(*funcs, imp);
|
|
++total;
|
|
}
|
|
eina_iterator_free(iitr);
|
|
|
|
if (!events)
|
|
return total;
|
|
justevs:
|
|
iitr = eolian_class_events_get(pcl);
|
|
EINA_ITERATOR_FOREACH(iitr, ev)
|
|
{
|
|
/* events do not override */
|
|
*events = eina_list_append(*events, ev);
|
|
++total;
|
|
}
|
|
eina_iterator_free(iitr);
|
|
return total;
|
|
}
|
|
|
|
static size_t
|
|
_callables_find(const Eolian_Class *cl, Eina_List **funcs,
|
|
Eina_List **events, Eina_Hash *written)
|
|
{
|
|
size_t total = 0;
|
|
if (!funcs && !events)
|
|
return total;
|
|
|
|
const Eolian_Class *pcl = eolian_class_parent_get(cl);
|
|
if (pcl)
|
|
{
|
|
total += _callables_find_body(pcl, funcs, events, written);
|
|
total += _callables_find(pcl, funcs, events, written);
|
|
}
|
|
|
|
Eina_Iterator *itr = eolian_class_extensions_get(cl);
|
|
EINA_ITERATOR_FOREACH(itr, pcl)
|
|
{
|
|
total += _callables_find_body(pcl, funcs, events, written);
|
|
total += _callables_find(pcl, funcs, events, written);
|
|
}
|
|
eina_iterator_free(itr);
|
|
|
|
return total;
|
|
}
|
|
|
|
EAPI size_t
|
|
eolian_aux_class_callables_get(const Eolian_Class *klass,
|
|
Eina_List **funcs, Eina_List **events,
|
|
size_t *ownfuncs, size_t *ownevs)
|
|
{
|
|
size_t of = 0, oe = 0, total = 0;
|
|
if (!klass || (!funcs && !events))
|
|
{
|
|
if (ownfuncs) *ownfuncs = of;
|
|
if (ownevs) *ownevs = oe;
|
|
return total;
|
|
}
|
|
|
|
Eina_Hash *written = eina_hash_pointer_new(NULL);
|
|
if (funcs)
|
|
{
|
|
const Eolian_Implement *imp;
|
|
Eina_Iterator *itr = eolian_class_implements_get(klass);
|
|
EINA_ITERATOR_FOREACH(itr, imp)
|
|
{
|
|
const Eolian_Function *ifn =
|
|
eolian_implement_function_get(imp, NULL);
|
|
eina_hash_set(written, &ifn, ifn);
|
|
*funcs = eina_list_append(*funcs, imp);
|
|
++of;
|
|
}
|
|
eina_iterator_free(itr);
|
|
}
|
|
if (events)
|
|
{
|
|
const Eolian_Event *ev;
|
|
Eina_Iterator *itr = eolian_class_events_get(klass);
|
|
EINA_ITERATOR_FOREACH(itr, ev)
|
|
{
|
|
/* no need to mark in written, events do not override */
|
|
*events = eina_list_append(*events, ev);
|
|
++oe;
|
|
}
|
|
}
|
|
if (ownfuncs) *ownfuncs = of;
|
|
if (ownevs) *ownevs = oe;
|
|
total = of + oe;
|
|
total += _callables_find(klass, funcs, events, written);
|
|
eina_hash_free(written);
|
|
return total;
|
|
}
|
|
|
|
static void
|
|
_all_impls_find(Eina_List **l, const Eolian_Class *cl,
|
|
const Eolian_Function *func, Eina_Hash *got,
|
|
Eina_Hash *children)
|
|
{
|
|
if (eina_hash_find(got, &cl))
|
|
return;
|
|
eina_hash_add(got, &cl, cl);
|
|
Eina_Iterator *itr = eolian_class_implements_get(cl);
|
|
const Eolian_Implement *imp;
|
|
EINA_ITERATOR_FOREACH(itr, imp)
|
|
{
|
|
const Eolian_Function *ofn = eolian_implement_function_get(imp, NULL);
|
|
if (ofn == func)
|
|
{
|
|
*l = eina_list_append(*l, imp);
|
|
break;
|
|
}
|
|
}
|
|
eina_iterator_free(itr);
|
|
Eina_List *tl;
|
|
const Eolian_Class *icl;
|
|
EINA_LIST_FOREACH(eina_hash_find(children, &cl), tl, icl)
|
|
_all_impls_find(l, icl, func, got, children);
|
|
}
|
|
|
|
EAPI Eina_List *
|
|
eolian_aux_function_all_implements_get(const Eolian_Function *func,
|
|
Eina_Hash *class_children)
|
|
{
|
|
if (!class_children)
|
|
return NULL;
|
|
|
|
const Eolian_Class *cl = eolian_implement_class_get(
|
|
eolian_function_implement_get(func));
|
|
|
|
Eina_List *ret = NULL;
|
|
Eina_Hash *got = eina_hash_pointer_new(NULL);
|
|
_all_impls_find(&ret, cl, func, got, class_children);
|
|
|
|
eina_hash_free(got);
|
|
return ret;
|
|
}
|
|
|
|
static const Eolian_Implement * _parent_impl_find(
|
|
const char *fulln, const Eolian_Class *cl);
|
|
|
|
static const Eolian_Implement *
|
|
_parent_impl_find_body(const Eolian_Class *icl, const char *fulln)
|
|
{
|
|
Eina_Iterator *iitr = eolian_class_implements_get(icl);
|
|
const Eolian_Implement *iimpl;
|
|
EINA_ITERATOR_FOREACH(iitr, iimpl)
|
|
{
|
|
if (eolian_implement_name_get(iimpl) == fulln)
|
|
{
|
|
eina_iterator_free(iitr);
|
|
return iimpl;
|
|
}
|
|
}
|
|
eina_iterator_free(iitr);
|
|
return _parent_impl_find(fulln, icl);
|
|
}
|
|
|
|
static const Eolian_Implement *
|
|
_parent_impl_find(const char *fulln, const Eolian_Class *cl)
|
|
{
|
|
const Eolian_Implement *iret = NULL;
|
|
const Eolian_Class *icl = eolian_class_parent_get(cl);
|
|
if (icl)
|
|
iret = _parent_impl_find_body(icl, fulln);
|
|
if (iret)
|
|
return iret;
|
|
Eina_Iterator *itr = eolian_class_extensions_get(cl);
|
|
EINA_ITERATOR_FOREACH(itr, icl)
|
|
{
|
|
iret = _parent_impl_find_body(icl, fulln);
|
|
if (iret)
|
|
{
|
|
eina_iterator_free(itr);
|
|
return iret;
|
|
}
|
|
}
|
|
eina_iterator_free(itr);
|
|
return NULL;
|
|
}
|
|
|
|
EAPI const Eolian_Implement *
|
|
eolian_aux_implement_parent_get(const Eolian_Implement *impl)
|
|
{
|
|
return _parent_impl_find(eolian_implement_name_get(impl),
|
|
eolian_implement_implementing_class_get(impl));
|
|
}
|
|
|
|
static const Eolian_Documentation *
|
|
_parent_documentation_find(const Eolian_Implement *impl,
|
|
Eolian_Function_Type ftype)
|
|
{
|
|
const Eolian_Implement *pimpl = eolian_aux_implement_parent_get(impl);
|
|
if (!pimpl)
|
|
return NULL;
|
|
|
|
const Eolian_Documentation *pdoc =
|
|
eolian_implement_documentation_get(pimpl, ftype);
|
|
if (!pdoc)
|
|
return _parent_documentation_find(pimpl, ftype);
|
|
|
|
return pdoc;
|
|
}
|
|
|
|
EAPI const Eolian_Documentation *
|
|
eolian_aux_implement_documentation_get(const Eolian_Implement *impl,
|
|
Eolian_Function_Type ftype)
|
|
{
|
|
const Eolian_Documentation *ret =
|
|
eolian_implement_documentation_get(impl, ftype);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
const Eolian_Class *icl = eolian_implement_implementing_class_get(impl);
|
|
if (eolian_implement_class_get(impl) == icl)
|
|
return NULL;
|
|
|
|
const Eolian_Implement *oimp = eolian_function_implement_get(
|
|
eolian_implement_function_get(impl, NULL));
|
|
if ((ftype == EOLIAN_PROP_GET) && !eolian_implement_is_prop_get(oimp))
|
|
return NULL;
|
|
if ((ftype == EOLIAN_PROP_SET) && !eolian_implement_is_prop_set(oimp))
|
|
return NULL;
|
|
|
|
return _parent_documentation_find(impl, ftype);
|
|
}
|
|
|
|
EAPI const Eolian_Documentation *
|
|
eolian_aux_implement_documentation_fallback_get(const Eolian_Implement *impl)
|
|
{
|
|
Eina_Bool ig = eolian_implement_is_prop_get(impl),
|
|
is = eolian_implement_is_prop_set(impl);
|
|
|
|
if (ig && !is)
|
|
return eolian_implement_documentation_get(impl, EOLIAN_PROP_GET);
|
|
else if (is && !ig)
|
|
return eolian_implement_documentation_get(impl, EOLIAN_PROP_SET);
|
|
|
|
return NULL;
|
|
}
|