#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; }