efl/src/lib/eolian/eolian_aux.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;
}