-
Notifications
You must be signed in to change notification settings - Fork 0
/
FileEnumerator.cpp
98 lines (84 loc) · 2.7 KB
/
FileEnumerator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "FileEnumerator.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/format.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <string_view>
namespace b = ::boost;
namespace ba = ::boost::adaptors;
using ::std::make_pair;
using ::std::regex;
using ::std::runtime_error;
using ::std::string;
using ::std::string_view;
static const char k_wildcardSeparator[] = ")|(?:";
// ============================ CmdLineFileSpec ============================
string CmdLineFileSpec::wildcard() const
{
string name = fname();
if (name.empty())
{
throw runtime_error(str(b::format("The path \"%1%\" does not contain a file name")
% m_path.string()));
}
b::algorithm::replace_all(name, "\\", "\\\\");
b::algorithm::replace_all(name, ".", "\\.");
b::algorithm::replace_all(name, "[", "\\[");
b::algorithm::replace_all(name, "{", "\\{");
b::algorithm::replace_all(name, "}", "\\}");
b::algorithm::replace_all(name, "(", "\\(");
b::algorithm::replace_all(name, ")", "\\)");
b::algorithm::replace_all(name, "+", "\\+");
b::algorithm::replace_all(name, "|", "\\|");
b::algorithm::replace_all(name, "^", "\\^");
b::algorithm::replace_all(name, "$", "\\$");
b::algorithm::replace_all(name, "*", ".*");
b::algorithm::replace_all(name, "?", ".");
//name = '^' + name + '$';
return name;
}
// ============================ FileEnumerator ============================
void FileEnumerator::insert(const char* pFileSpecStr)
{
CmdLineFileSpec fs(pFileSpecStr);
m_fileSpecMap.insert(make_pair(fs.dir(), fs));
}
void FileEnumerator::insert(const Path& fileSpecPath)
{
CmdLineFileSpec fs(fileSpecPath);
m_fileSpecMap.insert(make_pair(fs.dir(), fs));
}
#if defined(CMDLINEUTIL_TEST_MODE)
void FileEnumerator::getFileSpecList(PathList& fileSpecList) const
{
b::push_back(fileSpecList, m_fileSpecMap
| ba::map_values
| ba::transformed([] (const CmdLineFileSpec& clfs) { return clfs.filePath(); }));
}
#endif
// Due to the context in which this is called, rootRng is guaranteed not to be empty.
string FileEnumerator::combineRegexPatterns(const RootDirRng& rootRng)
{
string result;
size_t numStringsConcatenated = 0;
b::for_each(rootRng
| ba::map_values
| ba::transformed([] (const CmdLineFileSpec& clfs) { return clfs.wildcard(); }),
[&] (string_view str)
{
if (numStringsConcatenated > 0)
{
result += k_wildcardSeparator;
}
result += str;
++numStringsConcatenated;
});
return (numStringsConcatenated > 1)
? "^(?:" + result + ")$"
: "^" + result + "$";
}
FileEnumerator::DirPlusRegex FileEnumerator::dirToDirPlusRegex(const Path& dir) const
{
RootDirRng rootRng(m_fileSpecMap.equal_range(dir));
const regex rex(combineRegexPatterns(rootRng));
return make_pair(dir, rex);
}