3 struct simple_pattern {
6 NETDATA_SIMPLE_PREFIX_MODE mode;
8 struct simple_pattern *child;
10 struct simple_pattern *next;
13 static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
16 info(">>>> PARSE: '%s'", str);
19 NETDATA_SIMPLE_PREFIX_MODE mode;
20 struct simple_pattern *child = NULL;
22 char *buf = strdupz(str);
23 char *s = buf, *c = buf;
25 // skip asterisks in front
28 // find the next asterisk
29 while(*c && *c != '*') c++ ;
31 // do we have an asterisk in the middle?
32 if(*c == '*' && c[1] != '\0') {
34 child = parse_pattern(c, default_mode);
38 // check what this one matches
40 size_t len = strlen(s);
41 if(len >= 2 && *s == '*' && s[len - 1] == '*') {
44 mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
46 else if(len >= 1 && *s == '*') {
48 mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
50 else if(len >= 1 && s[len - 1] == '*') {
52 mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
57 // allocate the structure
58 struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
61 m->len = strlen(m->match);
65 m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
74 info("PATTERN '%s' is composed by", str);
75 struct simple_pattern *p;
76 for(p = m; p ; p = p->child)
77 info(">>>> COMPONENT: '%s%s%s' (len %zu type %u)",
78 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
80 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
88 NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
89 struct simple_pattern *root = NULL, *last = NULL;
91 if(unlikely(!list || !*list)) return root;
93 char *buf = strdupz(list);
99 while(isspace(*s)) s++;
102 if(unlikely(!*s)) break;
104 // find the next space
106 while(*c && !isspace(*c)) c++;
108 // find the next word
110 if(likely(*c)) n = c + 1;
113 // terminate our string
116 struct simple_pattern *m = parse_pattern(s, default_mode);
118 if(likely(n)) *c = ' ';
120 // link it at the end
128 // prepare for next loop
134 return (NETDATA_SIMPLE_PATTERN *)root;
137 static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) {
141 info("CHECK string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
142 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
144 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
152 case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
153 if(!m->len) return 1;
154 if((s = strstr(str, m->match))) {
155 if(!m->child) return 1;
156 return match_pattern(m->child, &s[m->len], len - (s - str) - m->len);
160 case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
161 if(unlikely(strncmp(str, m->match, m->len) == 0)) {
162 if(!m->child) return 1;
163 return match_pattern(m->child, &str[m->len], len - m->len);
167 case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
168 if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
169 if(!m->child) return 1;
174 case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
176 if(unlikely(strcmp(str, m->match) == 0)) {
177 if(!m->child) return 1;
187 int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
188 struct simple_pattern *m, *root = (struct simple_pattern *)list;
190 if(unlikely(!root)) return 0;
192 size_t len = strlen(str);
193 for(m = root; m ; m = m->next)
194 if(match_pattern(m, str, len)) {
198 info("MATCHED string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
199 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
201 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
204 struct simple_pattern *p;
205 for(p = m; p ; p = p->child)
206 info(">>>> MATCHED COMPONENT: '%s%s%s' (len %zu type %u)",
207 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
209 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
220 static inline void free_pattern(struct simple_pattern *m) {
221 if(m->next) free_pattern(m->next);
222 if(m->child) free_pattern(m->child);
223 freez((void *)m->match);
227 void netdata_simple_pattern_free(NETDATA_SIMPLE_PATTERN *list) {
228 free_pattern(((struct simple_pattern *)list)->next);