Move 'normalize_path' into path.cpp

This commit is contained in:
Daniel James
2017-08-09 15:40:52 +01:00
parent 1f4b71c744
commit 230c2a516b
3 changed files with 45 additions and 43 deletions

View File

@@ -21,6 +21,49 @@
namespace quickbook
{
// Convert the path to its canonical representation if it exists.
// Or something close if it doesn't.
fs::path normalize_path(fs::path const& path)
{
fs::path p = fs::absolute(path); // The base of the path.
fs::path extra; // The non-existant part of the path.
int parent_count = 0; // Number of active '..' sections
// Invariant: path is equivalent to: p / ('..' * parent_count) / extra
// i.e. if parent_count == 0: p/extra
// if parent_count == 2: p/../../extra
// Pop path sections from path until we find an existing
// path, adjusting for any dot path sections.
while (!fs::exists(fs::status(p))) {
fs::path name = p.filename();
p = p.parent_path();
if (name == "..") {
++parent_count;
}
else if (name == ".") {
}
else if (parent_count) {
--parent_count;
}
else {
extra = name / extra;
}
}
// If there are any left over ".." sections, then add them
// on to the end of the real path, and trust Boost.Filesystem
// to sort them out.
while (parent_count) {
p = p / "..";
--parent_count;
}
// Cannoicalize the existing part of the path, and add 'extra' back to
// the end.
return fs::canonical(p) / extra;
}
// Not a general purpose normalization function, just
// from paths from the root directory. It strips the excess
// ".." parts from a path like: "x/../../y", leaving "y".