Skip to content

Commit 6542780

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.6
1 parent 8dbc152 commit 6542780

File tree

3 files changed

+122
-15
lines changed

3 files changed

+122
-15
lines changed

llvm/include/llvm/Support/GlobPattern.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,30 @@ class GlobPattern {
6363
// Returns true for glob pattern "*". Can be used to avoid expensive
6464
// preparation/acquisition of the input for match().
6565
bool isTrivialMatchAll() const {
66-
if (!Prefix.empty())
66+
if (PrefixSize)
6767
return false;
68-
if (!Suffix.empty())
68+
if (SuffixSize)
6969
return false;
7070
if (SubGlobs.size() != 1)
7171
return false;
7272
return SubGlobs[0].getPat() == "*";
7373
}
7474

75-
StringRef prefix() const { return Prefix; }
76-
StringRef suffix() const { return Suffix; }
75+
// The followind functions are as shortcuts to some matching. They are
76+
// conservative to simplify implementations.
7777

78-
private:
79-
StringRef Prefix;
80-
StringRef Suffix;
78+
// Returns plain prefix of the pattern.
79+
StringRef prefix() const { return Pattern.take_front(PrefixSize); }
80+
// Returns plain suffix of the pattern.
81+
StringRef suffix() const { return Pattern.take_back(SuffixSize); }
82+
// Returns the longest plain substring of the pattern between of prefix and
83+
// suffix.
84+
StringRef longest_substr() const;
8185

86+
private:
87+
StringRef Pattern;
88+
size_t PrefixSize = 0;
89+
size_t SuffixSize = 0;
8290
struct SubGlobPattern {
8391
/// \param Pat the pattern to match against
8492
LLVM_ABI static Expected<SubGlobPattern> create(StringRef Pat);

llvm/lib/Support/GlobPattern.cpp

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,24 +132,60 @@ parseBraceExpansions(StringRef S, std::optional<size_t> MaxSubPatterns) {
132132
return std::move(SubPatterns);
133133
}
134134

135+
static StringRef maxPlainSubstring(StringRef S) {
136+
StringRef R;
137+
while (!S.empty()) {
138+
size_t PrefixSize = S.find_first_of("?*[{\\");
139+
if (PrefixSize == std::string::npos)
140+
PrefixSize = S.size();
141+
142+
if (R.size() < PrefixSize)
143+
R = S.take_front(PrefixSize);
144+
S = S.drop_front(PrefixSize);
145+
146+
switch (S.front()) {
147+
case '\\':
148+
S = S.drop_front(2);
149+
break;
150+
case '[': {
151+
size_t EndBracket = S.find_first_of("]");
152+
if (EndBracket == std::string::npos)
153+
return R; // Incorrect, but let SubGlobPattern::create handle it.
154+
S = S.drop_front(EndBracket + 1);
155+
break;
156+
}
157+
case '{':
158+
// TODO: implement.
159+
return {};
160+
default:
161+
S = S.drop_front(1);
162+
}
163+
}
164+
165+
return R;
166+
}
167+
135168
Expected<GlobPattern>
136169
GlobPattern::create(StringRef S, std::optional<size_t> MaxSubPatterns) {
137170
GlobPattern Pat;
171+
Pat.Pattern = S;
138172

139173
// Store the prefix that does not contain any metacharacter.
140-
size_t PrefixSize = S.find_first_of("?*[{\\");
141-
Pat.Prefix = S.substr(0, PrefixSize);
142-
if (PrefixSize == std::string::npos)
174+
Pat.PrefixSize = S.find_first_of("?*[{\\");
175+
if (Pat.PrefixSize == std::string::npos) {
176+
Pat.PrefixSize = S.size();
143177
return Pat;
144-
S = S.substr(PrefixSize);
178+
}
179+
S = S.substr(Pat.PrefixSize);
145180

146181
// Just in case we stop on unmatched opening brackets.
147182
size_t SuffixStart = S.find_last_of("?*[]{}\\");
148183
assert(SuffixStart != std::string::npos);
149184
if (S[SuffixStart] == '\\')
150185
++SuffixStart;
151-
++SuffixStart;
152-
Pat.Suffix = S.substr(SuffixStart);
186+
if (SuffixStart < S.size())
187+
++SuffixStart;
188+
Pat.SuffixSize = S.size() - SuffixStart;
153189
S = S.substr(0, SuffixStart);
154190

155191
SmallVector<std::string, 1> SubPats;
@@ -199,10 +235,15 @@ GlobPattern::SubGlobPattern::create(StringRef S) {
199235
return Pat;
200236
}
201237

238+
StringRef GlobPattern::longest_substr() const {
239+
return maxPlainSubstring(
240+
Pattern.drop_front(PrefixSize).drop_back(SuffixSize));
241+
}
242+
202243
bool GlobPattern::match(StringRef S) const {
203-
if (!S.consume_front(Prefix))
244+
if (!S.consume_front(prefix()))
204245
return false;
205-
if (!S.consume_back(Suffix))
246+
if (!S.consume_back(suffix()))
206247
return false;
207248
if (SubGlobs.empty() && S.empty())
208249
return true;

llvm/unittests/Support/GlobPatternTest.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,64 @@ TEST_F(GlobPatternTest, PrefixSuffix) {
329329
EXPECT_EQ("cd", Pat->suffix());
330330
}
331331

332+
TEST_F(GlobPatternTest, Substr) {
333+
auto Pat = GlobPattern::create("");
334+
ASSERT_TRUE((bool)Pat);
335+
EXPECT_EQ("", Pat->longest_substr());
336+
337+
Pat = GlobPattern::create("abcd");
338+
ASSERT_TRUE((bool)Pat);
339+
EXPECT_EQ("", Pat->longest_substr());
340+
341+
Pat = GlobPattern::create("a*bcd");
342+
ASSERT_TRUE((bool)Pat);
343+
EXPECT_EQ("", Pat->longest_substr());
344+
345+
Pat = GlobPattern::create("*abcd");
346+
ASSERT_TRUE((bool)Pat);
347+
EXPECT_EQ("", Pat->longest_substr());
348+
349+
Pat = GlobPattern::create("abcd*");
350+
ASSERT_TRUE((bool)Pat);
351+
EXPECT_EQ("", Pat->longest_substr());
352+
353+
Pat = GlobPattern::create("a*bc*d");
354+
ASSERT_TRUE((bool)Pat);
355+
EXPECT_EQ("bc", Pat->longest_substr());
356+
357+
Pat = GlobPattern::create("a*bc*def*g");
358+
ASSERT_TRUE((bool)Pat);
359+
EXPECT_EQ("def", Pat->longest_substr());
360+
361+
Pat = GlobPattern::create("a*bcd*ef*g");
362+
ASSERT_TRUE((bool)Pat);
363+
EXPECT_EQ("bcd", Pat->longest_substr());
364+
365+
Pat = GlobPattern::create("a*bcd*efg*h");
366+
ASSERT_TRUE((bool)Pat);
367+
EXPECT_EQ("bcd", Pat->longest_substr());
368+
369+
Pat = GlobPattern::create("a*bcd[ef]g*h");
370+
ASSERT_TRUE((bool)Pat);
371+
EXPECT_EQ("bcd", Pat->longest_substr());
372+
373+
Pat = GlobPattern::create("a*bcde\\fg*h");
374+
ASSERT_TRUE((bool)Pat);
375+
EXPECT_EQ("bcde", Pat->longest_substr());
376+
377+
Pat = GlobPattern::create("a*bcde\\[fg*h");
378+
ASSERT_TRUE((bool)Pat);
379+
EXPECT_EQ("bcde", Pat->longest_substr());
380+
381+
Pat = GlobPattern::create("a*bcde?fg*h");
382+
ASSERT_TRUE((bool)Pat);
383+
EXPECT_EQ("bcde", Pat->longest_substr());
384+
385+
Pat = GlobPattern::create("a*bcdef{g}*h");
386+
ASSERT_TRUE((bool)Pat);
387+
EXPECT_EQ("", Pat->longest_substr());
388+
}
389+
332390
TEST_F(GlobPatternTest, Pathological) {
333391
std::string P, S(40, 'a');
334392
StringRef Pieces[] = {"a*", "[ba]*", "{b*,a*}*"};

0 commit comments

Comments
 (0)