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