2.66 xs_match.h
 1/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
 2
 3#ifndef _XS_MATCH_H
 4
 5#define _XS_MATCH_H
 6
 7/* spec is very similar to shell file globbing:
 8   an * matches anything;
 9   a ? matches any character;
10   | select alternative strings to match;
11   a \\ escapes a special character;
12   any other char matches itself. */
13
14int xs_match(const char *str, const char *spec);
15
16#ifdef XS_IMPLEMENTATION
17
18int xs_match(const char *str, const char *spec)
19{
20    const char *b_str;
21    const char *b_spec = NULL;
22    const char *o_str  = str;
23
24retry:
25
26    for (;;) {
27        char c = *str++;
28        char p = *spec++;
29
30        if (c == '\0') {
31            /* end of string; also end of spec? */
32            if (p == '\0' || p == '|')
33                return 1;
34            else
35                break;
36        }
37        else
38        if (p == '?') {
39            /* match anything except the end */
40            if (c == '\0')
41                return 0;
42        }
43        else
44        if (p == '*') {
45            /* end of spec? match */
46            if (*spec == '\0')
47                return 1;
48
49            /* store spec for later */
50            b_spec = spec;
51
52            /* back one char */
53            b_str  = --str;
54        }
55        else {
56            if (p == '\\')
57                p = *spec++;
58
59            if (c != p) {
60                /* mismatch; do we have a backtrack? */
61                if (b_spec) {
62                    /* continue where we left, one char forward */
63                    spec = b_spec;
64                    str  = ++b_str;
65                }
66                else
67                    break;
68            }
69        }
70    }
71
72    /* try to find an alternative mark */
73    while (*spec) {
74        char p = *spec++;
75
76        if (p == '\\')
77            p = *spec++;
78
79        if (p == '|') {
80            /* no backtrack spec, restart str from the beginning */
81            b_spec = NULL;
82            str    = o_str;
83
84            goto retry;
85        }
86    }
87
88    return 0;
89}
90
91#endif /* XS_IMPLEMENTATION */
92
93#endif /* XS_MATCH_H */