xs_match.h (2166B)
1 /* copyright (c) 2022 - 2025 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 14 int xs_match(const char *str, const char *spec); 15 16 #ifdef XS_IMPLEMENTATION 17 18 int xs_match(const char *str, const char *spec) 19 { 20 const char *b_str = NULL; 21 const char *b_spec = NULL; 22 const char *o_str = str; 23 24 retry: 25 26 for (;;) { 27 const char *q = spec; 28 char c = *str++; 29 char p = *spec++; 30 31 if (c == '\0') { 32 /* end of string; also end of spec? */ 33 if (p == '\0' || p == '|') 34 return 1; 35 else 36 break; 37 } 38 else 39 if (p == '?') { 40 /* match anything except the end */ 41 if (c == '\0') 42 return 0; 43 } 44 else 45 if (p == '*') { 46 /* end of spec? match */ 47 if (*spec == '\0') 48 return 1; 49 50 /* store spec for later */ 51 b_spec = spec; 52 53 /* back one char */ 54 b_str = --str; 55 } 56 else { 57 if (p == '\\') 58 p = *spec++; 59 60 if (c != p) { 61 /* mismatch; do we have a backtrack? */ 62 if (b_spec) { 63 /* continue where we left, one char forward */ 64 spec = b_spec; 65 str = ++b_str; 66 } 67 else { 68 if (*q == '|') 69 spec = q; 70 71 break; 72 } 73 } 74 } 75 } 76 77 /* try to find an alternative mark */ 78 while (*spec) { 79 char p = *spec++; 80 81 if (p == '\\') 82 p = *spec++; 83 84 if (p == '|') { 85 /* no backtrack spec, restart str from the beginning */ 86 b_spec = NULL; 87 str = o_str; 88 89 goto retry; 90 } 91 } 92 93 return 0; 94 } 95 96 #endif /* XS_IMPLEMENTATION */ 97 98 #endif /* XS_MATCH_H */