1 #include "edje_private.h"
3 /* States manipulations. */
5 typedef struct _Edje_State Edje_State;
20 _edje_match_states_free(Edje_States *states,
30 Size |= sizeof (void *) - 1; \
35 _edje_match_states_alloc(Edje_Patterns *ppat, int n)
39 const size_t patterns_size = ppat->patterns_size;
40 const size_t patterns_max_length = ppat->max_length;
42 const size_t array_len = (patterns_max_length + 1) * patterns_size;
46 size_t states_has_size;
49 unsigned char *states;
54 states_size = sizeof (*l->states) * array_len;
57 has_size = sizeof (*l->has) * array_len;
60 states_has_size = states_size + has_size;
62 struct_size = sizeof (*l);
64 struct_size += states_has_size;
66 l = malloc(n * struct_size);
70 ppat->states->size = 0;
72 states = (unsigned char *)(l + n);
73 has = states + states_size;
75 for (i = 0; i < n; ++i)
77 l[i].states = (Edje_State *)states;
78 l[i].has = (Eina_Bool *)has;
81 memset(l[i].has, 0, has_size);
83 states += states_has_size;
84 has += states_has_size;
91 _edje_match_states_insert(Edje_States *list,
92 size_t patterns_max_length,
98 i = (idx * (patterns_max_length + 1)) + pos;
102 if (list->has[i]) return;
107 list->states[i].idx = idx;
108 list->states[i].pos = pos;
114 _edje_match_states_clear(Edje_States *list,
115 __UNUSED__ size_t patterns_size,
116 __UNUSED__ size_t patterns_max_length)
121 /* Token manipulation. */
125 patterns_not_found = 0,
127 patterns_syntax_error = 2
131 _edje_match_patterns_exec_class_token(enum status *status,
137 *status = patterns_syntax_error;
140 else if (cl_tok[1] == '-' && cl_tok[2] != ']')
142 if (*cl_tok <= c && c <= cl_tok[2])
143 *status = patterns_found;
149 *status = patterns_found;
154 static Edje_Match_Error
155 _edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret)
160 return EDJE_MATCH_SYNTAX_ERROR;
164 return EDJE_MATCH_OK;
168 return EDJE_MATCH_OK;
172 static Edje_Match_Error
173 _edje_match_patterns_exec_class(const char *cl,
177 enum status status = patterns_not_found;
181 if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK)
182 return EDJE_MATCH_SYNTAX_ERROR;
188 pos += _edje_match_patterns_exec_class_token(&status, cl + pos, c);
190 while (cl[pos] && cl[pos] != ']');
192 if (status == patterns_syntax_error || !cl[pos])
193 return EDJE_MATCH_SYNTAX_ERROR;
195 if (status == patterns_found)
196 *ret = neg ? 0 : pos + 1;
198 *ret = neg ? pos + 1 : 0;
200 return EDJE_MATCH_OK;
203 static Edje_Match_Error
204 _edje_match_patterns_exec_token(const char *tok,
213 *ret = tok[1] == c ? 2 : 0;
214 return EDJE_MATCH_OK;
216 return EDJE_MATCH_SYNTAX_ERROR;
220 return EDJE_MATCH_OK;
223 return _edje_match_patterns_exec_class(tok, c, ret);
226 *ret = *tok == c ? 1 : 0;
227 return EDJE_MATCH_OK;
232 _edje_match_patterns_exec_init_states(Edje_States *states,
233 size_t patterns_size,
234 size_t patterns_max_length)
238 states->size = patterns_size;
240 for (i = 0; i < patterns_size; ++i)
242 states->states[i].idx = i;
243 states->states[i].pos = 0;
244 states->has[i * (patterns_max_length + 1)] = 1;
248 /* Exported function. */
250 #define EDJE_MATCH_INIT_LIST(Func, Type, Source, Show) \
252 Func(const Eina_List *lst) \
257 if (!lst || eina_list_count(lst) <= 0) \
260 r = malloc(sizeof (Edje_Patterns) + \
261 eina_list_count(lst) \
262 * sizeof(*r->finals) \
263 * sizeof(*r->patterns)); \
264 if (!r) return NULL; \
268 r->patterns_size = eina_list_count(lst); \
270 r->patterns = (const char **)r->finals + r->patterns_size + 1; \
272 for (i = 0; lst; ++i) \
279 data = eina_list_data_get(lst); \
286 str = data->Source; \
287 if (!str) str = ""; \
288 r->patterns[i] = str; \
291 INF("%lu [%s]", (unsigned long)i, str); \
294 for (j = 0; str[j]; ++j) \
297 r->finals[i] = j + 1; \
300 j += special ? special + 1 : 0; \
302 if (j > r->max_length) \
305 lst = eina_list_next(lst); \
308 if (!_edje_match_states_alloc(r, 2)) \
317 #define EDJE_MATCH_INIT_ARRAY(Func, Type, Source, Show) \
319 Func(Type * const *lst, unsigned int count) \
324 if (!lst || count == 0) \
327 r = malloc(sizeof (Edje_Patterns) + \
329 * sizeof(*r->finals) \
330 * sizeof(*r->patterns)); \
331 if (!r) return NULL; \
335 r->patterns_size = count; \
337 r->patterns = (const char **)r->finals + r->patterns_size + 1; \
339 for (i = 0; i < count; ++i) \
351 str = lst[i]->Source; \
352 if (!str) str = ""; \
353 r->patterns[i] = str; \
356 INF("%lu [%s]", (unsigned long)i, str); \
359 for (j = 0; str[j]; ++j) \
362 r->finals[i] = j + 1; \
365 j += special ? special + 1 : 0; \
367 if (j > r->max_length) \
371 if (!_edje_match_states_alloc(r, 2)) \
380 EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init,
381 Edje_Part_Collection_Directory_Entry,
383 EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init,
386 EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init,
389 EDJE_MATCH_INIT_LIST(edje_match_callback_signal_init,
390 Edje_Signal_Callback,
392 EDJE_MATCH_INIT_LIST(edje_match_callback_source_init,
393 Edje_Signal_Callback,
397 _edje_match_collection_dir_exec_finals(const size_t *finals,
398 const Edje_States *states)
402 for (i = 0; i < states->size; ++i)
404 if (states->states[i].pos >= finals[states->states[i].idx])
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),
418 Eina_Bool prop __UNUSED__)
423 /* when not enought memory, they could be NULL */
424 if (!signal_finals || !source_finals) return EINA_TRUE;
426 for (i = 0; i < signal_states->size; ++i)
428 if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
430 for (j = 0; j < source_states->size; ++j)
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])
437 pr = programs[signal_states->states[i].idx];
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,
460 Eina_List *callbacks,
465 Edje_Signal_Callback *escb;
471 eina_array_step_set(&run, sizeof (Eina_Array), 4);
473 for (i = 0; i < signal_states->size; ++i)
475 if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
477 for (j = 0; j < source_states->size; ++j)
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])
482 escb = eina_list_nth(callbacks, signal_states->states[i].idx);
485 if ((prop) && (escb->propagate)) continue;
486 if ((!escb->just_added)
487 && (!escb->delete_me))
489 eina_array_push(&run, escb);
498 while ((escb = eina_array_pop(&run)))
500 escb->func(escb->data, ed->obj, sig, source);
501 if (_edje_block_break(ed))
506 if ((signal_ppat->delete_me) || (source_ppat->delete_me))
513 eina_array_flush(&run);
519 _edje_match_fn(const Edje_Patterns *ppat,
523 Edje_States *new_states = states + 1;
526 for (c = string; *c && states->size; ++c)
530 _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
532 for (i = 0; i < states->size; ++i)
534 const size_t idx = states->states[i].idx;
535 const size_t pos = states->states[i].pos;
537 if (!ppat->patterns[idx][pos])
539 else if (ppat->patterns[idx][pos] == '*')
541 _edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
542 _edje_match_states_insert(new_states, ppat->max_length, idx, pos);
548 if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
550 &m) != EDJE_MATCH_OK)
554 _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
558 Edje_States *tmp = states;
569 edje_match_collection_dir_exec(const Edje_Patterns *ppat,
573 Eina_Bool r = EINA_FALSE;
575 /* under high memory presure, it could be NULL */
576 if (!ppat) return EINA_FALSE;
578 _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
580 result = _edje_match_fn(ppat, string, ppat->states);
583 r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
589 edje_match_programs_exec(const Edje_Patterns *ppat_signal,
590 const Edje_Patterns *ppat_source,
593 Edje_Program **programs,
594 Eina_Bool (*func)(Edje_Program *pr, void *data),
598 Edje_States *signal_result;
599 Edje_States *source_result;
600 Eina_Bool r = EINA_FALSE;
602 /* under high memory presure, they could be NULL */
603 if (!ppat_source || !ppat_signal) return EINA_FALSE;
605 _edje_match_patterns_exec_init_states(ppat_signal->states,
606 ppat_signal->patterns_size,
607 ppat_signal->max_length);
608 _edje_match_patterns_exec_init_states(ppat_source->states,
609 ppat_source->patterns_size,
610 ppat_source->max_length);
612 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
613 source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
615 if (signal_result && source_result)
616 r = edje_match_programs_exec_check_finals(ppat_signal->finals,
628 edje_match_callback_exec(Edje_Patterns *ppat_signal,
629 Edje_Patterns *ppat_source,
632 Eina_List *callbacks,
637 Edje_States *signal_result;
638 Edje_States *source_result;
641 /* under high memory presure, they could be NULL */
642 if (!ppat_source || !ppat_signal) return 0;
646 _edje_match_patterns_exec_init_states(ppat_signal->states,
647 ppat_signal->patterns_size,
648 ppat_signal->max_length);
649 _edje_match_patterns_exec_init_states(ppat_source->states,
650 ppat_source->patterns_size,
651 ppat_source->max_length);
653 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
654 source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
656 if (signal_result && source_result)
657 r = edje_match_callback_exec_check_finals(ppat_signal,
670 if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal);
671 if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source);
676 edje_match_patterns_free(Edje_Patterns *ppat)
682 if (ppat->ref > 0) return;
683 _edje_match_states_free(ppat->states, 2);
688 _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
690 if (!ssp->signals_patterns)
693 edje_match_patterns_free(ssp->signals_patterns);
694 edje_match_patterns_free(ssp->sources_patterns);
695 ssp->signals_patterns = NULL;
696 ssp->sources_patterns = NULL;
699 static Eina_Rbtree_Direction
700 _edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1,
701 const Edje_Signal_Source_Char *n2,
702 __UNUSED__ void *data)
706 cmp = strcmp(n1->signal, n2->signal);
707 if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
709 return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
713 _edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node,
715 __UNUSED__ int length,
720 cmp = strcmp(node->signal, sig);
723 return strcmp(node->source, source);
727 edje_match_program_hash_build(Edje_Program *const *programs,
731 Eina_List *result = NULL;
732 Eina_Rbtree *new = NULL;
735 for (i = 0; i < count; ++i)
737 if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\")
738 && programs[i]->source && !strpbrk(programs[i]->source, "*?[\\"))
740 Edje_Signal_Source_Char *item;
742 item = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(new, programs[i]->signal, 0,
743 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), programs[i]->source);
746 item = malloc(sizeof (Edje_Signal_Source_Char));
749 item->signal = programs[i]->signal;
750 item->source = programs[i]->source;
753 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
754 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
757 item->list = eina_list_prepend(item->list, programs[i]);
760 result = eina_list_prepend(result, programs[i]);
768 edje_match_callback_hash_build(const Eina_List *callbacks,
771 Eina_List *result = NULL;
772 Eina_Rbtree *new = NULL;
773 Edje_Signal_Callback *callback;
776 EINA_LIST_FOREACH(callbacks, l, callback)
778 if (callback->signal && !strpbrk(callback->signal, "*?[\\")
779 && callback->source && !strpbrk(callback->source, "*?[\\"))
781 Edje_Signal_Source_Char *item;
783 item = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(new, callback->signal, 0,
784 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source);
787 item = malloc(sizeof (Edje_Signal_Source_Char));
790 item->signal = callback->signal;
791 item->source = callback->source;
794 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
795 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
798 item->list = eina_list_prepend(item->list, callback);
801 result = eina_list_prepend(result, callback);
809 edje_match_signal_source_hash_get(const char *sig,
811 const Eina_Rbtree *tree)
813 Edje_Signal_Source_Char *lookup;
815 lookup = (Edje_Signal_Source_Char *)eina_rbtree_inline_lookup(tree, sig, 0,
816 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source);
818 if (lookup) return lookup->list;
823 edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data)
825 eina_list_free(key->list);