NOW I do it right: #woxblox#
[divverent/netradiant.git] / libs / filematch.c
1 #include <string.h>
2 #include "filematch.h"
3
4 // LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
5
6 int matchpattern(const char *in, const char *pattern, int caseinsensitive)
7 {
8         return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", 0);
9 }
10
11 // wildcard_least_one: if true * matches 1 or more characters
12 //                     if false * matches 0 or more characters
13 int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, int wildcard_least_one)
14 {
15         int c1, c2;
16         while (*pattern)
17         {
18                 switch (*pattern)
19                 {
20                 case 0:
21                         return 1; // end of pattern
22                 case '?': // match any single character
23                         if (*in == 0 || strchr(separators, *in))
24                                 return 0; // no match
25                         in++;
26                         pattern++;
27                         break;
28                 case '*': // match anything until following string
29                         if(wildcard_least_one)
30                         {
31                                 if (*in == 0 || strchr(separators, *in))
32                                         return 0; // no match
33                                 in++;
34                         }
35                         pattern++;
36                         while (*in)
37                         {
38                                 if (strchr(separators, *in))
39                                         break;
40                                 // see if pattern matches at this offset
41                                 if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
42                                         return 1;
43                                 // nope, advance to next offset
44                                 in++;
45                         }
46                         break;
47                 default:
48                         if (*in != *pattern)
49                         {
50                                 if (!caseinsensitive)
51                                         return 0; // no match
52                                 c1 = *in;
53                                 if (c1 >= 'A' && c1 <= 'Z')
54                                         c1 += 'a' - 'A';
55                                 c2 = *pattern;
56                                 if (c2 >= 'A' && c2 <= 'Z')
57                                         c2 += 'a' - 'A';
58                                 if (c1 != c2)
59                                         return 0; // no match
60                         }
61                         in++;
62                         pattern++;
63                         break;
64                 }
65         }
66         if (*in)
67                 return 0; // reached end of pattern but not end of input
68         return 1; // success
69 }