diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/edje/src/lib/edje_match.c | 814 |
1 files changed, 814 insertions, 0 deletions
diff --git a/libraries/edje/src/lib/edje_match.c b/libraries/edje/src/lib/edje_match.c new file mode 100644 index 0000000..f113f7b --- /dev/null +++ b/libraries/edje/src/lib/edje_match.c | |||
@@ -0,0 +1,814 @@ | |||
1 | #include "edje_private.h" | ||
2 | |||
3 | /* States manipulations. */ | ||
4 | |||
5 | typedef struct _Edje_State Edje_State; | ||
6 | struct _Edje_State | ||
7 | { | ||
8 | size_t idx; | ||
9 | size_t pos; | ||
10 | }; | ||
11 | |||
12 | struct _Edje_States | ||
13 | { | ||
14 | size_t size; | ||
15 | Edje_State *states; | ||
16 | Eina_Bool *has; | ||
17 | }; | ||
18 | |||
19 | static void | ||
20 | _edje_match_states_free(Edje_States *states, | ||
21 | size_t states_size) | ||
22 | { | ||
23 | (void) states_size; | ||
24 | free(states); | ||
25 | } | ||
26 | |||
27 | #define ALIGN(Size) \ | ||
28 | { \ | ||
29 | Size--; \ | ||
30 | Size |= sizeof (void*) - 1; \ | ||
31 | Size++; \ | ||
32 | }; | ||
33 | |||
34 | static int | ||
35 | _edje_match_states_alloc(Edje_Patterns *ppat, int n) | ||
36 | { | ||
37 | Edje_States *l; | ||
38 | |||
39 | const size_t patterns_size = ppat->patterns_size; | ||
40 | const size_t patterns_max_length = ppat->max_length; | ||
41 | |||
42 | const size_t array_len = (patterns_max_length + 1) * patterns_size; | ||
43 | |||
44 | size_t states_size; | ||
45 | size_t has_size; | ||
46 | size_t states_has_size; | ||
47 | size_t struct_size; | ||
48 | |||
49 | unsigned char *states; | ||
50 | unsigned char *has; | ||
51 | |||
52 | int i; | ||
53 | |||
54 | states_size = sizeof (*l->states) * array_len; | ||
55 | ALIGN(states_size); | ||
56 | |||
57 | has_size = sizeof (*l->has) * array_len; | ||
58 | ALIGN(has_size); | ||
59 | |||
60 | states_has_size = states_size + has_size; | ||
61 | |||
62 | struct_size = sizeof (*l); | ||
63 | ALIGN(struct_size); | ||
64 | struct_size += states_has_size; | ||
65 | |||
66 | l = malloc(n * struct_size); | ||
67 | if (!l) return 0; | ||
68 | |||
69 | ppat->states = l; | ||
70 | ppat->states->size = 0; | ||
71 | |||
72 | states = (unsigned char *) (l + n); | ||
73 | has = states + states_size; | ||
74 | |||
75 | for (i = 0; i < n; ++i) | ||
76 | { | ||
77 | l[i].states = (Edje_State *) states; | ||
78 | l[i].has = (Eina_Bool *) has; | ||
79 | l[i].size = 0; | ||
80 | |||
81 | memset(l[i].has, 0, has_size); | ||
82 | |||
83 | states += states_has_size; | ||
84 | has += states_has_size; | ||
85 | } | ||
86 | |||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | static void | ||
91 | _edje_match_states_insert(Edje_States *list, | ||
92 | size_t patterns_max_length, | ||
93 | size_t idx, | ||
94 | size_t pos) | ||
95 | { | ||
96 | size_t i; | ||
97 | |||
98 | i = (idx * (patterns_max_length + 1)) + pos; | ||
99 | |||
100 | if (i < list->size) | ||
101 | { | ||
102 | if (list->has[i]) return; | ||
103 | } | ||
104 | list->has[i] = 1; | ||
105 | |||
106 | i = list->size; | ||
107 | list->states[i].idx = idx; | ||
108 | list->states[i].pos = pos; | ||
109 | list->has[i] = 0; | ||
110 | list->size++; | ||
111 | } | ||
112 | |||
113 | static void | ||
114 | _edje_match_states_clear(Edje_States *list, | ||
115 | __UNUSED__ size_t patterns_size, | ||
116 | __UNUSED__ size_t patterns_max_length) | ||
117 | { | ||
118 | list->size = 0; | ||
119 | } | ||
120 | |||
121 | /* Token manipulation. */ | ||
122 | |||
123 | enum status | ||
124 | { | ||
125 | patterns_not_found = 0, | ||
126 | patterns_found = 1, | ||
127 | patterns_syntax_error = 2 | ||
128 | }; | ||
129 | |||
130 | static size_t | ||
131 | _edje_match_patterns_exec_class_token(enum status *status, | ||
132 | const char *cl_tok, | ||
133 | char c) | ||
134 | { | ||
135 | if (! *cl_tok) | ||
136 | { | ||
137 | *status = patterns_syntax_error; | ||
138 | return 0; | ||
139 | } | ||
140 | else if (cl_tok[1] == '-' && cl_tok[2] != ']') | ||
141 | { | ||
142 | if (*cl_tok <= c && c <= cl_tok[2]) | ||
143 | *status = patterns_found; | ||
144 | return 3; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | if (c == *cl_tok) | ||
149 | *status = patterns_found; | ||
150 | return 1; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static Edje_Match_Error | ||
155 | _edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret) | ||
156 | { | ||
157 | switch (*cl_tok) | ||
158 | { | ||
159 | case 0: | ||
160 | return EDJE_MATCH_SYNTAX_ERROR; | ||
161 | |||
162 | case '!': | ||
163 | *ret = 1; | ||
164 | return EDJE_MATCH_OK; | ||
165 | |||
166 | default: | ||
167 | *ret = 0; | ||
168 | return EDJE_MATCH_OK; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static Edje_Match_Error | ||
173 | _edje_match_patterns_exec_class(const char *cl, | ||
174 | char c, | ||
175 | size_t *ret) | ||
176 | { | ||
177 | enum status status = patterns_not_found; | ||
178 | int pos = 1; | ||
179 | size_t neg; | ||
180 | |||
181 | if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK) | ||
182 | return EDJE_MATCH_SYNTAX_ERROR; | ||
183 | |||
184 | pos += neg; | ||
185 | |||
186 | do | ||
187 | { | ||
188 | pos += _edje_match_patterns_exec_class_token(&status, cl + pos, c); | ||
189 | } | ||
190 | while (cl[pos] && cl[pos] != ']'); | ||
191 | |||
192 | if (status == patterns_syntax_error || ! cl[pos]) | ||
193 | return EDJE_MATCH_SYNTAX_ERROR; | ||
194 | |||
195 | if (status == patterns_found) | ||
196 | *ret = neg ? 0 : pos + 1; | ||
197 | else | ||
198 | *ret = neg ? pos + 1 : 0; | ||
199 | |||
200 | return EDJE_MATCH_OK; | ||
201 | } | ||
202 | |||
203 | static Edje_Match_Error | ||
204 | _edje_match_patterns_exec_token(const char *tok, | ||
205 | char c, | ||
206 | size_t *ret) | ||
207 | { | ||
208 | switch (*tok) | ||
209 | { | ||
210 | case '\\': | ||
211 | if (tok[1]) | ||
212 | { | ||
213 | *ret = tok[1] == c ? 2 : 0; | ||
214 | return EDJE_MATCH_OK; | ||
215 | } | ||
216 | return EDJE_MATCH_SYNTAX_ERROR; | ||
217 | |||
218 | case '?': | ||
219 | *ret = 1; | ||
220 | return EDJE_MATCH_OK; | ||
221 | |||
222 | case '[': | ||
223 | return _edje_match_patterns_exec_class(tok, c, ret); | ||
224 | |||
225 | default: | ||
226 | *ret = *tok == c ? 1 : 0; | ||
227 | return EDJE_MATCH_OK; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | _edje_match_patterns_exec_init_states(Edje_States *states, | ||
233 | size_t patterns_size, | ||
234 | size_t patterns_max_length) | ||
235 | { | ||
236 | size_t i; | ||
237 | |||
238 | states->size = patterns_size; | ||
239 | |||
240 | for (i = 0; i < patterns_size; ++i) | ||
241 | { | ||
242 | states->states[i].idx = i; | ||
243 | states->states[i].pos = 0; | ||
244 | states->has[i * (patterns_max_length + 1)] = 1; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /* Exported function. */ | ||
249 | |||
250 | #define EDJE_MATCH_INIT_LIST(Func, Type, Source, Show) \ | ||
251 | Edje_Patterns* \ | ||
252 | Func(const Eina_List *lst) \ | ||
253 | { \ | ||
254 | Edje_Patterns *r; \ | ||
255 | size_t i; \ | ||
256 | \ | ||
257 | if (!lst || eina_list_count(lst) <= 0) \ | ||
258 | return NULL; \ | ||
259 | \ | ||
260 | r = malloc(sizeof (Edje_Patterns) + \ | ||
261 | eina_list_count(lst) \ | ||
262 | * sizeof(*r->finals) \ | ||
263 | * sizeof(*r->patterns)); \ | ||
264 | if (!r) return NULL; \ | ||
265 | \ | ||
266 | r->ref = 1; \ | ||
267 | r->delete_me = 0; \ | ||
268 | r->patterns_size = eina_list_count(lst); \ | ||
269 | r->max_length = 0; \ | ||
270 | r->patterns = (const char **) r->finals + r->patterns_size + 1; \ | ||
271 | \ | ||
272 | for (i = 0; lst; ++i) \ | ||
273 | { \ | ||
274 | const char *str; \ | ||
275 | Type *data; \ | ||
276 | size_t j; \ | ||
277 | int special = 0; \ | ||
278 | \ | ||
279 | data = eina_list_data_get(lst); \ | ||
280 | if (!data) \ | ||
281 | { \ | ||
282 | free(r); \ | ||
283 | return NULL; \ | ||
284 | } \ | ||
285 | \ | ||
286 | str = data->Source; \ | ||
287 | if (!str) str = ""; \ | ||
288 | r->patterns[i] = str; \ | ||
289 | \ | ||
290 | if (Show) \ | ||
291 | INF("%lu [%s]", (unsigned long)i, str); \ | ||
292 | \ | ||
293 | r->finals[i] = 0; \ | ||
294 | for (j = 0; str[j]; ++j) \ | ||
295 | if (str[j] != '*') \ | ||
296 | { \ | ||
297 | r->finals[i] = j + 1; \ | ||
298 | special++; \ | ||
299 | } \ | ||
300 | j += special ? special + 1 : 0; \ | ||
301 | \ | ||
302 | if (j > r->max_length) \ | ||
303 | r->max_length = j; \ | ||
304 | \ | ||
305 | lst = eina_list_next(lst); \ | ||
306 | } \ | ||
307 | \ | ||
308 | if (!_edje_match_states_alloc(r, 2)) \ | ||
309 | { \ | ||
310 | free(r); \ | ||
311 | return NULL; \ | ||
312 | } \ | ||
313 | \ | ||
314 | return r; \ | ||
315 | } | ||
316 | |||
317 | #define EDJE_MATCH_INIT_ARRAY(Func, Type, Source, Show) \ | ||
318 | Edje_Patterns* \ | ||
319 | Func(Type * const *lst, unsigned int count) \ | ||
320 | { \ | ||
321 | Edje_Patterns *r; \ | ||
322 | size_t i; \ | ||
323 | \ | ||
324 | if (!lst || count == 0) \ | ||
325 | return NULL; \ | ||
326 | \ | ||
327 | r = malloc(sizeof (Edje_Patterns) + \ | ||
328 | count \ | ||
329 | * sizeof(*r->finals) \ | ||
330 | * sizeof(*r->patterns)); \ | ||
331 | if (!r) return NULL; \ | ||
332 | \ | ||
333 | r->ref = 1; \ | ||
334 | r->delete_me = 0; \ | ||
335 | r->patterns_size = count; \ | ||
336 | r->max_length = 0; \ | ||
337 | r->patterns = (const char **) r->finals + r->patterns_size + 1; \ | ||
338 | \ | ||
339 | for (i = 0; i < count; ++i) \ | ||
340 | { \ | ||
341 | const char *str; \ | ||
342 | size_t j; \ | ||
343 | int special = 0; \ | ||
344 | \ | ||
345 | if (!lst[i]) \ | ||
346 | { \ | ||
347 | free(r); \ | ||
348 | return NULL; \ | ||
349 | } \ | ||
350 | \ | ||
351 | str = lst[i]->Source; \ | ||
352 | if (!str) str = ""; \ | ||
353 | r->patterns[i] = str; \ | ||
354 | \ | ||
355 | if (Show) \ | ||
356 | INF("%lu [%s]", (unsigned long)i, str); \ | ||
357 | \ | ||
358 | r->finals[i] = 0; \ | ||
359 | for (j = 0; str[j]; ++j) \ | ||
360 | if (str[j] != '*') \ | ||
361 | { \ | ||
362 | r->finals[i] = j + 1; \ | ||
363 | special++; \ | ||
364 | } \ | ||
365 | j += special ? special + 1 : 0; \ | ||
366 | \ | ||
367 | if (j > r->max_length) \ | ||
368 | r->max_length = j; \ | ||
369 | } \ | ||
370 | \ | ||
371 | if (!_edje_match_states_alloc(r, 2)) \ | ||
372 | { \ | ||
373 | free(r); \ | ||
374 | return NULL; \ | ||
375 | } \ | ||
376 | \ | ||
377 | return r; \ | ||
378 | } | ||
379 | |||
380 | EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init, | ||
381 | Edje_Part_Collection_Directory_Entry, | ||
382 | entry, 0); | ||
383 | EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init, | ||
384 | Edje_Program, | ||
385 | signal, 0); | ||
386 | EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init, | ||
387 | Edje_Program, | ||
388 | source, 0); | ||
389 | EDJE_MATCH_INIT_LIST(edje_match_callback_signal_init, | ||
390 | Edje_Signal_Callback, | ||
391 | signal, 0); | ||
392 | EDJE_MATCH_INIT_LIST(edje_match_callback_source_init, | ||
393 | Edje_Signal_Callback, | ||
394 | source, 0); | ||
395 | |||
396 | static Eina_Bool | ||
397 | _edje_match_collection_dir_exec_finals(const size_t *finals, | ||
398 | const Edje_States *states) | ||
399 | { | ||
400 | size_t i; | ||
401 | |||
402 | for (i = 0; i < states->size; ++i) | ||
403 | { | ||
404 | if (states->states[i].pos >= finals[states->states[i].idx]) | ||
405 | return EINA_TRUE; | ||
406 | } | ||
407 | return EINA_FALSE; | ||
408 | } | ||
409 | |||
410 | static Eina_Bool | ||
411 | edje_match_programs_exec_check_finals(const size_t *signal_finals, | ||
412 | const size_t *source_finals, | ||
413 | const Edje_States *signal_states, | ||
414 | const Edje_States *source_states, | ||
415 | Edje_Program **programs, | ||
416 | Eina_Bool (*func)(Edje_Program *pr, void *data), | ||
417 | void *data, | ||
418 | Eina_Bool prop __UNUSED__) | ||
419 | { | ||
420 | size_t i; | ||
421 | size_t j; | ||
422 | |||
423 | /* when not enought memory, they could be NULL */ | ||
424 | if (!signal_finals || !source_finals) return EINA_TRUE; | ||
425 | |||
426 | for (i = 0; i < signal_states->size; ++i) | ||
427 | { | ||
428 | if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx]) | ||
429 | { | ||
430 | for (j = 0; j < source_states->size; ++j) | ||
431 | { | ||
432 | if (signal_states->states[i].idx == source_states->states[j].idx | ||
433 | && source_states->states[j].pos >= source_finals[source_states->states[j].idx]) | ||
434 | { | ||
435 | Edje_Program *pr; | ||
436 | |||
437 | pr = programs[signal_states->states[i].idx]; | ||
438 | if (pr) | ||
439 | { | ||
440 | if (func(pr, data)) | ||
441 | return EINA_FALSE; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | |||
448 | return EINA_TRUE; | ||
449 | } | ||
450 | |||
451 | static int | ||
452 | edje_match_callback_exec_check_finals(const Edje_Patterns *singal_ppat, | ||
453 | const Edje_Patterns *source_ppat, | ||
454 | const size_t *signal_finals, | ||
455 | const size_t *source_finals, | ||
456 | const Edje_States *signal_states, | ||
457 | const Edje_States *source_states, | ||
458 | const char *sig, | ||
459 | const char *source, | ||
460 | Eina_List *callbacks, | ||
461 | Edje *ed, | ||
462 | Eina_Bool prop | ||
463 | ) | ||
464 | { | ||
465 | size_t i; | ||
466 | size_t j; | ||
467 | int r = 1; | ||
468 | |||
469 | for (i = 0; i < signal_states->size; ++i) | ||
470 | { | ||
471 | if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx]) | ||
472 | { | ||
473 | for (j = 0; j < source_states->size; ++j) | ||
474 | { | ||
475 | if (signal_states->states[i].idx == source_states->states[j].idx | ||
476 | && source_states->states[j].pos >= source_finals[source_states->states[j].idx]) | ||
477 | { | ||
478 | Edje_Signal_Callback *escb; | ||
479 | |||
480 | escb = eina_list_nth(callbacks, signal_states->states[i].idx); | ||
481 | if (escb) | ||
482 | { | ||
483 | if ((prop) && (escb->propagate)) continue; | ||
484 | if ((!escb->just_added) | ||
485 | && (!escb->delete_me)) | ||
486 | { | ||
487 | escb->func(escb->data, ed->obj, sig, source); | ||
488 | r = 2; | ||
489 | } | ||
490 | if (_edje_block_break(ed)) | ||
491 | return 0; | ||
492 | if ((singal_ppat->delete_me) || (source_ppat->delete_me)) | ||
493 | return 0; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | } | ||
498 | } | ||
499 | |||
500 | return r; | ||
501 | } | ||
502 | |||
503 | |||
504 | static Edje_States* | ||
505 | _edje_match_fn(const Edje_Patterns *ppat, | ||
506 | const char *string, | ||
507 | Edje_States *states) | ||
508 | { | ||
509 | Edje_States *new_states = states + 1; | ||
510 | const char *c; | ||
511 | |||
512 | for (c = string; *c && states->size; ++c) | ||
513 | { | ||
514 | size_t i; | ||
515 | |||
516 | _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length); | ||
517 | |||
518 | for (i = 0; i < states->size; ++i) | ||
519 | { | ||
520 | const size_t idx = states->states[i].idx; | ||
521 | const size_t pos = states->states[i].pos; | ||
522 | |||
523 | if (!ppat->patterns[idx][pos]) | ||
524 | continue; | ||
525 | else if (ppat->patterns[idx][pos] == '*') | ||
526 | { | ||
527 | _edje_match_states_insert(states, ppat->max_length, idx, pos + 1); | ||
528 | _edje_match_states_insert(new_states, ppat->max_length, idx, pos); | ||
529 | } | ||
530 | else | ||
531 | { | ||
532 | size_t m; | ||
533 | |||
534 | if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos, | ||
535 | *c, | ||
536 | &m) != EDJE_MATCH_OK) | ||
537 | return NULL; | ||
538 | |||
539 | if (m) | ||
540 | _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m); | ||
541 | } | ||
542 | } | ||
543 | { | ||
544 | Edje_States *tmp = states; | ||
545 | |||
546 | states = new_states; | ||
547 | new_states = tmp; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | return states; | ||
552 | } | ||
553 | |||
554 | Eina_Bool | ||
555 | edje_match_collection_dir_exec(const Edje_Patterns *ppat, | ||
556 | const char *string) | ||
557 | { | ||
558 | Edje_States *result; | ||
559 | Eina_Bool r = EINA_FALSE; | ||
560 | |||
561 | /* under high memory presure, it could be NULL */ | ||
562 | if (!ppat) return EINA_FALSE; | ||
563 | |||
564 | _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length); | ||
565 | |||
566 | result = _edje_match_fn(ppat, string, ppat->states); | ||
567 | |||
568 | if (result) | ||
569 | r = _edje_match_collection_dir_exec_finals(ppat->finals, result); | ||
570 | |||
571 | return r; | ||
572 | } | ||
573 | |||
574 | Eina_Bool | ||
575 | edje_match_programs_exec(const Edje_Patterns *ppat_signal, | ||
576 | const Edje_Patterns *ppat_source, | ||
577 | const char *sig, | ||
578 | const char *source, | ||
579 | Edje_Program **programs, | ||
580 | Eina_Bool (*func)(Edje_Program *pr, void *data), | ||
581 | void *data, | ||
582 | Eina_Bool prop) | ||
583 | { | ||
584 | Edje_States *signal_result; | ||
585 | Edje_States *source_result; | ||
586 | Eina_Bool r = EINA_FALSE; | ||
587 | |||
588 | /* under high memory presure, they could be NULL */ | ||
589 | if (!ppat_source || !ppat_signal) return EINA_FALSE; | ||
590 | |||
591 | _edje_match_patterns_exec_init_states(ppat_signal->states, | ||
592 | ppat_signal->patterns_size, | ||
593 | ppat_signal->max_length); | ||
594 | _edje_match_patterns_exec_init_states(ppat_source->states, | ||
595 | ppat_source->patterns_size, | ||
596 | ppat_source->max_length); | ||
597 | |||
598 | signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states); | ||
599 | source_result = _edje_match_fn(ppat_source, source, ppat_source->states); | ||
600 | |||
601 | if (signal_result && source_result) | ||
602 | r = edje_match_programs_exec_check_finals(ppat_signal->finals, | ||
603 | ppat_source->finals, | ||
604 | signal_result, | ||
605 | source_result, | ||
606 | programs, | ||
607 | func, | ||
608 | data, | ||
609 | prop); | ||
610 | return r; | ||
611 | } | ||
612 | |||
613 | int | ||
614 | edje_match_callback_exec(Edje_Patterns *ppat_signal, | ||
615 | Edje_Patterns *ppat_source, | ||
616 | const char *sig, | ||
617 | const char *source, | ||
618 | Eina_List *callbacks, | ||
619 | Edje *ed, | ||
620 | Eina_Bool prop | ||
621 | ) | ||
622 | { | ||
623 | Edje_States *signal_result; | ||
624 | Edje_States *source_result; | ||
625 | int r = 0; | ||
626 | |||
627 | /* under high memory presure, they could be NULL */ | ||
628 | if (!ppat_source || !ppat_signal) return 0; | ||
629 | |||
630 | ppat_signal->ref++; | ||
631 | ppat_source->ref++; | ||
632 | _edje_match_patterns_exec_init_states(ppat_signal->states, | ||
633 | ppat_signal->patterns_size, | ||
634 | ppat_signal->max_length); | ||
635 | _edje_match_patterns_exec_init_states(ppat_source->states, | ||
636 | ppat_source->patterns_size, | ||
637 | ppat_source->max_length); | ||
638 | |||
639 | signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states); | ||
640 | source_result = _edje_match_fn(ppat_source, source, ppat_source->states); | ||
641 | |||
642 | if (signal_result && source_result) | ||
643 | r = edje_match_callback_exec_check_finals(ppat_signal, | ||
644 | ppat_source, | ||
645 | ppat_signal->finals, | ||
646 | ppat_source->finals, | ||
647 | signal_result, | ||
648 | source_result, | ||
649 | sig, | ||
650 | source, | ||
651 | callbacks, | ||
652 | ed, | ||
653 | prop); | ||
654 | ppat_signal->ref--; | ||
655 | ppat_source->ref--; | ||
656 | if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal); | ||
657 | if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source); | ||
658 | return r; | ||
659 | } | ||
660 | |||
661 | void | ||
662 | edje_match_patterns_free(Edje_Patterns *ppat) | ||
663 | { | ||
664 | if (!ppat) return ; | ||
665 | |||
666 | ppat->delete_me = 1; | ||
667 | ppat->ref--; | ||
668 | if (ppat->ref > 0) return; | ||
669 | _edje_match_states_free(ppat->states, 2); | ||
670 | free(ppat); | ||
671 | } | ||
672 | |||
673 | void | ||
674 | _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp) | ||
675 | { | ||
676 | if (!ssp->signals_patterns) | ||
677 | return; | ||
678 | |||
679 | edje_match_patterns_free(ssp->signals_patterns); | ||
680 | edje_match_patterns_free(ssp->sources_patterns); | ||
681 | ssp->signals_patterns = NULL; | ||
682 | ssp->sources_patterns = NULL; | ||
683 | } | ||
684 | |||
685 | static Eina_Rbtree_Direction | ||
686 | _edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1, | ||
687 | const Edje_Signal_Source_Char *n2, | ||
688 | __UNUSED__ void *data) | ||
689 | { | ||
690 | int cmp; | ||
691 | |||
692 | cmp = strcmp(n1->signal, n2->signal); | ||
693 | if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT; | ||
694 | |||
695 | return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT; | ||
696 | } | ||
697 | |||
698 | static int | ||
699 | _edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node, | ||
700 | const char *sig, | ||
701 | __UNUSED__ int length, | ||
702 | const char *source) | ||
703 | { | ||
704 | int cmp; | ||
705 | |||
706 | cmp = strcmp(node->signal, sig); | ||
707 | if (cmp) return cmp; | ||
708 | |||
709 | return strcmp(node->source, source); | ||
710 | } | ||
711 | |||
712 | |||
713 | Eina_List * | ||
714 | edje_match_program_hash_build(Edje_Program * const *programs, | ||
715 | unsigned int count, | ||
716 | Eina_Rbtree **tree) | ||
717 | { | ||
718 | Eina_List *result = NULL; | ||
719 | Eina_Rbtree *new = NULL; | ||
720 | unsigned int i; | ||
721 | |||
722 | for (i = 0; i < count; ++i) | ||
723 | { | ||
724 | if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\") | ||
725 | && programs[i]->source && !strpbrk(programs[i]->source, "*?[\\")) | ||
726 | { | ||
727 | Edje_Signal_Source_Char *item; | ||
728 | |||
729 | item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, programs[i]->signal, 0, | ||
730 | EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), programs[i]->source); | ||
731 | if (!item) | ||
732 | { | ||
733 | item = malloc(sizeof (Edje_Signal_Source_Char)); | ||
734 | if (!item) continue; | ||
735 | |||
736 | item->signal = programs[i]->signal; | ||
737 | item->source = programs[i]->source; | ||
738 | item->list = NULL; | ||
739 | |||
740 | new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), | ||
741 | EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); | ||
742 | } | ||
743 | |||
744 | item->list = eina_list_prepend(item->list, programs[i]); | ||
745 | } | ||
746 | else | ||
747 | result = eina_list_prepend(result, programs[i]); | ||
748 | } | ||
749 | |||
750 | *tree = new; | ||
751 | return result; | ||
752 | } | ||
753 | |||
754 | Eina_List * | ||
755 | edje_match_callback_hash_build(const Eina_List *callbacks, | ||
756 | Eina_Rbtree **tree) | ||
757 | { | ||
758 | Eina_List *result = NULL; | ||
759 | Eina_Rbtree *new = NULL; | ||
760 | Edje_Signal_Callback *callback; | ||
761 | const Eina_List *l; | ||
762 | |||
763 | EINA_LIST_FOREACH(callbacks, l, callback) | ||
764 | { | ||
765 | if (callback->signal && !strpbrk(callback->signal, "*?[\\") | ||
766 | && callback->source && !strpbrk(callback->source, "*?[\\")) | ||
767 | { | ||
768 | Edje_Signal_Source_Char *item; | ||
769 | |||
770 | item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0, | ||
771 | EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source); | ||
772 | if (!item) | ||
773 | { | ||
774 | item = malloc(sizeof (Edje_Signal_Source_Char)); | ||
775 | if (!item) continue; | ||
776 | |||
777 | item->signal = callback->signal; | ||
778 | item->source = callback->source; | ||
779 | item->list = NULL; | ||
780 | |||
781 | new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), | ||
782 | EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); | ||
783 | } | ||
784 | |||
785 | item->list = eina_list_prepend(item->list, callback); | ||
786 | } | ||
787 | else | ||
788 | result = eina_list_prepend(result, callback); | ||
789 | } | ||
790 | |||
791 | *tree = new; | ||
792 | return result; | ||
793 | } | ||
794 | |||
795 | const Eina_List * | ||
796 | edje_match_signal_source_hash_get(const char *sig, | ||
797 | const char *source, | ||
798 | const Eina_Rbtree *tree) | ||
799 | { | ||
800 | Edje_Signal_Source_Char *lookup; | ||
801 | |||
802 | lookup = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(tree, sig, 0, | ||
803 | EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source); | ||
804 | |||
805 | if (lookup) return lookup->list; | ||
806 | return NULL; | ||
807 | } | ||
808 | |||
809 | void | ||
810 | edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data) | ||
811 | { | ||
812 | eina_list_free(key->list); | ||
813 | free(key); | ||
814 | } | ||