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) {
14 info(">>>> PARSE: '%s'", str);
16 NETDATA_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 = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
43 else if(len >= 1 && *s == '*') {
45 mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
47 else if(len >= 1 && s[len - 1] == '*') {
49 mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
54 // allocate the structure
55 struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
58 m->len = strlen(m->match);
62 m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
69 info("PATTERN '%s' is composed by", str);
70 struct simple_pattern *p;
71 for(p = m; p ; p = p->child)
72 info(">>>> COMPONENT: '%s%s%s' (len %zu type %u)",
73 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
75 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
82 NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
83 struct simple_pattern *root = NULL, *last = NULL;
85 if(unlikely(!list || !*list)) return root;
87 char *buf = strdupz(list);
93 while(isspace(*s)) s++;
96 if(unlikely(!*s)) break;
98 // find the next space
100 while(*c && !isspace(*c)) c++;
102 // find the next word
104 if(likely(*c)) n = c + 1;
107 // terminate our string
110 struct simple_pattern *m = parse_pattern(s, default_mode);
112 if(likely(n)) *c = ' ';
114 // link it at the end
122 // prepare for next loop
128 return (NETDATA_SIMPLE_PATTERN *)root;
131 static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) {
132 info("CHECK string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
133 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
135 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
142 case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
143 if(!m->len) return 1;
144 if((s = strstr(str, m->match))) {
145 if(!m->child) return 1;
146 return match_pattern(m->child, &s[m->len], len - (s - str) - m->len);
150 case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
151 if(unlikely(strncmp(str, m->match, m->len) == 0)) {
152 if(!m->child) return 1;
153 return match_pattern(m->child, &str[m->len], len - m->len);
157 case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
158 if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
159 if(!m->child) return 1;
164 case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
166 if(unlikely(strcmp(str, m->match) == 0)) {
167 if(!m->child) return 1;
177 int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
178 struct simple_pattern *m, *root = (struct simple_pattern *)list;
180 if(unlikely(!root)) return 0;
182 size_t len = strlen(str);
183 for(m = root; m ; m = m->next)
184 if(match_pattern(m, str, len)) {
185 info("MATCHED string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
186 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
188 (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
191 struct simple_pattern *p;
192 for(p = m; p ; p = p->child)
193 info(">>>> MATCHED COMPONENT: '%s%s%s' (len %zu type %u)",
194 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
196 (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",