summaryrefslogtreecommitdiff
path: root/src/lib/eolian/eolian_aux.c
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2018-11-04 18:56:54 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2018-11-29 13:56:52 +0100
commitbe7d76ece63844f1967ee12d042c920a8540ab4a (patch)
tree847f01a585bf940592d3556926cd25b66286e627 /src/lib/eolian/eolian_aux.c
parente93dbf21a26ea05118db1896025f7ad19e603813 (diff)
eolian_aux: add initial eolian_aux APIs
eolian_aux is a set of auxiliary APIs for eolian that build on top of the existing eolian APIs but do not belong in the main library.
Diffstat (limited to 'src/lib/eolian/eolian_aux.c')
-rw-r--r--src/lib/eolian/eolian_aux.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/lib/eolian/eolian_aux.c b/src/lib/eolian/eolian_aux.c
new file mode 100644
index 0000000..a66c02c
--- /dev/null
+++ b/src/lib/eolian/eolian_aux.c
@@ -0,0 +1,294 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "Eolian_Aux.h"
6
7static void
8_hashlist_free(void *ptr)
9{
10 eina_list_free((Eina_List *)ptr);
11}
12
13EAPI Eina_Hash *
14eolian_aux_state_class_children_find(const Eolian_State *state)
15{
16 if (!state)
17 return NULL;
18
19 Eina_Hash *h = eina_hash_pointer_new(_hashlist_free);
20 Eina_Iterator *itr = eolian_state_classes_get(state);
21 if (!itr)
22 return h;
23
24 const Eolian_Class *cl;
25 EINA_ITERATOR_FOREACH(itr, cl)
26 {
27 const Eolian_Class *icl = eolian_class_parent_get(cl);
28 if (icl)
29 eina_hash_set(h, &icl, eina_list_append(eina_hash_find(h, &icl), cl));
30 Eina_Iterator *iitr = eolian_class_extensions_get(cl);
31 EINA_ITERATOR_FOREACH(iitr, icl)
32 {
33 eina_hash_set(h, &icl,
34 eina_list_append(eina_hash_find(h, &icl), cl));
35 }
36 eina_iterator_free(iitr);
37 }
38 eina_iterator_free(itr);
39
40 return h;
41}
42
43static size_t
44_callables_find_body(const Eolian_Class *pcl,
45 Eina_List **funcs, Eina_List **events,
46 Eina_Hash *written)
47{
48 Eina_Iterator *iitr;
49 const Eolian_Implement *imp;
50 const Eolian_Event *ev;
51 size_t total = 0;
52
53 if (!funcs)
54 goto justevs;
55
56 iitr = eolian_class_implements_get(pcl);
57 EINA_ITERATOR_FOREACH(iitr, imp)
58 {
59 const Eolian_Function *ifn =
60 eolian_implement_function_get(imp, NULL);
61 if (eina_hash_find(written, &ifn))
62 continue;
63 *funcs = eina_list_append(*funcs, imp);
64 ++total;
65 }
66 eina_iterator_free(iitr);
67
68 if (!events)
69 return total;
70justevs:
71 iitr = eolian_class_events_get(pcl);
72 EINA_ITERATOR_FOREACH(iitr, ev)
73 {
74 /* events do not override */
75 *events = eina_list_append(*events, ev);
76 ++total;
77 }
78 eina_iterator_free(iitr);
79 return total;
80}
81
82static size_t
83_callables_find(const Eolian_Class *cl, Eina_List **funcs,
84 Eina_List **events, Eina_Hash *written)
85{
86 size_t total = 0;
87 if (!funcs && !events)
88 return total;
89
90 const Eolian_Class *pcl = eolian_class_parent_get(cl);
91 if (pcl)
92 total += _callables_find_body(pcl, funcs, events, written);
93
94 Eina_Iterator *itr = eolian_class_extensions_get(cl);
95 EINA_ITERATOR_FOREACH(itr, pcl)
96 total += _callables_find_body(pcl, funcs, events, written);
97
98 return total;
99}
100
101EAPI size_t
102eolian_aux_class_callables_get(const Eolian_Class *klass,
103 Eina_List **funcs, Eina_List **events,
104 size_t *ownfuncs, size_t *ownevs)
105{
106 size_t of = 0, oe = 0, total = 0;
107 if (!klass || (!funcs && !events))
108 {
109 if (ownfuncs) *ownfuncs = of;
110 if (ownevs) *ownevs = oe;
111 return total;
112 }
113
114 Eina_Hash *written = eina_hash_pointer_new(NULL);
115 if (funcs)
116 {
117 const Eolian_Implement *imp;
118 Eina_Iterator *itr = eolian_class_implements_get(klass);
119 EINA_ITERATOR_FOREACH(itr, imp)
120 {
121 const Eolian_Function *ifn =
122 eolian_implement_function_get(imp, NULL);
123 eina_hash_set(written, &ifn, ifn);
124 *funcs = eina_list_append(*funcs, imp);
125 ++of;
126 }
127 eina_iterator_free(itr);
128 }
129 if (events)
130 {
131 const Eolian_Event *ev;
132 Eina_Iterator *itr = eolian_class_events_get(klass);
133 EINA_ITERATOR_FOREACH(itr, ev)
134 {
135 /* no need to mark in written, events do not override */
136 *events = eina_list_append(*events, ev);
137 ++oe;
138 }
139 }
140 if (ownfuncs) *ownfuncs = of;
141 if (ownevs) *ownevs = oe;
142 total = of + oe;
143 total += _callables_find(klass, funcs, events, written);
144 eina_hash_free(written);
145 return total;
146}
147
148static void
149_all_impls_find(Eina_List **l, const Eolian_Class *cl,
150 const Eolian_Function *func, Eina_Hash *got,
151 Eina_Hash *children)
152{
153 if (eina_hash_find(got, &cl))
154 return;
155 eina_hash_add(got, &cl, cl);
156 Eina_Iterator *itr = eolian_class_implements_get(cl);
157 const Eolian_Implement *imp;
158 EINA_ITERATOR_FOREACH(itr, imp)
159 {
160 const Eolian_Function *ofn = eolian_implement_function_get(imp, NULL);
161 if (ofn == func)
162 {
163 *l = eina_list_append(*l, imp);
164 break;
165 }
166 }
167 eina_iterator_free(itr);
168 Eina_List *tl;
169 const Eolian_Class *icl;
170 EINA_LIST_FOREACH(eina_hash_find(children, &cl), tl, icl)
171 _all_impls_find(l, icl, func, got, children);
172}
173
174EAPI Eina_List *
175eolian_aux_function_all_implements_get(const Eolian_Function *func,
176 Eina_Hash *class_children)
177{
178 if (!class_children)
179 return NULL;
180
181 const Eolian_Class *cl = eolian_implement_class_get(
182 eolian_function_implement_get(func));
183
184 Eina_List *ret = NULL;
185 Eina_Hash *got = eina_hash_pointer_new(NULL);
186 _all_impls_find(&ret, cl, func, got, class_children);
187
188 eina_hash_free(got);
189 return ret;
190}
191
192static const Eolian_Implement * _parent_impl_find(
193 const char *fulln, const Eolian_Class *cl);
194
195static const Eolian_Implement *
196_parent_impl_find_body(const Eolian_Class *icl, const char *fulln)
197{
198 Eina_Iterator *iitr = eolian_class_implements_get(icl);
199 const Eolian_Implement *iimpl;
200 EINA_ITERATOR_FOREACH(iitr, iimpl)
201 {
202 if (eolian_implement_name_get(iimpl) == fulln)
203 {
204 eina_iterator_free(iitr);
205 return iimpl;
206 }
207 }
208 eina_iterator_free(iitr);
209 return _parent_impl_find(fulln, icl);
210 }
211
212static const Eolian_Implement *
213_parent_impl_find(const char *fulln, const Eolian_Class *cl)
214{
215 const Eolian_Implement *iret = NULL;
216 const Eolian_Class *icl = eolian_class_parent_get(cl);
217 if (icl)
218 iret = _parent_impl_find_body(icl, fulln);
219 if (iret)
220 return iret;
221 Eina_Iterator *itr = eolian_class_extensions_get(cl);
222 EINA_ITERATOR_FOREACH(itr, icl)
223 {
224 iret = _parent_impl_find_body(icl, fulln);
225 if (iret)
226 {
227 eina_iterator_free(itr);
228 return iret;
229 }
230 }
231 eina_iterator_free(itr);
232 return NULL;
233}
234
235EAPI const Eolian_Implement *
236eolian_aux_implement_parent_get(const Eolian_Implement *impl)
237{
238 return _parent_impl_find(eolian_implement_name_get(impl),
239 eolian_implement_implementing_class_get(impl));
240}
241
242static const Eolian_Documentation *
243_parent_documentation_find(const Eolian_Implement *impl,
244 Eolian_Function_Type ftype)
245{
246 const Eolian_Implement *pimpl = eolian_aux_implement_parent_get(impl);
247 if (!pimpl)
248 return NULL;
249
250 const Eolian_Documentation *pdoc =
251 eolian_implement_documentation_get(pimpl, ftype);
252 if (!pdoc)
253 return _parent_documentation_find(pimpl, ftype);
254
255 return pdoc;
256}
257
258EAPI const Eolian_Documentation *
259eolian_aux_implement_documentation_get(const Eolian_Implement *impl,
260 Eolian_Function_Type ftype)
261{
262 const Eolian_Documentation *ret =
263 eolian_implement_documentation_get(impl, ftype);
264
265 if (ret)
266 return ret;
267
268 const Eolian_Class *icl = eolian_implement_implementing_class_get(impl);
269 if (eolian_implement_class_get(impl) == icl)
270 return NULL;
271
272 const Eolian_Implement *oimp = eolian_function_implement_get(
273 eolian_implement_function_get(impl, NULL));
274 if ((ftype == EOLIAN_PROP_GET) && !eolian_implement_is_prop_get(oimp))
275 return NULL;
276 if ((ftype == EOLIAN_PROP_SET) && !eolian_implement_is_prop_set(oimp))
277 return NULL;
278
279 return _parent_documentation_find(impl, ftype);
280}
281
282EAPI const Eolian_Documentation *
283eolian_aux_implement_documentation_fallback_get(const Eolian_Implement *impl)
284{
285 Eina_Bool ig = eolian_implement_is_prop_get(impl),
286 is = eolian_implement_is_prop_set(impl);
287
288 if (ig && !is)
289 return eolian_implement_documentation_get(impl, EOLIAN_PROP_GET);
290 else if (is && !ig)
291 return eolian_implement_documentation_get(impl, EOLIAN_PROP_SET);
292
293 return NULL;
294}