Skip to content

Commit 8c5c0fc

Browse files
committed
chore: Path public API work
1 parent 028a460 commit 8c5c0fc

File tree

3 files changed

+276
-14
lines changed

3 files changed

+276
-14
lines changed

include/mrdox/Support/Path.hpp

+112-3
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,128 @@
1212
#define MRDOX_SUPPORT_PATH_HPP
1313

1414
#include <mrdox/Platform.hpp>
15+
#include <mrdox/Support/Error.hpp>
16+
#include <mrdox/Support/Expected.hpp>
1517
#include <string>
1618
#include <string_view>
1719

1820
namespace clang {
1921
namespace mrdox {
2022

21-
/** Return a full path from a possibly relative path.
23+
/** Append a trailing native separator if not already present.
2224
*/
25+
MRDOX_DECL
26+
std::string_view
27+
makeDirsy(
28+
std::string& dirName);
29+
30+
/** Return a native absolute path representing a path.
31+
32+
This function returns an absolute path using
33+
native separators given a relative or absolute
34+
path.
35+
36+
If the input path is relative, it is first made
37+
absolute by resolving it against the configuration's
38+
working directory.
39+
40+
The input path can use native, POSIX, or Windows
41+
separators.
42+
43+
The returned path will have a trailing separator.
44+
*/
45+
MRDOX_DECL
2346
std::string
24-
makeFullPath(
25-
std::string_view pathName,
47+
makeAbsoluteDirectory(
48+
std::string_view dirName,
2649
std::string_view workingDir);
2750

51+
MRDOX_DECL
52+
std::string
53+
makeFilePath(
54+
std::string_view dirName,
55+
std::string_view fileName);
56+
57+
//------------------------------------------------
58+
59+
struct AnyFileVisitor
60+
{
61+
virtual Error visitFile(std::string_view fileName) = 0;
62+
};
63+
64+
/** Call a function for each file in a directory.
65+
66+
This will iterate all the regular files in
67+
a directory and invoke the visitor with the
68+
path.
69+
*/
70+
MRDOX_DECL
71+
Error
72+
forEachFile(
73+
std::string_view dirPath,
74+
AnyFileVisitor& visitor);
75+
76+
/** Visit each file in a directory.
77+
*/
78+
template<class Visitor>
79+
Error
80+
forEachFile(
81+
std::string_view dirPath,
82+
Visitor&& visitor)
83+
{
84+
struct FileVisitor : AnyFileVisitor
85+
{
86+
Visitor& visitor_;
87+
88+
explicit FileVisitor(Visitor& v)
89+
: visitor_(v)
90+
{
91+
}
92+
93+
Error
94+
visitFile(std::string_view fileName) override
95+
{
96+
return visitor_(fileName);
97+
}
98+
};
99+
100+
FileVisitor v{visitor};
101+
return forEachFile(dirPath, static_cast<AnyFileVisitor&>(v));
102+
}
103+
104+
//------------------------------------------------
105+
106+
namespace files {
107+
108+
/** Return the filename part of the path.
109+
*/
110+
MRDOX_DECL
111+
std::string_view
112+
getFileName(
113+
std::string_view pathName);
114+
115+
/** Return the contents of a file as a string.
116+
*/
117+
MRDOX_DECL
118+
Expected<std::string>
119+
getFileText(
120+
std::string_view pathName);
121+
122+
/** Append a trailing native separator if not already present.
123+
*/
124+
MRDOX_DECL
125+
std::string
126+
makeDirsy(
127+
std::string_view pathName);
128+
129+
MRDOX_DECL
130+
std::string
131+
appendPath(
132+
std::string_view basePath,
133+
std::string_view pathName);
134+
135+
} // files
136+
28137
} // mrdox
29138
} // clang
30139

source/Support/Path.cpp

+163-11
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,85 @@
1010
//
1111

1212
#include "Path.hpp"
13+
#include "Support/Debug.hpp"
1314
#include <llvm/Support/FileSystem.h>
1415
#include <llvm/Support/Path.h>
16+
#include <llvm/Support/MemoryBuffer.h>
17+
18+
#include <fstream>
1519

1620
namespace clang {
1721
namespace mrdox {
1822

19-
//------------------------------------------------
23+
static
24+
bool
25+
isDirsy(
26+
std::string_view nativeDirName)
27+
{
28+
namespace path = llvm::sys::path;
29+
if(nativeDirName.empty())
30+
return false;
31+
if(! path::is_separator(
32+
nativeDirName.back(),
33+
path::Style::windows_slash))
34+
return false;
35+
return true;
36+
}
37+
38+
std::string_view
39+
makeDirsy(
40+
std::string& dirName)
41+
{
42+
namespace path = llvm::sys::path;
43+
44+
if( ! dirName.empty() &&
45+
! path::is_separator(
46+
dirName.back(),
47+
path::Style::windows_slash))
48+
{
49+
auto const sep = path::get_separator(path::Style::native);
50+
dirName.push_back(sep.front());
51+
}
52+
53+
return dirName;
54+
}
2055

2156
std::string
22-
makeFullPath(
23-
std::string_view pathName,
57+
makeAbsoluteDirectory(
58+
std::string_view dirName,
2459
std::string_view workingDir)
2560
{
2661
namespace path = llvm::sys::path;
2762

28-
llvm::SmallString<0> result;
63+
Assert(isDirsy(workingDir));
2964

30-
if(! path::is_absolute(pathName))
65+
if(! path::is_absolute(dirName, path::Style::windows_slash))
3166
{
32-
result = workingDir;
33-
path::append(result, path::Style::posix, pathName);
34-
path::remove_dots(result, true, path::Style::posix);
67+
SmallPathString result(workingDir);
68+
path::append(result, path::Style::native, dirName);
69+
path::remove_dots(result, true, path::Style::native);
70+
makeDirsy(result);
3571
return std::string(result);
3672
}
3773

38-
result = pathName;
39-
path::remove_dots(result, true);
40-
convert_to_slash(result);
74+
SmallPathString result(workingDir);
75+
path::remove_dots(result, true, path::Style::native);
76+
makeDirsy(result);
4177
return std::string(result);
4278
}
4379

80+
std::string
81+
makeFilePath(
82+
std::string_view dirName,
83+
std::string_view fileName)
84+
{
85+
namespace path = llvm::sys::path;
86+
87+
SmallPathString result(dirName);
88+
path::append(result, path::Style::native, fileName);
89+
path::remove_dots(result, true, path::Style::native);
90+
return std::string(result);
91+
}
4492

4593
//------------------------------------------------
4694

@@ -69,5 +117,109 @@ makeDirsy(
69117
}
70118
}
71119

120+
//------------------------------------------------
121+
122+
Error
123+
forEachFile(
124+
std::string_view dirPath,
125+
AnyFileVisitor& visitor)
126+
{
127+
namespace fs = llvm::sys::fs;
128+
namespace path = llvm::sys::path;
129+
130+
std::error_code ec;
131+
fs::directory_iterator const end{};
132+
fs::directory_iterator it(dirPath, ec, false);
133+
if(ec)
134+
return Error("fs::directory_iterator(\"{}\") returned \"{}\"", dirPath, ec);
135+
while(it != end)
136+
{
137+
if(it->type() == fs::file_type::directory_file)
138+
{
139+
std::string s = it->path();
140+
makeDirsy(s);
141+
auto err = visitor.visitFile(s);
142+
if(err)
143+
return err;
144+
}
145+
else if(it->type() == fs::file_type::regular_file)
146+
{
147+
auto err = visitor.visitFile(it->path());
148+
if(err)
149+
return err;
150+
}
151+
else
152+
{
153+
// we don't handle this type
154+
}
155+
it.increment(ec);
156+
if(ec)
157+
return Error("directory_iterator::increment returned \"{}\"", ec);
158+
}
159+
return Error::success();
160+
}
161+
162+
//------------------------------------------------
163+
164+
namespace files {
165+
166+
std::string_view
167+
getFileName(
168+
std::string_view pathName)
169+
{
170+
namespace path = llvm::sys::path;
171+
172+
return path::filename(pathName);
173+
}
174+
175+
Expected<std::string>
176+
getFileText(
177+
std::string_view pathName)
178+
{
179+
std::ifstream file((std::string(pathName)));
180+
if(! file.good())
181+
return Error("std::ifstream(\"{}\" returned \"{}\"",
182+
pathName, std::error_code(errno, std::generic_category()));
183+
std::istreambuf_iterator<char> it(file);
184+
std::istreambuf_iterator<char> const end;
185+
std::string text(it, end);
186+
if(! file.good())
187+
return Error("getFileText(\"{}\") returned \"{}\"",
188+
pathName, std::error_code(errno, std::generic_category()));
189+
return text;
190+
}
191+
192+
std::string
193+
makeDirsy(
194+
std::string_view pathName)
195+
{
196+
namespace path = llvm::sys::path;
197+
198+
std::string result = static_cast<std::string>(pathName);
199+
if( ! result.empty() &&
200+
! path::is_separator(
201+
result.back(),
202+
path::Style::windows_slash))
203+
{
204+
auto const sep = path::get_separator(path::Style::native);
205+
result.push_back(sep.front());
206+
}
207+
return result;
208+
}
209+
210+
std::string
211+
appendPath(
212+
std::string_view basePath,
213+
std::string_view pathName)
214+
{
215+
namespace path = llvm::sys::path;
216+
217+
SmallPathString temp(makeDirsy(basePath));
218+
path::append(temp, pathName);
219+
return static_cast<std::string>(temp.str());
220+
}
221+
222+
} // files
223+
72224
} // mrdox
73225
} // clang

source/Support/Path.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define MRDOX_LIB_SUPPORT_PATH_HPP
1414

1515
#include <mrdox/Platform.hpp>
16+
#include <mrdox/Support/Path.hpp>
1617
#include <llvm/ADT/SmallString.h>
1718
#include <llvm/ADT/StringRef.h>
1819
#include <llvm/Support/Path.h>

0 commit comments

Comments
 (0)