1 /*
2  * Copyright 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <string.h>
18 #include <AStringUtils.h>
19 
20 namespace android {
21 
22 // static
Compare(const char * a,const char * b,size_t len,bool ignoreCase)23 int AStringUtils::Compare(const char *a, const char *b, size_t len, bool ignoreCase) {
24     // this method relies on a trailing '\0' if a or b are shorter than len
25     return ignoreCase ? strncasecmp(a, b, len) : strncmp(a, b, len);
26 }
27 
28 // static
MatchesGlob(const char * glob,size_t globLen,const char * str,size_t strLen,bool ignoreCase)29 bool AStringUtils::MatchesGlob(
30         const char *glob, size_t globLen, const char *str, size_t strLen, bool ignoreCase) {
31     // this method does not assume a trailing '\0'
32     size_t ix = 0, globIx = 0;
33 
34     // pattern must match until first '*'
35     while (globIx < globLen && glob[globIx] != '*') {
36         ++globIx;
37     }
38     if (strLen < globIx || Compare(str, glob, globIx /* len */, ignoreCase)) {
39         return false;
40     }
41     ix = globIx;
42 
43     // process by * separated sections
44     while (globIx < globLen) {
45         ++globIx;
46         size_t start = globIx;
47         while (globIx < globLen && glob[globIx] != '*') {
48             ++globIx;
49         }
50         size_t len = globIx - start;
51         const char *pattern = glob + start;
52 
53         if (globIx == globLen) {
54             // last pattern must match tail
55             if (ix + len > strLen) {
56                 return false;
57             }
58             const char *tail = str + strLen - len;
59             return !Compare(tail, pattern, len, ignoreCase);
60         }
61         // progress after first occurrence of pattern
62         while (ix + len <= strLen && Compare(str + ix, pattern, len, ignoreCase)) {
63             ++ix;
64         }
65         if (ix + len > strLen) {
66             return false;
67         }
68         ix += len;
69         // we will loop around as globIx < globLen
70     }
71 
72     // we only get here if there were no * in the pattern
73     return ix == strLen;
74 }
75 
76 }  // namespace android
77 
78