From d744c997d8a4370d56901c5bdf92d3cca0ef83bc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 7 Feb 2014 18:58:37 +0100 Subject: [PATCH] fs/Traits: add function Relative() Move code from Path::RelativeFS() and make it generic. --- src/fs/Path.cxx | 22 ---------------------- src/fs/Path.hxx | 4 +++- src/fs/Traits.cxx | 40 ++++++++++++++++++++++++++++++++++++++++ src/fs/Traits.hxx | 18 ++++++++++++++++++ 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::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(p); } +PathTraitsFS::const_pointer +PathTraitsFS::Relative(const_pointer base, const_pointer other) +{ + return RelativePathImpl(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(p); } + +PathTraitsUTF8::const_pointer +PathTraitsUTF8::Relative(const_pointer base, const_pointer other) +{ + return RelativePathImpl(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 @@ -105,6 +105,15 @@ struct PathTraitsFS { gcc_pure gcc_nonnull_all 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, @@ -179,6 +188,15 @@ struct PathTraitsUTF8 { gcc_pure gcc_nonnull_all 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,