From 952da47c6d2a209e6a41fabe7a5365380d63a5e5 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 17 Sep 2023 02:52:44 +0200 Subject: Backport from xs. --- xs_match.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 xs_match.h (limited to 'xs_match.h') diff --git a/xs_match.h b/xs_match.h new file mode 100644 index 0000000..9f12c15 --- /dev/null +++ b/xs_match.h @@ -0,0 +1,71 @@ +/* copyright (c) 2022 - 2023 grunfink et al. / MIT license */ + +#ifndef _XS_MATCH_H + +#define _XS_MATCH_H + +/* spec is very similar to shell file globbing: + an * matches anything; + a ? matches any character; + | select alternative strings to match; + a \\ escapes a special character; + any other char matches itself. */ + +int xs_match(const char *str, const char *spec); + +#ifdef XS_IMPLEMENTATION + +int xs_match(const char *str, const char *spec) +{ + const char *o_str = str; + +again: + if (*spec == '*') { + spec++; /* wildcard */ + + do { + if (xs_match(str, spec)) + return 1; + str++; + } while (*str); + + return 0; + } + + if (*spec == '?' && *str) { + spec++; /* any character */ + str++; + goto again; + } + + if (*spec == '|') + return 1; /* alternative separator? positive match */ + + if (!*spec) + return 1; /* end of spec? positive match */ + + if (*spec == '\\') + spec++; /* escaped char */ + + if (*spec == *str) { + spec++; /* matched 1 char */ + str++; + goto again; + } + + /* not matched; are there any alternatives? */ + while (*spec) { + if (*spec == '|') + return xs_match(o_str, spec + 1); /* try next alternative */ + + if (*spec == '\\') + spec++; /* escaped char */ + spec++; + } + + return 0; +} + +#endif /* XS_IMPLEMENTATION */ + +#endif /* XS_MATCH_H */ -- cgit v1.2.3