1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13
14 // common goes first
15 #include "common.h"
16
17 // implementation header
18 #include "bzglob.h"
19
20 // system headers
21 #include <string>
22
23
24 static int match_multi (const char **pattern, const char **string);
25
26 static const char MATCH_MULTI = '*'; // matches any number of characters
27 static const char MATCH_SINGLE = '?'; // matches a single character
28
29
30 /******************************************************************************/
31
glob_match(const std::string & pattern,const std::string & string)32 bool glob_match (const std::string& pattern, const std::string& string)
33 {
34 return glob_match (pattern.c_str(), string.c_str());
35 }
36
37 /******************************************************************************/
38
glob_match(const char * pattern,const char * string)39 bool glob_match (const char *pattern, const char *string)
40 {
41 if (pattern == NULL)
42 return false;
43 if (string == NULL)
44 return false;
45
46 if ((pattern[0] == MATCH_MULTI) && (pattern[1] == '\0'))
47 return true;
48
49 while (*pattern != '\0')
50 {
51 if (*pattern == MATCH_MULTI)
52 {
53 pattern++;
54 switch (match_multi (&pattern, &string))
55 {
56 case +1:
57 {
58 return true;
59 }
60 case -1:
61 {
62 return false;
63 }
64 }
65 }
66 else if (*string == '\0')
67 return false;
68 else if ((*pattern == MATCH_SINGLE) || (*pattern == *string))
69 {
70 pattern++;
71 string++;
72 }
73 else
74 return false;
75 }
76
77 if (*string == '\0')
78 return true;
79 else
80 return false;
81 }
82
83 /******************************************************************************/
84
match_multi(const char ** pattern,const char ** string)85 static int match_multi (const char **pattern, const char **string)
86 {
87 const char *str = *pattern;
88 const char *obj = *string;
89
90 while ((*str != '\0') && (*str == MATCH_MULTI))
91 {
92 str++; // get rid of multiple '*'s
93 }
94
95 if (*str == '\0') // '*' was last, auto-match
96 return +1;
97
98 const char *strtop = str;
99 const char *objtop = obj;
100
101 while (*str != '\0')
102 {
103 if (*str == MATCH_MULTI)
104 {
105 *pattern = str;
106 *string = obj;
107 return 0; // matched this segment
108 }
109 else if (*obj == '\0')
110 {
111 return -1; // can't match
112 }
113 else
114 {
115 if ((*str == MATCH_SINGLE) || (*str == *obj))
116 {
117 str++;
118 obj++;
119 if ((*str == '\0') && (*obj != '\0')) // advanced check
120 {
121 obj++;
122 objtop++;
123 obj = objtop;
124 str = strtop;
125 }
126 }
127 else
128 {
129 obj++;
130 objtop++;
131 obj = objtop;
132 str = strtop;
133 }
134 }
135 }
136
137 *pattern = str;
138 *string = obj;
139
140 return +1; // full match
141 }
142
143
144 // Local Variables: ***
145 // mode: C++ ***
146 // tab-width: 4 ***
147 // c-basic-offset: 4 ***
148 // indent-tabs-mode: nil ***
149 // End: ***
150 // ex: shiftwidth=4 tabstop=4
151