]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - tools/perf/util/strfilter.c
6 #include "sane_ctype.h"
9 static const char *OP_and
= "&"; /* Logical AND */
10 static const char *OP_or
= "|"; /* Logical OR */
11 static const char *OP_not
= "!"; /* Logical NOT */
13 #define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!')
14 #define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')')
16 static void strfilter_node__delete(struct strfilter_node
*node
)
19 if (node
->p
&& !is_operator(*node
->p
))
20 zfree((char **)&node
->p
);
21 strfilter_node__delete(node
->l
);
22 strfilter_node__delete(node
->r
);
27 void strfilter__delete(struct strfilter
*filter
)
30 strfilter_node__delete(filter
->root
);
35 static const char *get_token(const char *s
, const char **e
)
39 while (isspace(*s
)) /* Skip spaces */
48 if (!is_separator(*s
)) {
51 while (*p
&& !is_separator(*p
) && !isspace(*p
))
53 /* Escape and special case: '!' is also used in glob pattern */
54 if (*(p
- 1) == '\\' || (*p
== '!' && *(p
- 1) == '[')) {
64 static struct strfilter_node
*strfilter_node__alloc(const char *op
,
65 struct strfilter_node
*l
,
66 struct strfilter_node
*r
)
68 struct strfilter_node
*node
= zalloc(sizeof(*node
));
79 static struct strfilter_node
*strfilter_node__new(const char *s
,
82 struct strfilter_node root
, *cur
, *last_op
;
88 memset(&root
, 0, sizeof(root
));
89 last_op
= cur
= &root
;
92 while (*s
!= '\0' && *s
!= ')') {
94 case '&': /* Exchg last OP->r with AND */
95 if (!cur
->r
|| !last_op
->r
)
97 cur
= strfilter_node__alloc(OP_and
, last_op
->r
, NULL
);
103 case '|': /* Exchg the root with OR */
104 if (!cur
->r
|| !root
.r
)
106 cur
= strfilter_node__alloc(OP_or
, root
.r
, NULL
);
112 case '!': /* Add NOT as a leaf node */
115 cur
->r
= strfilter_node__alloc(OP_not
, NULL
, NULL
);
120 case '(': /* Recursively parses inside the parenthesis */
123 cur
->r
= strfilter_node__new(s
+ 1, &s
);
126 if (!cur
->r
|| *s
!= ')')
133 cur
->r
= strfilter_node__alloc(NULL
, NULL
, NULL
);
136 cur
->r
->p
= strndup(s
, e
- s
);
140 s
= get_token(e
, &e
);
150 strfilter_node__delete(root
.r
);
155 * Parse filter rule and return new strfilter.
156 * Return NULL if fail, and *ep == NULL if memory allocation failed.
158 struct strfilter
*strfilter__new(const char *rules
, const char **err
)
160 struct strfilter
*filter
= zalloc(sizeof(*filter
));
161 const char *ep
= NULL
;
164 filter
->root
= strfilter_node__new(rules
, &ep
);
166 if (!filter
|| !filter
->root
|| *ep
!= '\0') {
169 strfilter__delete(filter
);
176 static int strfilter__append(struct strfilter
*filter
, bool _or
,
177 const char *rules
, const char **err
)
179 struct strfilter_node
*right
, *root
;
180 const char *ep
= NULL
;
182 if (!filter
|| !rules
)
185 right
= strfilter_node__new(rules
, &ep
);
186 if (!right
|| *ep
!= '\0') {
191 root
= strfilter_node__alloc(_or
? OP_or
: OP_and
, filter
->root
, right
);
201 strfilter_node__delete(right
);
202 return ep
? -EINVAL
: -ENOMEM
;
205 int strfilter__or(struct strfilter
*filter
, const char *rules
, const char **err
)
207 return strfilter__append(filter
, true, rules
, err
);
210 int strfilter__and(struct strfilter
*filter
, const char *rules
,
213 return strfilter__append(filter
, false, rules
, err
);
216 static bool strfilter_node__compare(struct strfilter_node
*node
,
219 if (!node
|| !node
->p
)
224 return strfilter_node__compare(node
->l
, str
) ||
225 strfilter_node__compare(node
->r
, str
);
227 return strfilter_node__compare(node
->l
, str
) &&
228 strfilter_node__compare(node
->r
, str
);
230 return !strfilter_node__compare(node
->r
, str
);
232 return strglobmatch(str
, node
->p
);
236 /* Return true if STR matches the filter rules */
237 bool strfilter__compare(struct strfilter
*filter
, const char *str
)
241 return strfilter_node__compare(filter
->root
, str
);
244 static int strfilter_node__sprint(struct strfilter_node
*node
, char *buf
);
246 /* sprint node in parenthesis if needed */
247 static int strfilter_node__sprint_pt(struct strfilter_node
*node
, char *buf
)
250 int pt
= node
->r
? 2 : 0; /* don't need to check node->l */
254 len
= strfilter_node__sprint(node
, buf
);
262 static int strfilter_node__sprint(struct strfilter_node
*node
, char *buf
)
266 if (!node
|| !node
->p
)
272 len
= strfilter_node__sprint_pt(node
->l
, buf
);
278 *(buf
+ len
++) = *node
->p
;
282 rlen
= strfilter_node__sprint_pt(node
->r
, buf
);
288 len
= strlen(node
->p
);
290 strcpy(buf
, node
->p
);
296 char *strfilter__string(struct strfilter
*filter
)
301 len
= strfilter_node__sprint(filter
->root
, NULL
);
305 ret
= malloc(len
+ 1);
307 strfilter_node__sprint(filter
->root
, ret
);