commit 952da47

default  ·  2023-09-17 00:52:44 +0000 UTC
parent 2edbb75
Backport from xs.
5 files changed,  +78, -6
M snac.c
+1, -1
1@@ -235,7 +235,7 @@ xs_str *sanitize(const char *content)
2 
3             if (valid_tags[i]) {
4                 /* accepted tag: rebuild it with only the accepted elements */
5-                xs *el = xs_regex_match(v, "(src|href|rel|class|target)=\"[^\"]*\"");
6+                xs *el = xs_regex_select(v, "(src|href|rel|class|target)=\"[^\"]*\"");
7                 xs *s3 = xs_join(el, " ");
8 
9                 s2 = xs_fmt("<%s%s%s%s>",
M snac.c
+1, -0
1@@ -17,6 +17,7 @@
2 #include "xs_time.h"
3 #include "xs_glob.h"
4 #include "xs_random.h"
5+#include "xs_match.h"
6 
7 #include "snac.h"
8 
+71, -0
 1@@ -0,0 +1,71 @@
 2+/* copyright (c) 2022 - 2023 grunfink et al. / MIT license */
 3+
 4+#ifndef _XS_MATCH_H
 5+
 6+#define _XS_MATCH_H
 7+
 8+/* spec is very similar to shell file globbing:
 9+   an * matches anything;
10+   a ? matches any character;
11+   | select alternative strings to match;
12+   a \\ escapes a special character;
13+   any other char matches itself. */
14+
15+int xs_match(const char *str, const char *spec);
16+
17+#ifdef XS_IMPLEMENTATION
18+
19+int xs_match(const char *str, const char *spec)
20+{
21+    const char *o_str = str;
22+
23+again:
24+    if (*spec == '*') {
25+        spec++;                 /* wildcard */
26+
27+        do {
28+            if (xs_match(str, spec))
29+                return 1;
30+            str++;
31+        } while (*str);
32+
33+        return 0;
34+    }
35+
36+    if (*spec == '?' && *str) {
37+        spec++;                 /* any character */
38+        str++;
39+        goto again;
40+    }
41+
42+    if (*spec == '|')
43+        return 1;               /* alternative separator? positive match */
44+
45+    if (!*spec)
46+        return 1;               /* end of spec? positive match */
47+
48+    if (*spec == '\\')
49+        spec++;                 /* escaped char */
50+
51+    if (*spec == *str) {
52+        spec++;                 /* matched 1 char */
53+        str++;
54+        goto again;
55+    }
56+
57+    /* not matched; are there any alternatives? */
58+    while (*spec) {
59+        if (*spec == '|')
60+            return xs_match(o_str, spec + 1);   /* try next alternative */
61+
62+        if (*spec == '\\')
63+            spec++;             /* escaped char */
64+        spec++;
65+    }
66+
67+    return 0;
68+}
69+
70+#endif /* XS_IMPLEMENTATION */
71+
72+#endif /* XS_MATCH_H */
+4, -4
 1@@ -6,8 +6,8 @@
 2 
 3 xs_list *xs_regex_split_n(const char *str, const char *rx, int count);
 4 #define xs_regex_split(str, rx) xs_regex_split_n(str, rx, XS_ALL)
 5-xs_list *xs_regex_match_n(const char *str, const char *rx, int count);
 6-#define xs_regex_match(str, rx) xs_regex_match_n(str, rx, XS_ALL)
 7+xs_list *xs_regex_select_n(const char *str, const char *rx, int count);
 8+#define xs_regex_select(str, rx) xs_regex_select_n(str, rx, XS_ALL)
 9 xs_list *xs_regex_replace_in(xs_str *str, const char *rx, const char *rep, int count);
10 #define xs_regex_replace_i(str, rx, rep) xs_regex_replace_in(str, rx, rep, XS_ALL)
11 #define xs_regex_replace_n(str, rx, rep, count) xs_regex_replace_in(xs_dup(str), rx, rep, count)
12@@ -55,8 +55,8 @@ xs_list *xs_regex_split_n(const char *str, const char *rx, int count)
13 }
14 
15 
16-xs_list *xs_regex_match_n(const char *str, const char *rx, int count)
17-/* returns a list with upto count matches */
18+xs_list *xs_regex_select_n(const char *str, const char *rx, int count)
19+/* selects all matches and return them as a list */
20 {
21     xs_list *list = xs_list_new();
22     xs *split = NULL;
+1, -1
1@@ -1 +1 @@
2-/* 0ca53ca2b1c34efa95639d2a0f5bf4bd32f8958c */
3+/* 06767a70773865042a70680aef50f7ecb077681a */