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