summaryrefslogtreecommitdiff
path: root/src/fs
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-02-07 18:58:37 +0100
committerMax Kellermann <max@duempel.org>2014-02-07 19:08:51 +0100
commitd744c997d8a4370d56901c5bdf92d3cca0ef83bc (patch)
tree808a88c401091b9c8444745e900152599badbd14 /src/fs
parent6b421cc354cb0c297fcf99d7824b99b61caec99d (diff)
fs/Traits: add function Relative()
Move code from Path::RelativeFS() and make it generic.
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/Path.cxx22
-rw-r--r--src/fs/Path.hxx4
-rw-r--r--src/fs/Traits.cxx40
-rw-r--r--src/fs/Traits.hxx18
4 files changed, 61 insertions, 23 deletions
diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx
index 54ad1c3a8..8288a4fec 100644
--- a/src/fs/Path.cxx
+++ b/src/fs/Path.cxx
@@ -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;
-}
diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx
index 3c9dc806f..9e0fa5aeb 100644
--- a/src/fs/Path.hxx
+++ b/src/fs/Path.hxx
@@ -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() {
diff --git a/src/fs/Traits.cxx b/src/fs/Traits.cxx
index a84c745a1..d62987087 100644
--- a/src/fs/Traits.cxx
+++ b/src/fs/Traits.cxx
@@ -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);
+}
diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx
index 323656991..88715c3e8 100644
--- a/src/fs/Traits.hxx
+++ b/src/fs/Traits.hxx
@@ -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.