]> git.saurik.com Git - wxWidgets.git/blob - src/common/glob.inc
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / glob.inc
1 /*
2 * File and other globbing (included by wb_utils.cc)
3 */
4
5 // This file includes:
6 // wxIsWild(const char *pattern)
7 // wxMatchWild(const char *pattern, const char *str, bool dot_special)
8 //
9
10
11 //---------------------------------------------------------------------------------
12 #ifndef UNIX_GLOB
13 # ifdef wx_x
14 # define UNIX_GLOB 1
15 # else
16 # define UNIX_GLOB 0
17 # endif
18 #endif
19
20 #if UNIX_GLOB
21 # ifdef wx_msw
22 # error "Can't use Unix file globbing under Windows!"
23 # endif
24 #endif
25
26 /*************************************************************************
27 *
28 * wxIsWild checks whether the pattern contains wildcards, and
29 * returns TRUE if it does, and FALSE if it does not (or if the
30 * pattern is NULL -- i.e. no string).
31 *
32 * The argument is:
33 *
34 * 1) pattern - a character string
35 */
36 bool
37 wxIsWild (const char *pattern)
38 {
39 while (*pattern)
40 {
41 switch (*pattern++)
42 {
43 case '?':
44 case '*':
45 #if UNIX_GLOB
46 case '[':
47 case '{': /* } */
48 #endif
49 return TRUE;
50 #if UNIX_GLOB
51 case '\\':
52 if (!*pattern++)
53 return FALSE;
54 #endif
55 } /* switch() */
56 } /* while() */
57 return FALSE;
58 }
59
60
61
62 #if UNIX_GLOB
63
64 // Unix Glob()
65 //
66 // Pattern Function
67 // -----------------------------------------------------
68 // '*' = match 0 or more occurances of anything
69 // "[abc]" = match anyof "abc" (ranges supported)
70 // "{xx,yy,zz}" = match anyof "xx", "yy", or "zz"
71 // '?' = match any character
72 //
73 // '\' is used to "escape" special characters
74 // Recursive
75
76 bool
77 wxMatchWild (const char *pattern, const char *str, bool dot_special)
78 {
79 char c;
80 const char *cp;
81 bool done = FALSE, ret_code, ok;
82 // Below is for vi fans
83 const char OB = '{', CB = '}';
84
85 #if 0
86 if (strcmp(pattern, "*.*") == 0)
87 pattern = "*"; // Hack for MS-DOS compat.
88 #endif
89
90 // dot_special means '.' only matches '.'
91 if (dot_special && *str == '.' && *pattern != *str)
92 return FALSE;
93
94 while ((*pattern != '\0') && (!done) && (((*str == '\0') &&
95 ((*pattern == OB) || (*pattern == '*'))) || (*str != '\0')))
96 {
97 switch (*pattern)
98 {
99 case '\\':
100 pattern++;
101 if (*pattern != '\0')
102 pattern++;
103 break;
104 case '*':
105 pattern++;
106 ret_code = FALSE;
107 while ((*str != '\0') && (!(ret_code = wxMatchWild (pattern, str++, FALSE))));
108 if (ret_code)
109 {
110 while (*str != '\0')
111 str++;
112 while (*pattern != '\0')
113 pattern++;
114 }
115 break;
116 case '[':
117 pattern++;
118 repeat:
119 if ((*pattern == '\0') || (*pattern == ']'))
120 {
121 done = TRUE;
122 break;
123 }
124 if (*pattern == '\\')
125 {
126 pattern++;
127 if (*pattern == '\0')
128 {
129 done = TRUE;
130 break;
131 }
132 }
133 if (*(pattern + 1) == '-')
134 {
135 c = *pattern;
136 pattern += 2;
137 if (*pattern == ']')
138 {
139 done = TRUE;
140 break;
141 }
142 if (*pattern == '\\')
143 {
144 pattern++;
145 if (*pattern == '\0')
146 {
147 done = TRUE;
148 break;
149 }
150 }
151 if ((*str < c) || (*str > *pattern))
152 {
153 pattern++;
154 goto repeat;
155 }
156 }
157 else if (*pattern != *str)
158 {
159 pattern++;
160 goto repeat;
161 }
162 pattern++;
163 while ((*pattern != ']') && (*pattern != '\0'))
164 {
165 if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
166 pattern++;
167 pattern++;
168 } // while()
169 if (*pattern != '\0')
170 {
171 pattern++, str++;
172 }
173 break;
174 case '?':
175 pattern++;
176 str++;
177 break;
178 case OB:
179 pattern++;
180 while ((*pattern != CB) && (*pattern != '\0'))
181 {
182 cp = str;
183 ok = TRUE;
184 while (ok && (*cp != '\0') && (*pattern != '\0') &&
185 (*pattern != ',') && (*pattern != CB))
186 {
187 if (*pattern == '\\')
188 pattern++;
189 ok = (*pattern++ == *cp++);
190 } // while()
191 if (*pattern == '\0')
192 {
193 ok = FALSE;
194 done = TRUE;
195 break;
196 }
197 else if (ok)
198 {
199 str = cp;
200 while ((*pattern != CB) && (*pattern != '\0'))
201 {
202 if (*++pattern == '\\')
203 {
204 if (*++pattern == CB)
205 pattern++;
206 }
207 } // while()
208 }
209 else
210 {
211 while (*pattern != CB && *pattern != ',' && *pattern != '\0')
212 {
213 if (*++pattern == '\\')
214 {
215 if (*++pattern == CB || *pattern == ',')
216 pattern++;
217 }
218 } // while()
219 }
220 if (*pattern != '\0')
221 pattern++;
222 } // while()
223 break;
224 default:
225 if (*str == *pattern)
226 {
227 str++, pattern++;
228 }
229 else
230 {
231 done = TRUE;
232 }
233 } // switch()
234 } // while()
235 while (*pattern == '*')
236 pattern++;
237 return ((*str == '\0') && (*pattern == '\0'));
238 }
239
240 #else /* MS-DOS/Windows glob() */
241 /*************************************************************************
242 *
243 * wxMatchWild matches the given pattern string against
244 * a text string, and returns TRUE if it matches, FALSE otherwise.
245 *
246 * A match means that the entire text string is used up in the matching.
247 * The pattern can contain the following wildcards.
248 *
249 * * -- matches any sequence of characters
250 * ? -- matches one character
251 *
252 * If one or other or both of the string arguments to wxMatchWild function is
253 * NULL (i.e. there isn't a string), then the function returns FALSE.
254 *
255 */
256 static bool wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j);
257
258 // @@@@ dotSpecial is ignored by MS-DOS
259 bool
260 wxMatchWild (const char *pattern, const char *text, bool /* dotSpecial */ )
261 {
262 if (pattern == NULL || text == NULL || *pattern == '\0' || *text == '\0')
263 return FALSE;
264 return wxPatternMatch (pattern, text, 0, 0);
265 }
266
267 /*************************************************************************
268 *
269 * wxPatternMatch does the work for wxMatchWild. wxPatternMatch matches
270 * the given pattern string against a text string, and returns TRUE if
271 * it matches, FALSE otherwise. It is assumed that the string arguments
272 * to wxPatternMatch exist.
273 *
274 * A match means that the entire text string is used up in the matching.
275 * The pattern can contain the following wildcards.
276 *
277 * * -- matches any sequence of characters
278 * ? -- matches one character
279 *
280 * wxPatternMatch works by going down the pattern trying to match the
281 * the same index character in the pattern and string arrays, and stops
282 * when the end of the pattern or text string is reached. However, if a
283 * '*' wildcard is met, the algorithm checks to see whether the remaining
284 * pattern (after the wildcard) matches the rest of the text (i.e. the
285 * wxPatternMatch function is called recursively).
286 */
287 // Recursive
288 static bool
289 wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j)
290 {
291 size_t pattern_length = strlen (pattern);
292 size_t text_length = strlen (text);
293 bool match = FALSE;
294
295 #ifdef wx_msw
296 // MS-DOS file system is case INDEPENDENT
297 # define EQU(x,y) (wxToLower(x) == wxToLower(y))
298 #else
299 # define EQU(x,y) ((x) == (y))
300 #endif
301
302 while (j < pattern_length && i < text_length)
303 {
304 if (EQU(text[i], pattern[j]) || pattern[j] == '?')
305 {
306 match = TRUE;
307 i++, j++;
308 }
309 else if (pattern[j] == '*')
310 {
311 // If pattern ends in '*'
312 if (++j == pattern_length)
313 {
314 match = TRUE;
315 i = text_length;
316 }
317 else
318 {
319 match = FALSE;
320 // after wildcard check to see whether rest of pattern matches
321 // up with rest of text
322 while (i < text_length && match != TRUE)
323 {
324 match = wxPatternMatch (pattern, text, i, j);
325 i++;
326 }
327 // text index is decremented so that it points to where
328 // the text string starts to match the rest of the pattern
329 i--;
330 }
331 }
332 else if (! EQU(text[i], pattern[j]))
333 {
334 j = pattern_length;
335 match = FALSE;
336 }
337 }
338 if (j == pattern_length && i == text_length && match == TRUE)
339 {
340 return TRUE;
341 }
342 else
343 // special case where pattern and text are the same except that pattern
344 // also only has '*' wildcards on the end
345 if (i == text_length && pattern[j] == '*' && match == TRUE)
346 {
347 for (; j < pattern_length; j++)
348 {
349 if (pattern[j] != '*')
350 return FALSE;
351 }
352 return TRUE;
353 }
354 else
355 {
356 return FALSE;
357 }
358 }
359
360 #endif /* UNIX_GLOB */
361 //-----------------------------------------------------------------------------