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);
520 _edje_match_fn(const Edje_Patterns *ppat,
524 Edje_States *new_states = states + 1;
527 for (c = string; *c && states->size; ++c)
531 _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
533 for (i = 0; i < states->size; ++i)
535 const size_t idx = states->states[i].idx;
536 const size_t pos = states->states[i].pos;
538 if (!ppat->patterns[idx][pos])
540 else if (ppat->patterns[idx][pos] == '*')
542 _edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
543 _edje_match_states_insert(new_states, ppat->max_length, idx, pos);
549 if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
551 &m) != EDJE_MATCH_OK)
555 _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
559 Edje_States *tmp = states;
570 edje_match_collection_dir_exec(const Edje_Patterns *ppat,
574 Eina_Bool r = EINA_FALSE;
576 /* under high memory presure, it could be NULL */
577 if (!ppat) return EINA_FALSE;
579 _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
581 result = _edje_match_fn(ppat, string, ppat->states);
584 r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
590 edje_match_programs_exec(const Edje_Patterns *ppat_signal,
591 const Edje_Patterns *ppat_source,
594 Edje_Program **programs,
595 Eina_Bool (*func)(Edje_Program *pr, void *data),
599 Edje_States *signal_result;
600 Edje_States *source_result;
601 Eina_Bool r = EINA_FALSE;
603 /* under high memory presure, they could be NULL */
604 if (!ppat_source || !ppat_signal) return EINA_FALSE;
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);
613 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
614 source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
616 if (signal_result && source_result)
617 r = edje_match_programs_exec_check_finals(ppat_signal->finals,
629 edje_match_callback_exec(Edje_Patterns *ppat_signal,
630 Edje_Patterns *ppat_source,
633 Eina_List *callbacks,
638 Edje_States *signal_result;
639 Edje_States *source_result;
642 /* under high memory presure, they could be NULL */
643 if (!ppat_source || !ppat_signal) return 0;
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);
654 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
655 source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
657 if (signal_result && source_result)
658 r = edje_match_callback_exec_check_finals(ppat_signal,
671 if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal);
672 if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source);
677 edje_match_patterns_free(Edje_Patterns *ppat)
683 if (ppat->ref > 0) return;
684 _edje_match_states_free(ppat->states, 2);
689 _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
691 if (!ssp->signals_patterns)
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;
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)
707 cmp = strcmp(n1->signal, n2->signal);
708 if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
710 return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
714 _edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node,
716 __UNUSED__ int length,
721 cmp = strcmp(node->signal, sig);
724 return strcmp(node->source, source);
729 edje_match_program_hash_build(Edje_Program * const *programs,
733 Eina_List *result = NULL;
734 Eina_Rbtree *new = NULL;
737 for (i = 0; i < count; ++i)
739 if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\")
740 && programs[i]->source && !strpbrk(programs[i]->source, "*?[\\"))
742 Edje_Signal_Source_Char *item;
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);
748 item = malloc(sizeof (Edje_Signal_Source_Char));
751 item->signal = programs[i]->signal;
752 item->source = programs[i]->source;
755 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
756 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
759 item->list = eina_list_prepend(item->list, programs[i]);
762 result = eina_list_prepend(result, programs[i]);
770 edje_match_callback_hash_build(const Eina_List *callbacks,
773 Eina_List *result = NULL;
774 Eina_Rbtree *new = NULL;
775 Edje_Signal_Callback *callback;
778 EINA_LIST_FOREACH(callbacks, l, callback)
780 if (callback->signal && !strpbrk(callback->signal, "*?[\\")
781 && callback->source && !strpbrk(callback->source, "*?[\\"))
783 Edje_Signal_Source_Char *item;
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);
789 item = malloc(sizeof (Edje_Signal_Source_Char));
792 item->signal = callback->signal;
793 item->source = callback->source;
796 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
797 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
800 item->list = eina_list_prepend(item->list, callback);
803 result = eina_list_prepend(result, callback);
811 edje_match_signal_source_hash_get(const char *sig,
813 const Eina_Rbtree *tree)
815 Edje_Signal_Source_Char *lookup;
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);
820 if (lookup) return lookup->list;
825 edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data)
827 eina_list_free(key->list);