3 struct simple_pattern {
7 SIMPLE_PREFIX_MODE mode;
10 struct simple_pattern *child;
12 struct simple_pattern *next;
15 static inline struct simple_pattern *parse_pattern(const char *str, SIMPLE_PREFIX_MODE default_mode) {
16 SIMPLE_PREFIX_MODE mode;
17 struct simple_pattern *child = NULL;
19 char *buf = strdupz(str);
20 char *s = buf, *c = buf;
22 // skip asterisks in front
25 // find the next asterisk
26 while(*c && *c != '*') c++;
28 // do we have an asterisk in the middle?
29 if(*c == '*' && c[1] != '\0') {
31 child = parse_pattern(c, default_mode);
35 // check what this one matches
37 size_t len = strlen(s);
38 if(len >= 2 && *s == '*' && s[len - 1] == '*') {
41 mode = SIMPLE_PATTERN_SUBSTRING;
43 else if(len >= 1 && *s == '*') {
45 mode = SIMPLE_PATTERN_SUFFIX;
47 else if(len >= 1 && s[len - 1] == '*') {
49 mode = SIMPLE_PATTERN_PREFIX;
54 // allocate the structure
55 struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
57 m->match = strdupz(s);
58 m->len = strlen(m->match);
62 m->mode = SIMPLE_PATTERN_SUBSTRING;
72 SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE default_mode) {
73 struct simple_pattern *root = NULL, *last = NULL;
75 if(unlikely(!list || !*list)) return root;
77 char *buf = strdupz(list);
85 while(isspace(*s)) s++;
93 if(unlikely(!*s)) break;
95 // find the next space
97 while(*c && !isspace(*c)) c++;
101 if(likely(*c)) n = c + 1;
104 // terminate our string
107 struct simple_pattern *m = parse_pattern(s, default_mode);
108 m->negative = negative;
110 if(likely(n)) *c = ' ';
112 // link it at the end
120 // prepare for next loop
126 return (SIMPLE_PATTERN *)root;
129 static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) {
134 case SIMPLE_PATTERN_SUBSTRING:
135 if(!m->len) return 1;
136 if((s = strstr(str, m->match))) {
137 if(!m->child) return 1;
138 return match_pattern(m->child, &s[m->len], len - (s - str) - m->len);
142 case SIMPLE_PATTERN_PREFIX:
143 if(unlikely(strncmp(str, m->match, m->len) == 0)) {
144 if(!m->child) return 1;
145 return match_pattern(m->child, &str[m->len], len - m->len);
149 case SIMPLE_PATTERN_SUFFIX:
150 if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
151 if(!m->child) return 1;
156 case SIMPLE_PATTERN_EXACT:
158 if(unlikely(strcmp(str, m->match) == 0)) {
159 if(!m->child) return 1;
169 int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str) {
170 struct simple_pattern *m, *root = (struct simple_pattern *)list;
172 if(unlikely(!root)) return 0;
174 size_t len = strlen(str);
175 for(m = root; m ; m = m->next)
176 if(match_pattern(m, str, len)) {
177 if(m->negative) return 0;
184 static inline void free_pattern(struct simple_pattern *m) {
187 if(m->next) free_pattern(m->next);
188 if(m->child) free_pattern(m->child);
189 freez((void *)m->match);
193 void simple_pattern_free(SIMPLE_PATTERN *list) {
196 free_pattern(((struct simple_pattern *)list)->next);