/src/mozilla-central/xpcom/io/nsWildCard.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* * |
8 | | * |
9 | | * |
10 | | * nsWildCard.cpp: shell-like wildcard match routines |
11 | | * |
12 | | * See nsIZipReader.findEntries documentation in nsIZipReader.idl for |
13 | | * a description of the syntax supported by the routines in this file. |
14 | | * |
15 | | * Rob McCool |
16 | | * |
17 | | */ |
18 | | |
19 | | #include "nsWildCard.h" |
20 | | #include "nsXPCOM.h" |
21 | | #include "nsCRTGlue.h" |
22 | | #include "nsCharTraits.h" |
23 | | |
24 | | /* -------------------- ASCII-specific character methods ------------------- */ |
25 | | |
26 | | typedef int static_assert_character_code_arrangement['a' > 'A' ? 1 : -1]; |
27 | | |
28 | | template<class T> |
29 | | static int |
30 | | alpha(T aChar) |
31 | 0 | { |
32 | 0 | return ('a' <= aChar && aChar <= 'z') || |
33 | 0 | ('A' <= aChar && aChar <= 'Z'); |
34 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int alpha<char>(char) Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int alpha<char16_t>(char16_t) |
35 | | |
36 | | template<class T> |
37 | | static int |
38 | | alphanumeric(T aChar) |
39 | 0 | { |
40 | 0 | return ('0' <= aChar && aChar <= '9') || ::alpha(aChar); |
41 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int alphanumeric<char>(char) Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int alphanumeric<char16_t>(char16_t) |
42 | | |
43 | | template<class T> |
44 | | static int |
45 | | lower(T aChar) |
46 | 0 | { |
47 | 0 | return ('A' <= aChar && aChar <= 'Z') ? aChar + ('a' - 'A') : aChar; |
48 | 0 | } |
49 | | |
50 | | template<class T> |
51 | | static int |
52 | | upper(T aChar) |
53 | 0 | { |
54 | 0 | return ('a' <= aChar && aChar <= 'z') ? aChar - ('a' - 'A') : aChar; |
55 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int upper<char>(char) Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int upper<char16_t>(char16_t) |
56 | | |
57 | | /* ----------------------------- _valid_subexp ---------------------------- */ |
58 | | |
59 | | template<class T> |
60 | | static int |
61 | | _valid_subexp(const T* aExpr, T aStop1, T aStop2) |
62 | 8.48k | { |
63 | 8.48k | int x; |
64 | 8.48k | int nsc = 0; /* Number of special characters */ |
65 | 8.48k | int np; /* Number of pipe characters in union */ |
66 | 8.48k | int tld = 0; /* Number of tilde characters */ |
67 | 8.48k | |
68 | 199k | for (x = 0; aExpr[x] && (aExpr[x] != aStop1) && (aExpr[x] != aStop2); ++x) { |
69 | 190k | switch (aExpr[x]) { |
70 | 190k | case '~': |
71 | 0 | if (tld) { /* at most one exclusion */ |
72 | 0 | return INVALID_SXP; |
73 | 0 | } |
74 | 0 | if (aStop1) { /* no exclusions within unions */ |
75 | 0 | return INVALID_SXP; |
76 | 0 | } |
77 | 0 | if (!aExpr[x + 1]) { /* exclusion cannot be last character */ |
78 | 0 | return INVALID_SXP; |
79 | 0 | } |
80 | 0 | if (!x) { /* exclusion cannot be first character */ |
81 | 0 | return INVALID_SXP; |
82 | 0 | } |
83 | 0 | ++tld; |
84 | 0 | MOZ_FALLTHROUGH; |
85 | 16.9k | case '*': |
86 | 16.9k | case '?': |
87 | 16.9k | case '$': |
88 | 16.9k | ++nsc; |
89 | 16.9k | break; |
90 | 16.9k | case '[': |
91 | 0 | ++nsc; |
92 | 0 | if ((!aExpr[++x]) || (aExpr[x] == ']')) { |
93 | 0 | return INVALID_SXP; |
94 | 0 | } |
95 | 0 | for (; aExpr[x] && (aExpr[x] != ']'); ++x) { |
96 | 0 | if (aExpr[x] == '\\' && !aExpr[++x]) { |
97 | 0 | return INVALID_SXP; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | if (!aExpr[x]) { |
101 | 0 | return INVALID_SXP; |
102 | 0 | } |
103 | 0 | break; |
104 | 0 | case '(': |
105 | 0 | ++nsc; |
106 | 0 | if (aStop1) { /* no nested unions */ |
107 | 0 | return INVALID_SXP; |
108 | 0 | } |
109 | 0 | np = -1; |
110 | 0 | do { |
111 | 0 | int t = ::_valid_subexp(&aExpr[++x], T(')'), T('|')); |
112 | 0 | if (t == 0 || t == INVALID_SXP) { |
113 | 0 | return INVALID_SXP; |
114 | 0 | } |
115 | 0 | x += t; |
116 | 0 | if (!aExpr[x]) { |
117 | 0 | return INVALID_SXP; |
118 | 0 | } |
119 | 0 | ++np; |
120 | 0 | } while (aExpr[x] == '|'); |
121 | 0 | if (np < 1) { /* must be at least one pipe */ |
122 | 0 | return INVALID_SXP; |
123 | 0 | } |
124 | 0 | break; |
125 | 0 | case ')': |
126 | 0 | case ']': |
127 | 0 | case '|': |
128 | 0 | return INVALID_SXP; |
129 | 0 | case '\\': |
130 | 0 | ++nsc; |
131 | 0 | if (!aExpr[++x]) { |
132 | 0 | return INVALID_SXP; |
133 | 0 | } |
134 | 0 | break; |
135 | 173k | default: |
136 | 173k | break; |
137 | 190k | } |
138 | 190k | } |
139 | 8.48k | if (!aStop1 && !nsc) { /* must be at least one special character */ |
140 | 0 | return NON_SXP; |
141 | 0 | } |
142 | 8.48k | return ((aExpr[x] == aStop1 || aExpr[x] == aStop2) ? x : INVALID_SXP); |
143 | 8.48k | } Unified_cpp_xpcom_io1.cpp:int _valid_subexp<char>(char const*, char, char) Line | Count | Source | 62 | 8.48k | { | 63 | 8.48k | int x; | 64 | 8.48k | int nsc = 0; /* Number of special characters */ | 65 | 8.48k | int np; /* Number of pipe characters in union */ | 66 | 8.48k | int tld = 0; /* Number of tilde characters */ | 67 | 8.48k | | 68 | 199k | for (x = 0; aExpr[x] && (aExpr[x] != aStop1) && (aExpr[x] != aStop2); ++x) { | 69 | 190k | switch (aExpr[x]) { | 70 | 190k | case '~': | 71 | 0 | if (tld) { /* at most one exclusion */ | 72 | 0 | return INVALID_SXP; | 73 | 0 | } | 74 | 0 | if (aStop1) { /* no exclusions within unions */ | 75 | 0 | return INVALID_SXP; | 76 | 0 | } | 77 | 0 | if (!aExpr[x + 1]) { /* exclusion cannot be last character */ | 78 | 0 | return INVALID_SXP; | 79 | 0 | } | 80 | 0 | if (!x) { /* exclusion cannot be first character */ | 81 | 0 | return INVALID_SXP; | 82 | 0 | } | 83 | 0 | ++tld; | 84 | 0 | MOZ_FALLTHROUGH; | 85 | 16.9k | case '*': | 86 | 16.9k | case '?': | 87 | 16.9k | case '$': | 88 | 16.9k | ++nsc; | 89 | 16.9k | break; | 90 | 16.9k | case '[': | 91 | 0 | ++nsc; | 92 | 0 | if ((!aExpr[++x]) || (aExpr[x] == ']')) { | 93 | 0 | return INVALID_SXP; | 94 | 0 | } | 95 | 0 | for (; aExpr[x] && (aExpr[x] != ']'); ++x) { | 96 | 0 | if (aExpr[x] == '\\' && !aExpr[++x]) { | 97 | 0 | return INVALID_SXP; | 98 | 0 | } | 99 | 0 | } | 100 | 0 | if (!aExpr[x]) { | 101 | 0 | return INVALID_SXP; | 102 | 0 | } | 103 | 0 | break; | 104 | 0 | case '(': | 105 | 0 | ++nsc; | 106 | 0 | if (aStop1) { /* no nested unions */ | 107 | 0 | return INVALID_SXP; | 108 | 0 | } | 109 | 0 | np = -1; | 110 | 0 | do { | 111 | 0 | int t = ::_valid_subexp(&aExpr[++x], T(')'), T('|')); | 112 | 0 | if (t == 0 || t == INVALID_SXP) { | 113 | 0 | return INVALID_SXP; | 114 | 0 | } | 115 | 0 | x += t; | 116 | 0 | if (!aExpr[x]) { | 117 | 0 | return INVALID_SXP; | 118 | 0 | } | 119 | 0 | ++np; | 120 | 0 | } while (aExpr[x] == '|'); | 121 | 0 | if (np < 1) { /* must be at least one pipe */ | 122 | 0 | return INVALID_SXP; | 123 | 0 | } | 124 | 0 | break; | 125 | 0 | case ')': | 126 | 0 | case ']': | 127 | 0 | case '|': | 128 | 0 | return INVALID_SXP; | 129 | 0 | case '\\': | 130 | 0 | ++nsc; | 131 | 0 | if (!aExpr[++x]) { | 132 | 0 | return INVALID_SXP; | 133 | 0 | } | 134 | 0 | break; | 135 | 173k | default: | 136 | 173k | break; | 137 | 190k | } | 138 | 190k | } | 139 | 8.48k | if (!aStop1 && !nsc) { /* must be at least one special character */ | 140 | 0 | return NON_SXP; | 141 | 0 | } | 142 | 8.48k | return ((aExpr[x] == aStop1 || aExpr[x] == aStop2) ? x : INVALID_SXP); | 143 | 8.48k | } |
Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _valid_subexp<char16_t>(char16_t const*, char16_t, char16_t) |
144 | | |
145 | | |
146 | | template<class T> |
147 | | int |
148 | | NS_WildCardValid_(const T* aExpr) |
149 | 8.48k | { |
150 | 8.48k | int x = ::_valid_subexp(aExpr, T('\0'), T('\0')); |
151 | 8.48k | return (x < 0 ? x : VALID_SXP); |
152 | 8.48k | } int NS_WildCardValid_<char>(char const*) Line | Count | Source | 149 | 8.48k | { | 150 | 8.48k | int x = ::_valid_subexp(aExpr, T('\0'), T('\0')); | 151 | 8.48k | return (x < 0 ? x : VALID_SXP); | 152 | 8.48k | } |
Unexecuted instantiation: int NS_WildCardValid_<char16_t>(char16_t const*) |
153 | | |
154 | | int |
155 | | NS_WildCardValid(const char* aExpr) |
156 | 8.48k | { |
157 | 8.48k | return NS_WildCardValid_(aExpr); |
158 | 8.48k | } |
159 | | |
160 | | int |
161 | | NS_WildCardValid(const char16_t* aExpr) |
162 | 0 | { |
163 | 0 | return NS_WildCardValid_(aExpr); |
164 | 0 | } |
165 | | |
166 | | /* ----------------------------- _shexp_match ----------------------------- */ |
167 | | |
168 | | |
169 | 8.49k | #define MATCH 0 |
170 | 8.61k | #define NOMATCH 1 |
171 | 0 | #define ABORTED -1 |
172 | | |
173 | | template<class T> |
174 | | static int |
175 | | _shexp_match(const T* aStr, const T* aExpr, bool aCaseInsensitive, |
176 | | unsigned int aLevel); |
177 | | |
178 | | /** |
179 | | * Count characters until we reach a NUL character or either of the |
180 | | * two delimiter characters, stop1 or stop2. If we encounter a bracketed |
181 | | * expression, look only for NUL or ']' inside it. Do not look for stop1 |
182 | | * or stop2 inside it. Return ABORTED if bracketed expression is unterminated. |
183 | | * Handle all escaping. |
184 | | * Return index in input string of first stop found, or ABORTED if not found. |
185 | | * If "dest" is non-nullptr, copy counted characters to it and null terminate. |
186 | | */ |
187 | | template<class T> |
188 | | static int |
189 | | _scan_and_copy(const T* aExpr, T aStop1, T aStop2, T* aDest) |
190 | 0 | { |
191 | 0 | int sx; /* source index */ |
192 | 0 | T cc; |
193 | 0 |
|
194 | 0 | for (sx = 0; (cc = aExpr[sx]) && cc != aStop1 && cc != aStop2; ++sx) { |
195 | 0 | if (cc == '\\') { |
196 | 0 | if (!aExpr[++sx]) { |
197 | 0 | return ABORTED; /* should be impossible */ |
198 | 0 | } |
199 | 0 | } else if (cc == '[') { |
200 | 0 | while ((cc = aExpr[++sx]) && cc != ']') { |
201 | 0 | if (cc == '\\' && !aExpr[++sx]) { |
202 | 0 | return ABORTED; |
203 | 0 | } |
204 | 0 | } |
205 | 0 | if (!cc) { |
206 | 0 | return ABORTED; /* should be impossible */ |
207 | 0 | } |
208 | 0 | } |
209 | 0 | } |
210 | 0 | if (aDest && sx) { |
211 | 0 | /* Copy all but the closing delimiter. */ |
212 | 0 | memcpy(aDest, aExpr, sx * sizeof(T)); |
213 | 0 | aDest[sx] = 0; |
214 | 0 | } |
215 | 0 | return cc ? sx : ABORTED; /* index of closing delimiter */ |
216 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _scan_and_copy<char>(char const*, char, char, char*) Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _scan_and_copy<char16_t>(char16_t const*, char16_t, char16_t, char16_t*) |
217 | | |
218 | | /* On input, expr[0] is the opening parenthesis of a union. |
219 | | * See if any of the alternatives in the union matches as a pattern. |
220 | | * The strategy is to take each of the alternatives, in turn, and append |
221 | | * the rest of the expression (after the closing ')' that marks the end of |
222 | | * this union) to that alternative, and then see if the resultant expression |
223 | | * matches the input string. Repeat this until some alternative matches, |
224 | | * or we have an abort. |
225 | | */ |
226 | | template<class T> |
227 | | static int |
228 | | _handle_union(const T* aStr, const T* aExpr, bool aCaseInsensitive, |
229 | | unsigned int aLevel) |
230 | 0 | { |
231 | 0 | int sx; /* source index */ |
232 | 0 | int cp; /* source index of closing parenthesis */ |
233 | 0 | int count; |
234 | 0 | int ret = NOMATCH; |
235 | 0 | T* e2; |
236 | 0 |
|
237 | 0 | /* Find the closing parenthesis that ends this union in the expression */ |
238 | 0 | cp = ::_scan_and_copy(aExpr, T(')'), T('\0'), static_cast<T*>(nullptr)); |
239 | 0 | if (cp == ABORTED || cp < 4) { /* must be at least "(a|b" before ')' */ |
240 | 0 | return ABORTED; |
241 | 0 | } |
242 | 0 | ++cp; /* now index of char after closing parenthesis */ |
243 | 0 | e2 = (T*)moz_xmalloc((1 + nsCharTraits<T>::length(aExpr)) * sizeof(T)); |
244 | 0 | for (sx = 1; ; ++sx) { |
245 | 0 | /* Here, aExpr[sx] is one character past the preceding '(' or '|'. */ |
246 | 0 | /* Copy everything up to the next delimiter to e2 */ |
247 | 0 | count = ::_scan_and_copy(aExpr + sx, T(')'), T('|'), e2); |
248 | 0 | if (count == ABORTED || !count) { |
249 | 0 | ret = ABORTED; |
250 | 0 | break; |
251 | 0 | } |
252 | 0 | sx += count; |
253 | 0 | /* Append everything after closing parenthesis to e2. This is safe. */ |
254 | 0 | nsCharTraits<T>::copy(e2 + count, aExpr + cp, |
255 | 0 | nsCharTraits<T>::length(aExpr + cp) + 1); |
256 | 0 | ret = ::_shexp_match(aStr, e2, aCaseInsensitive, aLevel + 1); |
257 | 0 | if (ret != NOMATCH || !aExpr[sx] || aExpr[sx] == ')') { |
258 | 0 | break; |
259 | 0 | } |
260 | 0 | } |
261 | 0 | free(e2); |
262 | 0 | if (sx < 2) { |
263 | 0 | ret = ABORTED; |
264 | 0 | } |
265 | 0 | return ret; |
266 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _handle_union<char>(char const*, char const*, bool, unsigned int) Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _handle_union<char16_t>(char16_t const*, char16_t const*, bool, unsigned int) |
267 | | |
268 | | /* returns 1 if val is in range from start..end, case insensitive. */ |
269 | | static int |
270 | | _is_char_in_range(unsigned char aStart, unsigned char aEnd, unsigned char aVal) |
271 | 0 | { |
272 | 0 | char map[256]; |
273 | 0 | memset(map, 0, sizeof(map)); |
274 | 0 | while (aStart <= aEnd) { |
275 | 0 | map[lower(aStart++)] = 1; |
276 | 0 | } |
277 | 0 | return map[lower(aVal)]; |
278 | 0 | } |
279 | | |
280 | | template<class T> |
281 | | static int |
282 | | _shexp_match(const T* aStr, const T* aExpr, bool aCaseInsensitive, |
283 | | unsigned int aLevel) |
284 | 8.55k | { |
285 | 8.55k | int x; /* input string index */ |
286 | 8.55k | int y; /* expression index */ |
287 | 8.55k | int ret, neg; |
288 | 8.55k | |
289 | 8.55k | if (aLevel > 20) { /* Don't let the stack get too deep. */ |
290 | 0 | return ABORTED; |
291 | 0 | } |
292 | 9.00k | for (x = 0, y = 0; aExpr[y]; ++y, ++x) { |
293 | 8.99k | if (!aStr[x] && aExpr[y] != '$' && aExpr[y] != '*') { |
294 | 6 | return NOMATCH; |
295 | 6 | } |
296 | 8.98k | switch (aExpr[y]) { |
297 | 8.98k | case '$': |
298 | 6 | if (aStr[x]) { |
299 | 0 | return NOMATCH; |
300 | 0 | } |
301 | 6 | --x; /* we don't want loop to increment x */ |
302 | 6 | break; |
303 | 9 | case '*': |
304 | 9 | while (aExpr[++y] == '*') { |
305 | 0 | } |
306 | 9 | if (!aExpr[y]) { |
307 | 0 | return MATCH; |
308 | 0 | } |
309 | 78 | while (aStr[x]) { |
310 | 75 | ret = ::_shexp_match(&aStr[x++], &aExpr[y], aCaseInsensitive, |
311 | 75 | aLevel + 1); |
312 | 75 | switch (ret) { |
313 | 75 | case NOMATCH: |
314 | 69 | continue; |
315 | 75 | case ABORTED: |
316 | 0 | return ABORTED; |
317 | 75 | default: |
318 | 6 | return MATCH; |
319 | 75 | } |
320 | 75 | } |
321 | 9 | if (aExpr[y] == '$' && aExpr[y + 1] == '\0' && !aStr[x]) { |
322 | 0 | return MATCH; |
323 | 3 | } else { |
324 | 3 | return NOMATCH; |
325 | 3 | } |
326 | 0 | case '[': { |
327 | 0 | T start, end = 0; |
328 | 0 | int i; |
329 | 0 | ++y; |
330 | 0 | neg = (aExpr[y] == '^' && aExpr[y + 1] != ']'); |
331 | 0 | if (neg) { |
332 | 0 | ++y; |
333 | 0 | } |
334 | 0 | i = y; |
335 | 0 | start = aExpr[i++]; |
336 | 0 | if (start == '\\') { |
337 | 0 | start = aExpr[i++]; |
338 | 0 | } |
339 | 0 | if (::alphanumeric(start) && aExpr[i++] == '-') { |
340 | 0 | end = aExpr[i++]; |
341 | 0 | if (end == '\\') { |
342 | 0 | end = aExpr[i++]; |
343 | 0 | } |
344 | 0 | } |
345 | 0 | if (::alphanumeric(end) && aExpr[i] == ']') { |
346 | 0 | /* This is a range form: a-b */ |
347 | 0 | T val = aStr[x]; |
348 | 0 | if (end < start) { /* swap them */ |
349 | 0 | T tmp = end; |
350 | 0 | end = start; |
351 | 0 | start = tmp; |
352 | 0 | } |
353 | 0 | if (aCaseInsensitive && ::alpha(val)) { |
354 | 0 | val = ::_is_char_in_range((unsigned char)start, |
355 | 0 | (unsigned char)end, |
356 | 0 | (unsigned char)val); |
357 | 0 | if (neg == val) { |
358 | 0 | return NOMATCH; |
359 | 0 | } |
360 | 0 | } else if (neg != (val < start || val > end)) { |
361 | 0 | return NOMATCH; |
362 | 0 | } |
363 | 0 | y = i; |
364 | 0 | } else { |
365 | 0 | /* Not range form */ |
366 | 0 | int matched = 0; |
367 | 0 | for (; aExpr[y] != ']'; ++y) { |
368 | 0 | if (aExpr[y] == '\\') { |
369 | 0 | ++y; |
370 | 0 | } |
371 | 0 | if (aCaseInsensitive) { |
372 | 0 | matched |= (::upper(aStr[x]) == ::upper(aExpr[y])); |
373 | 0 | } else { |
374 | 0 | matched |= (aStr[x] == aExpr[y]); |
375 | 0 | } |
376 | 0 | } |
377 | 0 | if (neg == matched) { |
378 | 0 | return NOMATCH; |
379 | 0 | } |
380 | 0 | } |
381 | 0 | } |
382 | 0 | break; |
383 | 0 | case '(': |
384 | 0 | if (!aExpr[y + 1]) { |
385 | 0 | return ABORTED; |
386 | 0 | } |
387 | 0 | return ::_handle_union(&aStr[x], &aExpr[y], aCaseInsensitive, |
388 | 0 | aLevel + 1); |
389 | 0 | case '?': |
390 | 0 | break; |
391 | 0 | case ')': |
392 | 0 | case ']': |
393 | 0 | case '|': |
394 | 0 | return ABORTED; |
395 | 0 | case '\\': |
396 | 0 | ++y; |
397 | 0 | MOZ_FALLTHROUGH; |
398 | 8.97k | default: |
399 | 8.97k | if (aCaseInsensitive) { |
400 | 0 | if (::upper(aStr[x]) != ::upper(aExpr[y])) { |
401 | 0 | return NOMATCH; |
402 | 0 | } |
403 | 8.97k | } else { |
404 | 8.97k | if (aStr[x] != aExpr[y]) { |
405 | 8.53k | return NOMATCH; |
406 | 8.53k | } |
407 | 441 | } |
408 | 441 | break; |
409 | 8.98k | } |
410 | 8.98k | } |
411 | 8.55k | return (aStr[x] ? NOMATCH : MATCH); |
412 | 8.55k | } Unified_cpp_xpcom_io1.cpp:int _shexp_match<char>(char const*, char const*, bool, unsigned int) Line | Count | Source | 284 | 8.55k | { | 285 | 8.55k | int x; /* input string index */ | 286 | 8.55k | int y; /* expression index */ | 287 | 8.55k | int ret, neg; | 288 | 8.55k | | 289 | 8.55k | if (aLevel > 20) { /* Don't let the stack get too deep. */ | 290 | 0 | return ABORTED; | 291 | 0 | } | 292 | 9.00k | for (x = 0, y = 0; aExpr[y]; ++y, ++x) { | 293 | 8.99k | if (!aStr[x] && aExpr[y] != '$' && aExpr[y] != '*') { | 294 | 6 | return NOMATCH; | 295 | 6 | } | 296 | 8.98k | switch (aExpr[y]) { | 297 | 8.98k | case '$': | 298 | 6 | if (aStr[x]) { | 299 | 0 | return NOMATCH; | 300 | 0 | } | 301 | 6 | --x; /* we don't want loop to increment x */ | 302 | 6 | break; | 303 | 9 | case '*': | 304 | 9 | while (aExpr[++y] == '*') { | 305 | 0 | } | 306 | 9 | if (!aExpr[y]) { | 307 | 0 | return MATCH; | 308 | 0 | } | 309 | 78 | while (aStr[x]) { | 310 | 75 | ret = ::_shexp_match(&aStr[x++], &aExpr[y], aCaseInsensitive, | 311 | 75 | aLevel + 1); | 312 | 75 | switch (ret) { | 313 | 75 | case NOMATCH: | 314 | 69 | continue; | 315 | 75 | case ABORTED: | 316 | 0 | return ABORTED; | 317 | 75 | default: | 318 | 6 | return MATCH; | 319 | 75 | } | 320 | 75 | } | 321 | 9 | if (aExpr[y] == '$' && aExpr[y + 1] == '\0' && !aStr[x]) { | 322 | 0 | return MATCH; | 323 | 3 | } else { | 324 | 3 | return NOMATCH; | 325 | 3 | } | 326 | 0 | case '[': { | 327 | 0 | T start, end = 0; | 328 | 0 | int i; | 329 | 0 | ++y; | 330 | 0 | neg = (aExpr[y] == '^' && aExpr[y + 1] != ']'); | 331 | 0 | if (neg) { | 332 | 0 | ++y; | 333 | 0 | } | 334 | 0 | i = y; | 335 | 0 | start = aExpr[i++]; | 336 | 0 | if (start == '\\') { | 337 | 0 | start = aExpr[i++]; | 338 | 0 | } | 339 | 0 | if (::alphanumeric(start) && aExpr[i++] == '-') { | 340 | 0 | end = aExpr[i++]; | 341 | 0 | if (end == '\\') { | 342 | 0 | end = aExpr[i++]; | 343 | 0 | } | 344 | 0 | } | 345 | 0 | if (::alphanumeric(end) && aExpr[i] == ']') { | 346 | 0 | /* This is a range form: a-b */ | 347 | 0 | T val = aStr[x]; | 348 | 0 | if (end < start) { /* swap them */ | 349 | 0 | T tmp = end; | 350 | 0 | end = start; | 351 | 0 | start = tmp; | 352 | 0 | } | 353 | 0 | if (aCaseInsensitive && ::alpha(val)) { | 354 | 0 | val = ::_is_char_in_range((unsigned char)start, | 355 | 0 | (unsigned char)end, | 356 | 0 | (unsigned char)val); | 357 | 0 | if (neg == val) { | 358 | 0 | return NOMATCH; | 359 | 0 | } | 360 | 0 | } else if (neg != (val < start || val > end)) { | 361 | 0 | return NOMATCH; | 362 | 0 | } | 363 | 0 | y = i; | 364 | 0 | } else { | 365 | 0 | /* Not range form */ | 366 | 0 | int matched = 0; | 367 | 0 | for (; aExpr[y] != ']'; ++y) { | 368 | 0 | if (aExpr[y] == '\\') { | 369 | 0 | ++y; | 370 | 0 | } | 371 | 0 | if (aCaseInsensitive) { | 372 | 0 | matched |= (::upper(aStr[x]) == ::upper(aExpr[y])); | 373 | 0 | } else { | 374 | 0 | matched |= (aStr[x] == aExpr[y]); | 375 | 0 | } | 376 | 0 | } | 377 | 0 | if (neg == matched) { | 378 | 0 | return NOMATCH; | 379 | 0 | } | 380 | 0 | } | 381 | 0 | } | 382 | 0 | break; | 383 | 0 | case '(': | 384 | 0 | if (!aExpr[y + 1]) { | 385 | 0 | return ABORTED; | 386 | 0 | } | 387 | 0 | return ::_handle_union(&aStr[x], &aExpr[y], aCaseInsensitive, | 388 | 0 | aLevel + 1); | 389 | 0 | case '?': | 390 | 0 | break; | 391 | 0 | case ')': | 392 | 0 | case ']': | 393 | 0 | case '|': | 394 | 0 | return ABORTED; | 395 | 0 | case '\\': | 396 | 0 | ++y; | 397 | 0 | MOZ_FALLTHROUGH; | 398 | 8.97k | default: | 399 | 8.97k | if (aCaseInsensitive) { | 400 | 0 | if (::upper(aStr[x]) != ::upper(aExpr[y])) { | 401 | 0 | return NOMATCH; | 402 | 0 | } | 403 | 8.97k | } else { | 404 | 8.97k | if (aStr[x] != aExpr[y]) { | 405 | 8.53k | return NOMATCH; | 406 | 8.53k | } | 407 | 441 | } | 408 | 441 | break; | 409 | 8.98k | } | 410 | 8.98k | } | 411 | 8.55k | return (aStr[x] ? NOMATCH : MATCH); | 412 | 8.55k | } |
Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int _shexp_match<char16_t>(char16_t const*, char16_t const*, bool, unsigned int) |
413 | | |
414 | | template<class T> |
415 | | static int |
416 | | ns_WildCardMatch(const T* aStr, const T* aXp, bool aCaseInsensitive) |
417 | 8.47k | { |
418 | 8.47k | T* expr = nullptr; |
419 | 8.47k | int ret = MATCH; |
420 | 8.47k | |
421 | 8.47k | if (!nsCharTraits<T>::find(aXp, nsCharTraits<T>::length(aXp), T('~'))) { |
422 | 8.47k | return ::_shexp_match(aStr, aXp, aCaseInsensitive, 0); |
423 | 8.47k | } |
424 | 0 | |
425 | 0 | expr = (T*)moz_xmalloc((nsCharTraits<T>::length(aXp) + 1) * sizeof(T)); |
426 | 0 | memcpy(expr, aXp, (nsCharTraits<T>::length(aXp) + 1) * sizeof(T)); |
427 | 0 |
|
428 | 0 | int x = ::_scan_and_copy(expr, T('~'), T('\0'), static_cast<T*>(nullptr)); |
429 | 0 | if (x != ABORTED && expr[x] == '~') { |
430 | 0 | expr[x++] = '\0'; |
431 | 0 | ret = ::_shexp_match(aStr, &expr[x], aCaseInsensitive, 0); |
432 | 0 | switch (ret) { |
433 | 0 | case NOMATCH: |
434 | 0 | ret = MATCH; |
435 | 0 | break; |
436 | 0 | case MATCH: |
437 | 0 | ret = NOMATCH; |
438 | 0 | break; |
439 | 0 | default: |
440 | 0 | break; |
441 | 0 | } |
442 | 0 | } |
443 | 0 | if (ret == MATCH) { |
444 | 0 | ret = ::_shexp_match(aStr, expr, aCaseInsensitive, 0); |
445 | 0 | } |
446 | 0 |
|
447 | 0 | free(expr); |
448 | 0 | return ret; |
449 | 0 | } Unified_cpp_xpcom_io1.cpp:int ns_WildCardMatch<char>(char const*, char const*, bool) Line | Count | Source | 417 | 8.47k | { | 418 | 8.47k | T* expr = nullptr; | 419 | 8.47k | int ret = MATCH; | 420 | 8.47k | | 421 | 8.47k | if (!nsCharTraits<T>::find(aXp, nsCharTraits<T>::length(aXp), T('~'))) { | 422 | 8.47k | return ::_shexp_match(aStr, aXp, aCaseInsensitive, 0); | 423 | 8.47k | } | 424 | 0 | | 425 | 0 | expr = (T*)moz_xmalloc((nsCharTraits<T>::length(aXp) + 1) * sizeof(T)); | 426 | 0 | memcpy(expr, aXp, (nsCharTraits<T>::length(aXp) + 1) * sizeof(T)); | 427 | 0 |
| 428 | 0 | int x = ::_scan_and_copy(expr, T('~'), T('\0'), static_cast<T*>(nullptr)); | 429 | 0 | if (x != ABORTED && expr[x] == '~') { | 430 | 0 | expr[x++] = '\0'; | 431 | 0 | ret = ::_shexp_match(aStr, &expr[x], aCaseInsensitive, 0); | 432 | 0 | switch (ret) { | 433 | 0 | case NOMATCH: | 434 | 0 | ret = MATCH; | 435 | 0 | break; | 436 | 0 | case MATCH: | 437 | 0 | ret = NOMATCH; | 438 | 0 | break; | 439 | 0 | default: | 440 | 0 | break; | 441 | 0 | } | 442 | 0 | } | 443 | 0 | if (ret == MATCH) { | 444 | 0 | ret = ::_shexp_match(aStr, expr, aCaseInsensitive, 0); | 445 | 0 | } | 446 | 0 |
| 447 | 0 | free(expr); | 448 | 0 | return ret; | 449 | 0 | } |
Unexecuted instantiation: Unified_cpp_xpcom_io1.cpp:int ns_WildCardMatch<char16_t>(char16_t const*, char16_t const*, bool) |
450 | | |
451 | | template<class T> |
452 | | int |
453 | | NS_WildCardMatch_(const T* aStr, const T* aExpr, bool aCaseInsensitive) |
454 | 8.47k | { |
455 | 8.47k | int is_valid = NS_WildCardValid(aExpr); |
456 | 8.47k | switch (is_valid) { |
457 | 8.47k | case INVALID_SXP: |
458 | 0 | return -1; |
459 | 8.47k | default: |
460 | 8.47k | return ::ns_WildCardMatch(aStr, aExpr, aCaseInsensitive); |
461 | 8.47k | } |
462 | 8.47k | } int NS_WildCardMatch_<char>(char const*, char const*, bool) Line | Count | Source | 454 | 8.47k | { | 455 | 8.47k | int is_valid = NS_WildCardValid(aExpr); | 456 | 8.47k | switch (is_valid) { | 457 | 8.47k | case INVALID_SXP: | 458 | 0 | return -1; | 459 | 8.47k | default: | 460 | 8.47k | return ::ns_WildCardMatch(aStr, aExpr, aCaseInsensitive); | 461 | 8.47k | } | 462 | 8.47k | } |
Unexecuted instantiation: int NS_WildCardMatch_<char16_t>(char16_t const*, char16_t const*, bool) |
463 | | |
464 | | int |
465 | | NS_WildCardMatch(const char* aStr, const char* aXp, bool aCaseInsensitive) |
466 | 8.47k | { |
467 | 8.47k | return NS_WildCardMatch_(aStr, aXp, aCaseInsensitive); |
468 | 8.47k | } |
469 | | |
470 | | int |
471 | | NS_WildCardMatch(const char16_t* aStr, const char16_t* aXp, |
472 | | bool aCaseInsensitive) |
473 | 0 | { |
474 | 0 | return NS_WildCardMatch_(aStr, aXp, aCaseInsensitive); |
475 | 0 | } |