Commit d744c997 authored by Max Kellermann's avatar Max Kellermann

fs/Traits: add function Relative()

Move code from Path::RelativeFS() and make it generic.
parent 6b421cc3
......@@ -26,25 +26,3 @@ Path::ToUTF8() const
{
return ::PathToUTF8(c_str());
}
const char *
Path::RelativeFS(const char *other_fs) const
{
const size_t l = length();
if (memcmp(data(), other_fs, l) != 0)
return nullptr;
other_fs += l;
if (*other_fs != 0) {
if (!PathTraitsFS::IsSeparator(*other_fs))
/* mismatch */
return nullptr;
/* skip remaining path separators */
do {
++other_fs;
} while (PathTraitsFS::IsSeparator(*other_fs));
}
return other_fs;
}
......@@ -135,7 +135,9 @@ public:
* nullptr on mismatch.
*/
gcc_pure
const char *RelativeFS(const char *other_fs) const;
const char *RelativeFS(const char *other_fs) const {
return PathTraitsFS::Relative(value, other_fs);
}
gcc_pure
bool IsAbsolute() {
......
......@@ -78,6 +78,34 @@ GetParentPathImpl(typename Traits::const_pointer p)
return typename Traits::string(p, sep);
}
template<typename Traits>
typename Traits::const_pointer
RelativePathImpl(typename Traits::const_pointer base,
typename Traits::const_pointer other)
{
assert(base != nullptr);
assert(other != nullptr);
const auto base_length = Traits::GetLength(base);
if (memcmp(base, other, base_length * sizeof(*base)) != 0)
/* mismatch */
return nullptr;
other += base_length;
if (other != 0) {
if (!Traits::IsSeparator(*other))
/* mismatch */
return nullptr;
/* skip remaining path separators */
do {
++other;
} while (Traits::IsSeparator(*other));
}
return other;
}
PathTraitsFS::string
PathTraitsFS::Build(PathTraitsFS::const_pointer a, size_t a_size,
PathTraitsFS::const_pointer b, size_t b_size)
......@@ -97,6 +125,12 @@ PathTraitsFS::GetParent(PathTraitsFS::const_pointer p)
return GetParentPathImpl<PathTraitsFS>(p);
}
PathTraitsFS::const_pointer
PathTraitsFS::Relative(const_pointer base, const_pointer other)
{
return RelativePathImpl<PathTraitsFS>(base, other);
}
PathTraitsUTF8::string
PathTraitsUTF8::Build(PathTraitsUTF8::const_pointer a, size_t a_size,
PathTraitsUTF8::const_pointer b, size_t b_size)
......@@ -115,3 +149,9 @@ PathTraitsUTF8::GetParent(PathTraitsUTF8::const_pointer p)
{
return GetParentPathImpl<PathTraitsUTF8>(p);
}
PathTraitsUTF8::const_pointer
PathTraitsUTF8::Relative(const_pointer base, const_pointer other)
{
return RelativePathImpl<PathTraitsUTF8>(base, other);
}
......@@ -106,6 +106,15 @@ struct PathTraitsFS {
static string GetParent(const_pointer p);
/**
* Determine the relative part of the given path to this
* object, not including the directory separator. Returns an
* empty string if the given path equals this object or
* nullptr on mismatch.
*/
gcc_pure gcc_nonnull_all
static const_pointer Relative(const_pointer base, const_pointer other);
/**
* Constructs the path from the given components.
* If either of the components is empty string,
* remaining component is returned unchanged.
......@@ -180,6 +189,15 @@ struct PathTraitsUTF8 {
static string GetParent(const_pointer p);
/**
* Determine the relative part of the given path to this
* object, not including the directory separator. Returns an
* empty string if the given path equals this object or
* nullptr on mismatch.
*/
gcc_pure gcc_nonnull_all
static const_pointer Relative(const_pointer base, const_pointer other);
/**
* Constructs the path from the given components.
* If either of the components is empty string,
* remaining component is returned unchanged.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment