1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/*
* This code would not have been possible without the prior work and
* suggestions of various sourced. Special thanks to Robey for
* all his time/help tracking down bugs and his ever-helpful advice.
*
* 04/09: Fixed the "*\*" against "*a" bug (caused an endless loop)
*
* Chris Fuller (aka Fred1@IRC & Fwitz@IRC)
* crf@cfox.bchs.uh.edu
*
* I hereby release this code into the public domain
*
*/
#include "lib.h"
#include "wildcard-match.h"
#include <ctype.h>
#define WILDS '*' /* matches 0 or more characters (including spaces) */
#define WILDQ '?' /* matches exactly one character */
#define NOMATCH 0
#define MATCH (match+sofar)
static int wildcard_match_int(const char *data, const char *mask, bool icase)
{
const char *ma = mask, *na = data, *lsm = NULL, *lsn = NULL;
int match = 1;
int sofar = 0;
if (na[0] == '\0') {
/* empty string can match only "*" wildcard(s) */
while (ma[0] == '*') ma++;
return ma[0] == '\0' ? MATCH : NOMATCH;
}
/* find the end of each string */
while (*(mask++) != '\0');
mask-=2;
while (*(data++) != '\0');
data-=2;
while (data >= na) {
/* If the mask runs out of chars before the string, fall back on
* a wildcard or fail. */
if (mask < ma) {
if (lsm != NULL) {
data = --lsn;
mask = lsm;
if (data < na)
lsm = NULL;
sofar = 0;
}
else
return NOMATCH;
}
switch (*mask) {
case WILDS: /* Matches anything */
do
mask--; /* Zap redundant wilds */
while ((mask >= ma) && (*mask == WILDS));
lsm = mask;
lsn = data;
match += sofar;
sofar = 0; /* Update fallback pos */
if (mask < ma)
return MATCH;
continue; /* Next char, please */
case WILDQ:
mask--;
data--;
continue; /* '?' always matches */
}
if (icase ? (i_toupper(*mask) == i_toupper(*data)) :
(*mask == *data)) { /* If matching char */
mask--;
data--;
sofar++; /* Tally the match */
continue; /* Next char, please */
}
if (lsm != NULL) { /* To to fallback on '*' */
data = --lsn;
mask = lsm;
if (data < na)
lsm = NULL; /* Rewind to saved pos */
sofar = 0;
continue; /* Next char, please */
}
return NOMATCH; /* No fallback=No match */
}
while ((mask >= ma) && (*mask == WILDS))
mask--; /* Zap leftover %s & *s */
return (mask >= ma) ? NOMATCH : MATCH; /* Start of both = match */
}
bool wildcard_match(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, FALSE) != 0;
}
bool wildcard_match_icase(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, TRUE) != 0;
}
|