[PowerPC] Generate Power9 extswsli extend sign and shift immediate instruction
[llvm-core.git] / lib / Support / GlobPattern.cpp
blob4ea110301f16de42e17b29945a802663c0751b94
1 //===-- GlobPattern.cpp - Glob pattern matcher implementation -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements a glob pattern matcher.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/GlobPattern.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Errc.h"
20 using namespace llvm;
22 static bool hasWildcard(StringRef S) {
23 return S.find_first_of("?*[") != StringRef::npos;
26 // Expands character ranges and returns a bitmap.
27 // For example, "a-cf-hz" is expanded to "abcfghz".
28 static Expected<BitVector> expand(StringRef S, StringRef Original) {
29 BitVector BV(256, false);
31 // Expand X-Y.
32 for (;;) {
33 if (S.size() < 3)
34 break;
36 uint8_t Start = S[0];
37 uint8_t End = S[2];
39 // If it doesn't start with something like X-Y,
40 // consume the first character and proceed.
41 if (S[1] != '-') {
42 BV[Start] = true;
43 S = S.substr(1);
44 continue;
47 // It must be in the form of X-Y.
48 // Validate it and then interpret the range.
49 if (Start > End)
50 return make_error<StringError>("invalid glob pattern: " + Original,
51 errc::invalid_argument);
53 for (int C = Start; C <= End; ++C)
54 BV[(uint8_t)C] = true;
55 S = S.substr(3);
58 for (char C : S)
59 BV[(uint8_t)C] = true;
60 return BV;
63 // This is a scanner for the glob pattern.
64 // A glob pattern token is one of "*", "?", "[<chars>]", "[^<chars>]"
65 // (which is a negative form of "[<chars>]"), or a non-meta character.
66 // This function returns the first token in S.
67 static Expected<BitVector> scan(StringRef &S, StringRef Original) {
68 switch (S[0]) {
69 case '*':
70 S = S.substr(1);
71 // '*' is represented by an empty bitvector.
72 // All other bitvectors are 256-bit long.
73 return BitVector();
74 case '?':
75 S = S.substr(1);
76 return BitVector(256, true);
77 case '[': {
78 size_t End = S.find(']', 1);
79 if (End == StringRef::npos)
80 return make_error<StringError>("invalid glob pattern: " + Original,
81 errc::invalid_argument);
83 StringRef Chars = S.substr(1, End - 1);
84 S = S.substr(End + 1);
85 if (Chars.startswith("^")) {
86 Expected<BitVector> BV = expand(Chars.substr(1), Original);
87 if (!BV)
88 return BV.takeError();
89 return BV->flip();
91 return expand(Chars, Original);
93 default:
94 BitVector BV(256, false);
95 BV[(uint8_t)S[0]] = true;
96 S = S.substr(1);
97 return BV;
101 Expected<GlobPattern> GlobPattern::create(StringRef S) {
102 GlobPattern Pat;
104 // S doesn't contain any metacharacter,
105 // so the regular string comparison should work.
106 if (!hasWildcard(S)) {
107 Pat.Exact = S;
108 return Pat;
111 // S is something like "foo*". We can use startswith().
112 if (S.endswith("*") && !hasWildcard(S.drop_back())) {
113 Pat.Prefix = S.drop_back();
114 return Pat;
117 // S is something like "*foo". We can use endswith().
118 if (S.startswith("*") && !hasWildcard(S.drop_front())) {
119 Pat.Suffix = S.drop_front();
120 return Pat;
123 // Otherwise, we need to do real glob pattern matching.
124 // Parse the pattern now.
125 StringRef Original = S;
126 while (!S.empty()) {
127 Expected<BitVector> BV = scan(S, Original);
128 if (!BV)
129 return BV.takeError();
130 Pat.Tokens.push_back(*BV);
132 return Pat;
135 bool GlobPattern::match(StringRef S) const {
136 if (Exact)
137 return S == *Exact;
138 if (Prefix)
139 return S.startswith(*Prefix);
140 if (Suffix)
141 return S.endswith(*Suffix);
142 return matchOne(Tokens, S);
145 // Runs glob pattern Pats against string S.
146 bool GlobPattern::matchOne(ArrayRef<BitVector> Pats, StringRef S) const {
147 for (;;) {
148 if (Pats.empty())
149 return S.empty();
151 // If Pats[0] is '*', try to match Pats[1..] against all possible
152 // tail strings of S to see at least one pattern succeeds.
153 if (Pats[0].size() == 0) {
154 Pats = Pats.slice(1);
155 if (Pats.empty())
156 // Fast path. If a pattern is '*', it matches anything.
157 return true;
158 for (size_t I = 0, E = S.size(); I < E; ++I)
159 if (matchOne(Pats, S.substr(I)))
160 return true;
161 return false;
164 // If Pats[0] is not '*', it must consume one character.
165 if (S.empty() || !Pats[0][(uint8_t)S[0]])
166 return false;
167 Pats = Pats.slice(1);
168 S = S.substr(1);