Skip to content

Commit 3348484

Browse files
committed
Cleanups, comments, more tests
1 parent 89c0e71 commit 3348484

File tree

3 files changed

+264
-189
lines changed

3 files changed

+264
-189
lines changed

lib/pathmatch.cpp

Lines changed: 19 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -21,173 +21,23 @@
2121
#include "path.h"
2222

2323
#include <algorithm>
24-
#include <cctype>
25-
#include <cstdio>
2624
#include <stack>
2725
#include <string>
2826
#include <vector>
2927

30-
struct Pathstr
31-
{
32-
static Pathstr from_pattern(const std::string &pattern, const std::string &basepath, bool icase)
33-
{
34-
if (!pattern.empty() && pattern[0] == '.')
35-
return Pathstr(basepath.c_str(), pattern.c_str(), icase);
36-
return Pathstr(pattern.c_str(), nullptr, icase);
37-
}
38-
39-
static Pathstr from_path(const std::string &path, const std::string &basepath, bool icase)
40-
{
41-
if (Path::isAbsolute(path))
42-
return Pathstr(path.c_str(), nullptr, icase);
43-
return Pathstr(basepath.c_str(), path.c_str(), icase);
44-
}
45-
46-
explicit Pathstr(const char *a = nullptr, const char *b = nullptr, bool lowercase = false) :
47-
s{a, b}, lcase(lowercase)
48-
{
49-
for (int i = 0; i < 2; i++) {
50-
e[i] = s[i];
51-
52-
if (s[i] == nullptr || *s[i] == '\0')
53-
continue;
54-
55-
if (st.l != 0)
56-
st.l++;
57-
58-
while (*e[i] != '\0') {
59-
e[i]++;
60-
st.l++;
61-
}
62-
63-
st.p = e[i];
64-
}
65-
66-
if (st.l == 0)
67-
st.c = '\0';
68-
69-
simplify(false);
70-
}
71-
72-
std::size_t left() const
73-
{
74-
return st.l;
75-
}
76-
77-
char current() const
78-
{
79-
if (st.c != EOF)
80-
return st.c;
81-
82-
char c = st.p[-1];
83-
84-
if (c == '\\')
85-
return '/';
86-
87-
if (lcase)
88-
return std::tolower(c);
89-
90-
return c;
91-
}
92-
93-
void simplify(bool leadsep)
94-
{
95-
while (left() != 0) {
96-
State rst = st;
97-
98-
if (leadsep) {
99-
if (current() != '/')
100-
break;
101-
nextc();
102-
}
103-
104-
char c = current();
105-
if (c == '.') {
106-
nextc();
107-
c = current();
108-
if (c == '.') {
109-
nextc();
110-
c = current();
111-
if (c == '/') {
112-
/* Skip '<name>/../' */
113-
nextc();
114-
simplify(false);
115-
while (left() != 0 && current() != '/')
116-
nextc();
117-
continue;
118-
}
119-
} else if (c == '/') {
120-
/* Skip '/./' */
121-
continue;
122-
} else if (c == '\0') {
123-
/* Skip leading './' */
124-
break;
125-
}
126-
} else if (c == '/' && left() != 1) {
127-
/* Skip double separator (keep root) */
128-
nextc();
129-
leadsep = false;
130-
continue;
131-
}
132-
133-
st = rst;
134-
break;
135-
}
136-
}
137-
138-
void advance()
139-
{
140-
nextc();
141-
142-
if (current() == '/')
143-
simplify(true);
144-
}
14528

146-
void nextc()
147-
{
148-
if (st.l == 0)
149-
return;
150-
151-
st.l--;
152-
153-
if (st.l == 0)
154-
st.c = '\0';
155-
else if (st.c != EOF) {
156-
st.c = EOF;
157-
} else {
158-
st.p--;
159-
if (st.p == s[1]) {
160-
st.p = e[0];
161-
st.c = '/';
162-
}
163-
}
164-
}
165-
166-
void operator++()
167-
{
168-
advance();
169-
}
170-
171-
char operator*() const
172-
{
173-
return current();
174-
}
175-
176-
struct State
177-
{
178-
const char *p;
179-
std::size_t l;
180-
int c {EOF};
181-
};
182-
183-
const char *s[2] {};
184-
const char *e[2] {};
185-
State st {};
186-
bool lcase;
187-
};
29+
PathMatch::PathMatch(std::vector<std::string> patterns, std::string basepath, Mode mode) :
30+
mPatterns(std::move(patterns)), mBasepath(std::move(basepath)), mMode(mode)
31+
{}
18832

33+
bool PathMatch::match(const std::string &path) const
34+
{
35+
return std::any_of(mPatterns.cbegin(), mPatterns.cend(), [=] (const std::string &pattern) {
36+
return match(pattern, path, mBasepath, mMode);
37+
});
38+
}
18939

190-
static bool match_one(const std::string &pattern, const std::string &path, const std::string &basepath, bool icase)
40+
bool PathMatch::match(const std::string &pattern, const std::string &path, const std::string &basepath, Mode mode)
19141
{
19242
if (pattern.empty())
19343
return false;
@@ -197,13 +47,12 @@ static bool match_one(const std::string &pattern, const std::string &path, const
19747

19848
bool real = Path::isAbsolute(pattern) || pattern[0] == '.';
19949

200-
Pathstr s = Pathstr::from_pattern(pattern, basepath, icase);
201-
Pathstr t = Pathstr::from_path(path, basepath, icase);
202-
203-
Pathstr p = s;
204-
Pathstr q = t;
50+
PathIterator s = PathIterator::from_pattern(pattern, basepath, mode == Mode::icase);
51+
PathIterator t = PathIterator::from_path(path, basepath, mode == Mode::icase);
52+
PathIterator p = s;
53+
PathIterator q = t;
20554

206-
std::stack<std::pair<Pathstr::State, Pathstr::State>> b;
55+
std::stack<std::pair<PathIterator::Pos, PathIterator::Pos>> b;
20756

20857
for (;;) {
20958
switch (*s) {
@@ -214,10 +63,10 @@ static bool match_one(const std::string &pattern, const std::string &path, const
21463
slash = true;
21564
++s;
21665
}
217-
b.emplace(s.st, t.st);
66+
b.emplace(s.getpos(), t.getpos());
21867
while (*t != '\0' && (slash || *t != '/')) {
21968
if (*s == *t)
220-
b.emplace(s.st, t.st);
69+
b.emplace(s.getpos(), t.getpos());
22170
++t;
22271
}
22372
continue;
@@ -248,8 +97,8 @@ static bool match_one(const std::string &pattern, const std::string &path, const
24897
if (!b.empty()) {
24998
const auto &bp = b.top();
25099
b.pop();
251-
s.st = bp.first;
252-
t.st = bp.second;
100+
s.setpos(bp.first);
101+
t.setpos(bp.second);
253102
continue;
254103
}
255104

@@ -266,20 +115,3 @@ static bool match_one(const std::string &pattern, const std::string &path, const
266115
return false;
267116
}
268117
}
269-
270-
271-
PathMatch::PathMatch(std::vector<std::string> patterns, std::string basepath, Mode mode) :
272-
mPatterns(std::move(patterns)), mBasepath(std::move(basepath)), mMode(mode)
273-
{}
274-
275-
bool PathMatch::match(const std::string &path) const
276-
{
277-
return std::any_of(mPatterns.cbegin(), mPatterns.cend(), [=] (const std::string &pattern) {
278-
return match_one(pattern, path, mBasepath, mMode == Mode::icase);
279-
});
280-
}
281-
282-
bool PathMatch::match(const std::string &pattern, const std::string &path, const std::string &basepath, Mode mode)
283-
{
284-
return match_one(pattern, path, basepath, mode == Mode::icase);
285-
}

0 commit comments

Comments
 (0)