]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/pk3man/wild.cpp
* added pk3man and fixed it to compile for latest radiant
[xonotic/netradiant.git] / contrib / pk3man / wild.cpp
1 // Wild.cpp: implementation of the CWild class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "stdafx.h"
6 //#include "pakman.h"
7 #include "wild.h"
8
9 #ifdef _DEBUG
10 #undef THIS_FILE
11 static char THIS_FILE[]=__FILE__;
12 #define new DEBUG_NEW
13 #endif
14
15 //////////////////////////////////////////////////////////////////////
16 // Construction/Destruction
17 //////////////////////////////////////////////////////////////////////
18
19 CWild::CWild()
20 {
21
22 }
23
24 CWild::~CWild()
25 {
26
27 }
28
29 int CWild::fpattern_isvalid(const char *pat)
30 {
31         int             len;
32
33         /* Check args */
34         if (pat == NULL)
35                 return (FALSE);
36
37         /* Verify that the pattern is valid */
38         for (len = 0;  pat[len] != '\0';  len++)
39         {
40                 switch (pat[len])
41                 {
42                 case FPAT_SET_L:
43                         /* Char set */
44                         len++;
45                         if (pat[len] == FPAT_SET_NOT)
46                                 len++;                  /* Set negation */
47
48                         while (pat[len] != FPAT_SET_R)
49                         {
50                                 if (pat[len] == QUOTE)
51                                         len++;          /* Quoted char */
52                                 if (pat[len] == '\0')
53                                         return (FALSE); /* Missing closing bracket */
54                                 len++;
55
56                                 if (pat[len] == FPAT_SET_THRU)
57                                 {
58                                         /* Char range */
59                                         len++;
60                                         if (pat[len] == QUOTE)
61                                                 len++;          /* Quoted char */
62                                         if (pat[len] == '\0')
63                                                 return (FALSE); /* Missing closing bracket */
64                                         len++;
65                                 }
66
67                                 if (pat[len] == '\0')
68                                         return (FALSE); /* Missing closing bracket */
69                         }
70                         break;
71
72                 case QUOTE:
73                         /* Quoted char */
74                         len++;
75                         if (pat[len] == '\0')
76                                 return (FALSE);         /* Missing quoted char */
77                         break;
78
79                 case FPAT_NOT:
80                         /* Negated pattern */
81                         len++;
82                         if (pat[len] == '\0')
83                                 return (FALSE);         /* Missing subpattern */
84                         break;
85
86                 default:
87                         /* Valid character */
88                         break;
89                 }
90         }
91
92         return (TRUE);
93 }
94
95
96 int CWild::fpattern_submatch(const char *pat, const char *fname)
97 {
98         int             fch;
99         int             pch;
100         int             i;
101         int             yes, match;
102         int             lo, hi;
103
104         /* Attempt to match subpattern against subfilename */
105         while (*pat != '\0')
106         {
107                 fch = *fname;
108                 pch = *pat;
109                 pat++;
110
111                 switch (pch)
112                 {
113                 case FPAT_ANY:
114                         /* Match a single char */
115                         if (fch == DEL  ||  fch == DEL2  ||  fch == '\0')
116                                 return (FALSE);
117                         fname++;
118                         break;
119
120                 case FPAT_CLOS:
121                         /* Match zero or more chars */
122                         i = 0;
123                         while (fname[i] != '\0')//  && fname[i] != DEL  &&  fname[i] != DEL2)
124                                 i++;
125
126                         while (i >= 0)
127                         {
128                                 if (fpattern_submatch(pat, fname+i))
129                                         return (TRUE);
130                                 i--;
131                         }
132                         return (FALSE);
133
134                 case SUB:
135                         /* Match zero or more chars */
136                         i = 0;
137                         while (fname[i] != '\0'  && fname[i] != DEL  &&  fname[i] != DEL2  && fname[i] != '.')
138                                 i++;
139                         while (i >= 0)
140                         {
141                                 if (fpattern_submatch(pat, fname+i))
142                                         return (TRUE);
143                                 i--;
144                         }
145                         return (FALSE);
146
147                 case QUOTE:
148                         /* Match a quoted char */
149                         pch = *pat;
150                         if (lowercase(fch) != lowercase(pch)  ||  pch == '\0')
151                                 return (FALSE);
152                         fname++;
153                         pat++;
154                         break;
155
156                 case FPAT_SET_L:
157                         /* Match char set/range */
158                         yes = TRUE;
159                         if (*pat == FPAT_SET_NOT)
160                         {
161                         pat++;
162                         yes = FALSE;    /* Set negation */
163                         }
164
165                         /* Look for [s], [-], [abc], [a-c] */
166                         match = !yes;
167                         while (*pat != FPAT_SET_R  &&  *pat != '\0')
168                         {
169                                 if (*pat == QUOTE)
170                                         pat++;  /* Quoted char */
171
172                                 if (*pat == '\0')
173                                         break;
174                                 lo = *pat++;
175                                 hi = lo;
176
177                                 if (*pat == FPAT_SET_THRU)
178                                 {
179                                         /* Range */
180                                         pat++;
181
182                                         if (*pat == QUOTE)
183                                                 pat++;  /* Quoted char */
184
185                                         if (*pat == '\0')
186                                                 break;
187                                         hi = *pat++;
188                                 }
189
190                                 if (*pat == '\0')
191                                         break;
192
193                                 /* Compare character to set range */
194                                 if (lowercase(fch) >= lowercase(lo)  &&
195                                         lowercase(fch) <= lowercase(hi))
196                                         match = yes;
197                         }
198
199                         if (!match)
200                                 return (FALSE);
201
202                         if (*pat == '\0')
203                                 return (FALSE);         /* Missing closing bracket */
204
205                         fname++;
206                         pat++;
207                         break;
208
209                 case FPAT_NOT:
210                         /* Match only if rest of pattern does not match */
211                         if (*pat == '\0')
212                                 return (FALSE);         /* Missing subpattern */
213                         i = fpattern_submatch(pat, fname);
214                         return !i;
215
216
217                 case DEL:
218                 case DEL2:
219
220                         /* Match path delimiter char */
221                         if (fch != DEL  &&  fch != DEL2)
222                                 return (FALSE);
223                         fname++;
224                         break;
225
226                 default:
227                         /* Match a (non-null) char exactly */
228                         if (lowercase(fch) != lowercase(pch))
229                                 return (FALSE);
230                         fname++;
231                         break;
232                 }
233         }
234
235         /* Check for complete match */
236         if (*fname != '\0')
237                 return (FALSE);
238
239         /* Successful match */
240         return (TRUE);
241 }
242
243
244 /*-----------------------------------------------------------------------------
245 * fpattern_match()
246 *       Attempts to match pattern 'pat' to filename 'fname'.
247 *
248 * Returns
249 *       1 (true) if the filename matches, otherwise 0 (false).
250 *
251 * Caveats
252 *       If 'fname' is null, zero (false) is returned.
253 *
254 *       If 'pat' is null, zero (false) is returned.
255 *
256 *       If 'pat' is empty (""), the only filename it matches is the empty
257 *       string ("").
258 *
259 *       If 'fname' is empty, the only pattern that will match it is the empty
260 *       string ("").
261 *
262 *       If 'pat' is not a well-formed pattern, zero (false) is returned.
263 *
264 *       Upper and lower case letters are treated the same; alphabetic
265 *       characters are converted to lower case before matching occurs.
266 *       Conversion to lower case is dependent upon the current locale setting.
267 */
268
269 int CWild::fpattern_match(const char *pat, const char *fname)
270 {
271         int             rc;
272
273         /* Check args */
274         if (fname == NULL)
275                 return (FALSE);
276
277         if (pat == NULL)
278                 return (FALSE);
279
280         /* Verify that the pattern is valid, and get its length */
281         if (!fpattern_isvalid(pat))
282                 return (FALSE);
283
284         /* Attempt to match pattern against filename */
285         if (fname[0] == '\0')
286                 return (pat[0] == '\0');        /* Special case */
287         rc = fpattern_submatch(pat, fname);
288
289         return (rc);
290 }
291
292
293 /*-----------------------------------------------------------------------------
294 * fpattern_matchn()
295 *       Attempts to match pattern 'pat' to filename 'fname'.
296 *       This operates like fpattern_match() except that it does not verify that
297 *       pattern 'pat' is well-formed, assuming that it has been checked by a
298 *       prior call to fpattern_isvalid().
299 *
300 * Returns
301 *       1 (true) if the filename matches, otherwise 0 (false).
302 *
303 * Caveats
304 *       If 'fname' is null, zero (false) is returned.
305 *
306 *       If 'pat' is null, zero (false) is returned.
307 *
308 *       If 'pat' is empty (""), the only filename it matches is the empty ("")
309 *       string.
310 *
311 *       If 'pat' is not a well-formed pattern, unpredictable results may occur.
312 *
313 *       Upper and lower case letters are treated the same; alphabetic
314 *       characters are converted to lower case before matching occurs.
315 *       Conversion to lower case is dependent upon the current locale setting.
316 *
317 * See also
318 *       fpattern_match().
319 */
320
321 int CWild::fpattern_matchn(const char *pat, const char *fname)
322 {
323         int             rc;
324
325         /* Check args */
326         if (fname == NULL)
327                 return (FALSE);
328
329         if (pat == NULL)
330                 return (FALSE);
331
332         /* Assume that pattern is well-formed */
333
334         /* Attempt to match pattern against filename */
335         rc = fpattern_submatch(pat, fname);
336
337         return (rc);
338 }