Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_match.c
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 *signal_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    Edje_Signal_Callback *escb;
466    Eina_Array   run;
467    size_t       i;
468    size_t       j;
469    int          r = 1;
470
471    eina_array_step_set(&run, sizeof (Eina_Array), 4);
472
473    for (i = 0; i < signal_states->size; ++i)
474      {
475         if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
476           {
477              for (j = 0; j < source_states->size; ++j)
478                {
479                   if (signal_states->states[i].idx == source_states->states[j].idx
480                       && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
481                     {
482                        escb = eina_list_nth(callbacks, signal_states->states[i].idx);
483                        if (escb)
484                          {
485                             if ((prop) && (escb->propagate)) continue;
486                             if ((!escb->just_added)
487                                 && (!escb->delete_me))
488                               {
489                                  eina_array_push(&run, escb);
490                                  r = 2;
491                               }
492                          }
493                     }
494                }
495           }
496      }
497
498    while ((escb = eina_array_pop(&run)))
499      {
500         escb->func(escb->data, ed->obj, sig, source);
501         if (_edje_block_break(ed))
502           {
503              r = 0;
504              break;
505           }
506         if ((signal_ppat->delete_me) || (source_ppat->delete_me))
507           {
508              r = 0;
509              break;
510           }
511      }
512
513    eina_array_flush(&run);
514
515    return r;
516 }
517
518
519 static Edje_States*
520 _edje_match_fn(const Edje_Patterns      *ppat,
521                const char               *string,
522                Edje_States              *states)
523 {
524    Edje_States  *new_states = states + 1;
525    const char   *c;
526
527    for (c = string; *c && states->size; ++c)
528      {
529         size_t  i;
530
531         _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
532
533         for (i = 0; i < states->size; ++i)
534           {
535              const size_t       idx = states->states[i].idx;
536              const size_t       pos = states->states[i].pos;
537
538              if (!ppat->patterns[idx][pos])
539                 continue;
540              else if (ppat->patterns[idx][pos] == '*')
541                {
542                   _edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
543                   _edje_match_states_insert(new_states, ppat->max_length, idx, pos);
544                }
545              else
546                {
547                   size_t        m;
548
549                   if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
550                                                       *c,
551                                                       &m) != EDJE_MATCH_OK)
552                      return NULL;
553
554                   if (m)
555                      _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
556                }
557           }
558           {
559              Edje_States  *tmp = states;
560
561              states = new_states;
562              new_states = tmp;
563           }
564      }
565
566    return states;
567 }
568
569 Eina_Bool
570 edje_match_collection_dir_exec(const Edje_Patterns      *ppat,
571                                const char               *string)
572 {
573    Edje_States  *result;
574    Eina_Bool     r = EINA_FALSE;
575
576    /* under high memory presure, it could be NULL */
577    if (!ppat) return EINA_FALSE;
578
579    _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
580
581    result = _edje_match_fn(ppat, string, ppat->states);
582
583    if (result)
584       r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
585
586    return r;
587 }
588
589 Eina_Bool
590 edje_match_programs_exec(const Edje_Patterns    *ppat_signal,
591                          const Edje_Patterns    *ppat_source,
592                          const char             *sig,
593                          const char             *source,
594                          Edje_Program          **programs,
595                          Eina_Bool (*func)(Edje_Program *pr, void *data),
596                          void                   *data,
597                          Eina_Bool               prop)
598 {
599    Edje_States  *signal_result;
600    Edje_States  *source_result;
601    Eina_Bool     r = EINA_FALSE;
602
603    /* under high memory presure, they could be NULL */
604    if (!ppat_source || !ppat_signal) return EINA_FALSE;
605
606    _edje_match_patterns_exec_init_states(ppat_signal->states,
607                                          ppat_signal->patterns_size,
608                                          ppat_signal->max_length);
609    _edje_match_patterns_exec_init_states(ppat_source->states,
610                                          ppat_source->patterns_size,
611                                          ppat_source->max_length);
612
613    signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
614    source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
615
616    if (signal_result && source_result)
617       r = edje_match_programs_exec_check_finals(ppat_signal->finals,
618                                                 ppat_source->finals,
619                                                 signal_result,
620                                                 source_result,
621                                                 programs,
622                                                 func,
623                                                 data,
624                                                 prop);
625    return r;
626 }
627
628 int
629 edje_match_callback_exec(Edje_Patterns          *ppat_signal,
630                          Edje_Patterns          *ppat_source,
631                          const char             *sig,
632                          const char             *source,
633                          Eina_List              *callbacks,
634                          Edje                   *ed,
635                          Eina_Bool               prop
636                         )
637 {
638    Edje_States  *signal_result;
639    Edje_States  *source_result;
640    int           r = 0;
641
642    /* under high memory presure, they could be NULL */
643    if (!ppat_source || !ppat_signal) return 0;
644
645    ppat_signal->ref++;
646    ppat_source->ref++;
647    _edje_match_patterns_exec_init_states(ppat_signal->states,
648                                          ppat_signal->patterns_size,
649                                          ppat_signal->max_length);
650    _edje_match_patterns_exec_init_states(ppat_source->states,
651                                          ppat_source->patterns_size,
652                                          ppat_source->max_length);
653
654    signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
655    source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
656
657    if (signal_result && source_result)
658       r = edje_match_callback_exec_check_finals(ppat_signal,
659                                                 ppat_source,
660                                                 ppat_signal->finals,
661                                                 ppat_source->finals,
662                                                 signal_result,
663                                                 source_result,
664                                                 sig,
665                                                 source,
666                                                 callbacks,
667                                                 ed,
668                                                 prop);
669    ppat_signal->ref--;
670    ppat_source->ref--;
671    if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal);
672    if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source);
673    return r;
674 }
675
676 void
677 edje_match_patterns_free(Edje_Patterns *ppat)
678 {
679    if (!ppat) return ;
680
681    ppat->delete_me = 1;
682    ppat->ref--;
683    if (ppat->ref > 0) return;
684    _edje_match_states_free(ppat->states, 2);
685    free(ppat);
686 }
687
688 void
689 _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
690 {
691    if (!ssp->signals_patterns)
692      return;
693
694    edje_match_patterns_free(ssp->signals_patterns);
695    edje_match_patterns_free(ssp->sources_patterns);
696    ssp->signals_patterns = NULL;
697    ssp->sources_patterns = NULL;
698 }
699
700 static Eina_Rbtree_Direction
701 _edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1,
702                              const Edje_Signal_Source_Char *n2,
703                              __UNUSED__ void *data)
704 {
705    int cmp;
706
707    cmp = strcmp(n1->signal, n2->signal);
708    if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
709
710    return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
711 }
712
713 static int
714 _edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node,
715                             const char *sig,
716                             __UNUSED__ int length,
717                             const char *source)
718 {
719    int cmp;
720
721    cmp = strcmp(node->signal, sig);
722    if (cmp) return cmp;
723
724    return strcmp(node->source, source);
725 }
726
727
728 Eina_List *
729 edje_match_program_hash_build(Edje_Program * const *programs,
730                               unsigned int count,
731                               Eina_Rbtree **tree)
732 {
733    Eina_List *result = NULL;
734    Eina_Rbtree *new = NULL;
735    unsigned int i;
736
737    for (i = 0; i < count; ++i)
738      {
739         if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\")
740             && programs[i]->source && !strpbrk(programs[i]->source, "*?[\\"))
741           {
742              Edje_Signal_Source_Char *item;
743
744              item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, programs[i]->signal, 0,
745                                                                          EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), programs[i]->source);
746              if (!item)
747                {
748                   item = malloc(sizeof (Edje_Signal_Source_Char));
749                   if (!item) continue;
750
751                   item->signal = programs[i]->signal;
752                   item->source = programs[i]->source;
753                   item->list = NULL;
754
755                   new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
756                                                   EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
757                }
758
759              item->list = eina_list_prepend(item->list, programs[i]);
760           }
761         else
762            result = eina_list_prepend(result, programs[i]);
763      }
764
765    *tree = new;
766    return result;
767 }
768
769 Eina_List *
770 edje_match_callback_hash_build(const Eina_List *callbacks,
771                                Eina_Rbtree **tree)
772 {
773    Eina_List *result = NULL;
774    Eina_Rbtree *new = NULL;
775    Edje_Signal_Callback *callback;
776    const Eina_List *l;
777
778    EINA_LIST_FOREACH(callbacks, l, callback)
779      {
780         if (callback->signal && !strpbrk(callback->signal, "*?[\\")
781             && callback->source && !strpbrk(callback->source, "*?[\\"))
782           {
783              Edje_Signal_Source_Char *item;
784
785              item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0,
786                                                                          EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source);
787              if (!item)
788                {
789                   item = malloc(sizeof (Edje_Signal_Source_Char));
790                   if (!item) continue;
791
792                   item->signal = callback->signal;
793                   item->source = callback->source;
794                   item->list = NULL;
795
796                   new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
797                                                   EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
798                }
799
800              item->list = eina_list_prepend(item->list, callback);
801           }
802         else
803            result = eina_list_prepend(result, callback);
804      }
805
806    *tree = new;
807    return result;
808 }
809
810 const Eina_List *
811 edje_match_signal_source_hash_get(const char *sig,
812                                   const char *source,
813                                   const Eina_Rbtree *tree)
814 {
815    Edje_Signal_Source_Char *lookup;
816
817    lookup = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(tree, sig, 0,
818                                                                  EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source);
819
820    if (lookup) return lookup->list;
821    return NULL;
822 }
823
824 void
825 edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data)
826 {
827    eina_list_free(key->list);
828    free(key);
829 }