|
@@ -237,3 +237,70 @@ bool strfilter__compare(struct strfilter *filter, const char *str)
|
|
|
return false;
|
|
|
return strfilter_node__compare(filter->root, str);
|
|
|
}
|
|
|
+
|
|
|
+static int strfilter_node__sprint(struct strfilter_node *node, char *buf);
|
|
|
+
|
|
|
+/* sprint node in parenthesis if needed */
|
|
|
+static int strfilter_node__sprint_pt(struct strfilter_node *node, char *buf)
|
|
|
+{
|
|
|
+ int len;
|
|
|
+ int pt = node->r ? 2 : 0; /* don't need to check node->l */
|
|
|
+
|
|
|
+ if (buf && pt)
|
|
|
+ *buf++ = '(';
|
|
|
+ len = strfilter_node__sprint(node, buf);
|
|
|
+ if (len < 0)
|
|
|
+ return len;
|
|
|
+ if (buf && pt)
|
|
|
+ *(buf + len) = ')';
|
|
|
+ return len + pt;
|
|
|
+}
|
|
|
+
|
|
|
+static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
|
|
|
+{
|
|
|
+ int len = 0, rlen;
|
|
|
+
|
|
|
+ if (!node || !node->p)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (*node->p) {
|
|
|
+ case '|':
|
|
|
+ case '&':
|
|
|
+ len = strfilter_node__sprint_pt(node->l, buf);
|
|
|
+ if (len < 0)
|
|
|
+ return len;
|
|
|
+ case '!':
|
|
|
+ if (buf) {
|
|
|
+ *(buf + len++) = *node->p;
|
|
|
+ buf += len;
|
|
|
+ } else
|
|
|
+ len++;
|
|
|
+ rlen = strfilter_node__sprint_pt(node->r, buf);
|
|
|
+ if (rlen < 0)
|
|
|
+ return rlen;
|
|
|
+ len += rlen;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ len = strlen(node->p);
|
|
|
+ if (buf)
|
|
|
+ strcpy(buf, node->p);
|
|
|
+ }
|
|
|
+
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
+char *strfilter__string(struct strfilter *filter)
|
|
|
+{
|
|
|
+ int len;
|
|
|
+ char *ret = NULL;
|
|
|
+
|
|
|
+ len = strfilter_node__sprint(filter->root, NULL);
|
|
|
+ if (len < 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ ret = malloc(len + 1);
|
|
|
+ if (ret)
|
|
|
+ strfilter_node__sprint(filter->root, ret);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|