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