1 #include "edje_private.h"
2
3 /* States manipulations. */
4
5 typedef struct _Edje_State Edje_State;
6 struct _Edje_State
7 {
8 unsigned int idx;
9 unsigned int pos;
10 };
11
12 struct _Edje_States
13 {
14 unsigned int size;
15 Edje_State *states;
16 Eina_Bool *has;
17 };
18
19 static void
_edje_match_states_free(Edje_States * states,unsigned int states_size)20 _edje_match_states_free(Edje_States *states,
21 unsigned int 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
_edje_match_states_alloc(Edje_Patterns * ppat,int n)35 _edje_match_states_alloc(Edje_Patterns *ppat, int n)
36 {
37 Edje_States *l;
38
39 const unsigned int patterns_size = ppat->patterns_size;
40 const unsigned int patterns_max_length = ppat->max_length;
41
42 const unsigned int array_len = (patterns_max_length + 1) * patterns_size;
43
44 unsigned int states_size;
45 unsigned int has_size;
46 unsigned int states_has_size;
47 unsigned int 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
_edje_match_states_insert(Edje_States * list,unsigned int patterns_max_length,unsigned int idx,unsigned int pos)91 _edje_match_states_insert(Edje_States *list,
92 unsigned int patterns_max_length,
93 unsigned int idx,
94 unsigned int pos)
95 {
96 unsigned int 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
_edje_match_states_clear(Edje_States * list,unsigned int patterns_size EINA_UNUSED,unsigned int patterns_max_length EINA_UNUSED)114 _edje_match_states_clear(Edje_States *list,
115 unsigned int patterns_size EINA_UNUSED,
116 unsigned int patterns_max_length EINA_UNUSED)
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 unsigned int
_edje_match_patterns_exec_class_token(enum status * status,const char * cl_tok,char c)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
_edje_match_patterns_exec_class_complement(const char * cl_tok,unsigned int * ret)155 _edje_match_patterns_exec_class_complement(const char *cl_tok, unsigned int *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
_edje_match_patterns_exec_class(const char * cl,char c,unsigned int * ret)173 _edje_match_patterns_exec_class(const char *cl,
174 char c,
175 unsigned int *ret)
176 {
177 enum status status = patterns_not_found;
178 int pos = 1;
179 unsigned int 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
_edje_match_patterns_exec_token(const char * tok,char c,unsigned int * ret)204 _edje_match_patterns_exec_token(const char *tok,
205 char c,
206 unsigned int *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
_edje_match_patterns_exec_init_states(Edje_States * states,unsigned int patterns_size,unsigned int patterns_max_length)232 _edje_match_patterns_exec_init_states(Edje_States *states,
233 unsigned int patterns_size,
234 unsigned int patterns_max_length)
235 {
236 unsigned int 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 unsigned int 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 = EINA_FALSE; \
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 unsigned int 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 unsigned int 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 = EINA_FALSE; \
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 unsigned int 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 #define EDJE_MATCH_INIT_INARRAY(Func, Source, Show) \
381 Edje_Patterns * \
382 Func(const Eina_Inarray * array, const Edje_Signal_Callback_Match * matches) \
383 { \
384 Edje_Patterns *r; \
385 int *it; \
386 unsigned int i = 0; \
387 \
388 if (!matches) \
389 return NULL; \
390 \
391 r = malloc(sizeof (Edje_Patterns) + \
392 eina_inarray_count(array) \
393 * sizeof(*r->finals) \
394 * sizeof(*r->patterns)); \
395 if (!r) return NULL; \
396 \
397 r->ref = 1; \
398 r->delete_me = EINA_FALSE; \
399 r->patterns_size = eina_inarray_count(array); \
400 r->max_length = 0; \
401 r->patterns = (const char **)r->finals + r->patterns_size + 1; \
402 \
403 EINA_INARRAY_FOREACH(array, it) \
404 { \
405 const char *str; \
406 unsigned int j; \
407 int special = 0; \
408 \
409 str = (matches + *it)->Source; \
410 if (!str) str = ""; \
411 r->patterns[i] = str; \
412 \
413 if (Show) \
414 INF("%lu [%s]", (unsigned long)i, str); \
415 \
416 r->finals[i] = 0; \
417 for (j = 0; str[j]; ++j) \
418 if (str[j] != '*') \
419 { \
420 r->finals[i] = j + 1; \
421 special++; \
422 } \
423 j += special ? special + 1 : 0; \
424 \
425 if (j > r->max_length) \
426 r->max_length = j; \
427 \
428 i++; \
429 } \
430 \
431 if (!_edje_match_states_alloc(r, 2)) \
432 { \
433 free(r); \
434 return NULL; \
435 } \
436 \
437 return r; \
438 }
439
440 EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init,
441 Edje_Part_Collection_Directory_Entry,
442 entry, 0);
443 EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init,
444 Edje_Program,
445 signal, 0);
446 EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init,
447 Edje_Program,
448 source, 0);
449 EDJE_MATCH_INIT_INARRAY(edje_match_callback_signal_init,
450 signal, 0);
451 EDJE_MATCH_INIT_INARRAY(edje_match_callback_source_init,
452 source, 0);
453
454 static Eina_Bool
_edje_match_collection_dir_exec_finals(const unsigned int * finals,const Edje_States * states)455 _edje_match_collection_dir_exec_finals(const unsigned int *finals,
456 const Edje_States *states)
457 {
458 unsigned int i;
459
460 for (i = 0; i < states->size; ++i)
461 {
462 if (states->states[i].pos >= finals[states->states[i].idx])
463 return EINA_TRUE;
464 }
465 return EINA_FALSE;
466 }
467
468 static Eina_Bool
edje_match_programs_exec_check_finals(const unsigned int * signal_finals,const unsigned int * source_finals,const Edje_States * signal_states,const Edje_States * source_states,Edje_Program ** programs,Eina_Bool (* func)(Edje_Program * pr,void * data),void * data,Eina_Bool prop EINA_UNUSED)469 edje_match_programs_exec_check_finals(const unsigned int *signal_finals,
470 const unsigned int *source_finals,
471 const Edje_States *signal_states,
472 const Edje_States *source_states,
473 Edje_Program **programs,
474 Eina_Bool (*func)(Edje_Program *pr, void *data),
475 void *data,
476 Eina_Bool prop EINA_UNUSED)
477 {
478 unsigned int i;
479 unsigned int j;
480
481 /* when not enough memory, they could be NULL */
482 if (!signal_finals || !source_finals) return EINA_TRUE;
483
484 for (i = 0; i < signal_states->size; ++i)
485 {
486 if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
487 {
488 for (j = 0; j < source_states->size; ++j)
489 {
490 if (signal_states->states[i].idx == source_states->states[j].idx
491 && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
492 {
493 Edje_Program *pr;
494
495 pr = programs[signal_states->states[i].idx];
496 if (pr)
497 {
498 if (func(pr, data))
499 return EINA_FALSE;
500 }
501 }
502 }
503 }
504 }
505
506 return EINA_TRUE;
507 }
508
509 static int
edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns * ssp,const Edje_Signal_Callback_Match * matches,const Edje_States * signal_states,const Edje_States * source_states,const char * sig,const char * source,Edje * ed,Eina_Bool prop)510 edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp,
511 const Edje_Signal_Callback_Match *matches,
512 const Edje_States *signal_states,
513 const Edje_States *source_states,
514 const char *sig,
515 const char *source,
516 Edje *ed,
517 Eina_Bool prop)
518 {
519 const Edje_Signal_Callback_Match *cb;
520 Eina_Array run;
521 unsigned int i;
522 unsigned int j;
523 int r = 1;
524
525 eina_array_step_set(&run, sizeof (Eina_Array), 4);
526
527 for (i = 0; i < signal_states->size; ++i)
528 if (signal_states->states[i].pos >= ssp->signals_patterns->finals[signal_states->states[i].idx])
529 {
530 for (j = 0; j < source_states->size; ++j)
531 {
532 if (signal_states->states[i].idx == source_states->states[j].idx
533 && source_states->states[j].pos >= ssp->sources_patterns->finals[source_states->states[j].idx])
534 {
535 int *e;
536
537 e = eina_inarray_nth(&ssp->u.callbacks.globing, signal_states->states[i].idx);
538
539 cb = &matches[*e];
540 if (cb)
541 {
542 if ((prop) && ed->callbacks->flags[*e].propagate) continue;
543 eina_array_push(&run, cb);
544 r = 2;
545 }
546 }
547 }
548 }
549
550 while ((cb = eina_array_pop(&run)))
551 {
552 int idx = cb - matches;
553
554 if (ed->callbacks->flags[idx].delete_me) continue;
555
556 if (ed->callbacks->flags[idx].legacy)
557 cb->legacy((void *)ed->callbacks->custom_data[idx], ed->obj, sig, source);
558 else
559 cb->eo((void *)ed->callbacks->custom_data[idx], ed->obj, sig, source);
560 if (_edje_block_break(ed))
561 {
562 r = 0;
563 break;
564 }
565 if ((ssp->signals_patterns->delete_me) || (ssp->sources_patterns->delete_me))
566 {
567 r = 0;
568 break;
569 }
570 }
571
572 eina_array_flush(&run);
573
574 return r;
575 }
576
577 static Edje_States *
_edje_match_fn(const Edje_Patterns * ppat,const char * string,Edje_States * states)578 _edje_match_fn(const Edje_Patterns *ppat,
579 const char *string,
580 Edje_States *states)
581 {
582 Edje_States *new_states = states + 1;
583 const char *c;
584
585 for (c = string; *c && states->size; ++c)
586 {
587 unsigned int i;
588
589 _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
590
591 for (i = 0; i < states->size; ++i)
592 {
593 const unsigned int idx = states->states[i].idx;
594 const unsigned int pos = states->states[i].pos;
595
596 if (!ppat->patterns[idx][pos])
597 continue;
598 else if (ppat->patterns[idx][pos] == '*')
599 {
600 _edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
601 _edje_match_states_insert(new_states, ppat->max_length, idx, pos);
602 }
603 else
604 {
605 unsigned int m;
606
607 if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
608 *c,
609 &m) != EDJE_MATCH_OK)
610 return NULL;
611
612 if (m)
613 _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
614 }
615 }
616 {
617 Edje_States *tmp = states;
618
619 states = new_states;
620 new_states = tmp;
621 }
622 }
623
624 return states;
625 }
626
627 Eina_Bool
edje_match_collection_dir_exec(const Edje_Patterns * ppat,const char * string)628 edje_match_collection_dir_exec(const Edje_Patterns *ppat,
629 const char *string)
630 {
631 Edje_States *result;
632 Eina_Bool r = EINA_FALSE;
633
634 /* under high memory presure, it could be NULL */
635 if (!ppat) return EINA_FALSE;
636
637 _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
638
639 result = _edje_match_fn(ppat, string, ppat->states);
640
641 if (result)
642 r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
643
644 return r;
645 }
646
647 Eina_Bool
edje_match_programs_exec(const Edje_Patterns * ppat_signal,const Edje_Patterns * ppat_source,const char * sig,const char * source,Edje_Program ** programs,Eina_Bool (* func)(Edje_Program * pr,void * data),void * data,Eina_Bool prop)648 edje_match_programs_exec(const Edje_Patterns *ppat_signal,
649 const Edje_Patterns *ppat_source,
650 const char *sig,
651 const char *source,
652 Edje_Program **programs,
653 Eina_Bool (*func)(Edje_Program *pr, void *data),
654 void *data,
655 Eina_Bool prop)
656 {
657 Edje_States *signal_result;
658 Edje_States *source_result;
659 Eina_Bool r = EINA_FALSE;
660
661 /* under high memory presure, they could be NULL */
662 if (!ppat_source || !ppat_signal) return EINA_FALSE;
663
664 _edje_match_patterns_exec_init_states(ppat_signal->states,
665 ppat_signal->patterns_size,
666 ppat_signal->max_length);
667 _edje_match_patterns_exec_init_states(ppat_source->states,
668 ppat_source->patterns_size,
669 ppat_source->max_length);
670
671 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
672 source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
673
674 if (signal_result && source_result)
675 r = edje_match_programs_exec_check_finals(ppat_signal->finals,
676 ppat_source->finals,
677 signal_result,
678 source_result,
679 programs,
680 func,
681 data,
682 prop);
683 return r;
684 }
685
686 int
edje_match_callback_exec(const Edje_Signals_Sources_Patterns * ssp,const Edje_Signal_Callback_Match * matches,const char * sig,const char * source,Edje * ed,Eina_Bool prop)687 edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp,
688 const Edje_Signal_Callback_Match *matches,
689 const char *sig,
690 const char *source,
691 Edje *ed,
692 Eina_Bool prop)
693 {
694 Edje_States *signal_result;
695 Edje_States *source_result;
696 int r = 0;
697
698 /* under high memory presure, they could be NULL */
699 if (!ssp->sources_patterns || !ssp->signals_patterns) return 0;
700
701 ssp->signals_patterns->ref++;
702 ssp->sources_patterns->ref++;
703 _edje_match_patterns_exec_init_states(ssp->signals_patterns->states,
704 ssp->signals_patterns->patterns_size,
705 ssp->signals_patterns->max_length);
706 _edje_match_patterns_exec_init_states(ssp->sources_patterns->states,
707 ssp->sources_patterns->patterns_size,
708 ssp->sources_patterns->max_length);
709
710 signal_result = _edje_match_fn(ssp->signals_patterns, sig, ssp->signals_patterns->states);
711 source_result = _edje_match_fn(ssp->sources_patterns, source, ssp->sources_patterns->states);
712
713 if (signal_result && source_result)
714 r = edje_match_callback_exec_check_finals(ssp,
715 matches,
716 signal_result,
717 source_result,
718 sig,
719 source,
720 ed,
721 prop);
722 ssp->signals_patterns->ref--;
723 ssp->sources_patterns->ref--;
724 if (ssp->signals_patterns->ref <= 0) edje_match_patterns_free(ssp->signals_patterns);
725 if (ssp->sources_patterns->ref <= 0) edje_match_patterns_free(ssp->sources_patterns);
726 return r;
727 }
728
729 void
edje_match_patterns_free(Edje_Patterns * ppat)730 edje_match_patterns_free(Edje_Patterns *ppat)
731 {
732 if (!ppat) return;
733
734 ppat->delete_me = EINA_TRUE;
735 ppat->ref--;
736 if (ppat->ref > 0) return;
737 _edje_match_states_free(ppat->states, 2);
738 free(ppat);
739 }
740
741 void
_edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns * ssp)742 _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
743 {
744 if (!ssp->signals_patterns)
745 return;
746
747 edje_match_patterns_free(ssp->signals_patterns);
748 edje_match_patterns_free(ssp->sources_patterns);
749 ssp->signals_patterns = NULL;
750 ssp->sources_patterns = NULL;
751 }
752
753 static Eina_Rbtree_Direction
_edje_signal_source_node_cmp(const Edje_Signal_Source_Char * n1,const Edje_Signal_Source_Char * n2,void * data EINA_UNUSED)754 _edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1,
755 const Edje_Signal_Source_Char *n2,
756 void *data EINA_UNUSED)
757 {
758 int cmp;
759
760 cmp = strcmp(n1->signal, n2->signal);
761 if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
762
763 return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
764 }
765
766 static int
_edje_signal_source_key_cmp(const Edje_Signal_Source_Char * node,const char * sig,int length EINA_UNUSED,const char * source)767 _edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node,
768 const char *sig,
769 int length EINA_UNUSED,
770 const char *source)
771 {
772 int cmp;
773
774 cmp = strcmp(node->signal, sig);
775 if (cmp) return cmp;
776
777 return strcmp(node->source, source);
778 }
779
780 Eina_List *
edje_match_program_hash_build(Edje_Program * const * programs,unsigned int count,Eina_Rbtree ** tree)781 edje_match_program_hash_build(Edje_Program *const *programs,
782 unsigned int count,
783 Eina_Rbtree **tree)
784 {
785 Eina_List *result = NULL;
786 Eina_Rbtree *new = NULL;
787 unsigned int i;
788
789 for (i = 0; i < count; ++i)
790 {
791 if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\")
792 && programs[i]->source && !strpbrk(programs[i]->source, "*?[\\"))
793 {
794 Edje_Signal_Source_Char *item;
795
796 item = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(new, programs[i]->signal, 0,
797 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), programs[i]->source);
798 if (!item)
799 {
800 item = malloc(sizeof (Edje_Signal_Source_Char));
801 if (!item) continue;
802
803 item->signal = programs[i]->signal;
804 item->source = programs[i]->source;
805 eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (void *), 8);
806
807 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
808 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
809 }
810
811 eina_inarray_push(&item->list, &programs[i]);
812 }
813 else
814 result = eina_list_prepend(result, programs[i]);
815 }
816
817 *tree = new;
818 return result;
819 }
820
821 void
edje_match_callback_hash_build(const Edje_Signal_Callback_Match * callbacks,int callbacks_count,Eina_Rbtree ** tree,Eina_Inarray * result)822 edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callbacks,
823 int callbacks_count,
824 Eina_Rbtree **tree,
825 Eina_Inarray *result)
826 {
827 Eina_Rbtree *new = NULL;
828 int i;
829
830 eina_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8);
831
832 for (i = 0; i < callbacks_count; ++i, ++callbacks)
833 {
834 if (callbacks->signal && !strpbrk(callbacks->signal, "*?[\\")
835 && callbacks->source && !strpbrk(callbacks->source, "*?[\\"))
836 {
837 Edje_Signal_Source_Char *item;
838
839 item = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(new, callbacks->signal, 0,
840 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callbacks->source);
841 if (!item)
842 {
843 item = malloc(sizeof (Edje_Signal_Source_Char));
844 if (!item) continue;
845
846 item->signal = callbacks->signal;
847 item->source = callbacks->source;
848 eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (int), 8);
849
850 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
851 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
852 }
853
854 eina_inarray_push(&item->list, &i);
855 }
856 else
857 {
858 eina_inarray_push(result, &i);
859 }
860 }
861
862 *tree = new;
863 }
864
865 const Eina_Inarray *
edje_match_signal_source_hash_get(const char * sig,const char * source,const Eina_Rbtree * tree)866 edje_match_signal_source_hash_get(const char *sig,
867 const char *source,
868 const Eina_Rbtree *tree)
869 {
870 Edje_Signal_Source_Char *lookup;
871
872 lookup = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(tree, sig, 0,
873 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source);
874
875 if (lookup) return &lookup->list;
876 return NULL;
877 }
878
879 void
edje_match_signal_source_free(Edje_Signal_Source_Char * key,void * data EINA_UNUSED)880 edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data EINA_UNUSED)
881 {
882 eina_inarray_flush(&key->list);
883 free(key);
884 }
885
886