diff --git a/src/fs/Traits.cxx b/src/fs/Traits.cxx index fbd87bdce..3c596dfc8 100644 --- a/src/fs/Traits.cxx +++ b/src/fs/Traits.cxx @@ -117,6 +117,37 @@ RelativePathImpl(typename Traits::string_view base, return other; } +template +typename Traits::string_view +RelativePathImpl(typename Traits::string_view base, + typename Traits::string_view _other) noexcept +{ + BasicStringView other(_other); + + if (!other.SkipPrefix(base)) + /* mismatch */ + return {}; + + if (!other.empty()) { + if (!Traits::IsSeparator(other.front())) { + if (!base.empty() && Traits::IsSeparator(other.data[-1])) + /* "other" has no more slash, but the + matching base ended with a slash: + enough to detect a match */ + return other; + + /* mismatch */ + return {}; + } + + /* skip remaining path separators */ + while (!other.empty() && Traits::IsSeparator(other.front())) + other.pop_front(); + } + + return other; +} + PathTraitsFS::string PathTraitsFS::Build(string_view a, string_view b) noexcept { @@ -141,6 +172,12 @@ PathTraitsFS::Relative(string_view base, const_pointer other) noexcept return RelativePathImpl(base, other); } +PathTraitsFS::string_view +PathTraitsFS::Relative(string_view base, string_view other) noexcept +{ + return RelativePathImpl(base, other); +} + PathTraitsFS::string PathTraitsFS::Apply(const_pointer base, const_pointer path) noexcept { @@ -178,3 +215,9 @@ PathTraitsUTF8::Relative(string_view base, const_pointer other) noexcept { return RelativePathImpl(base, other); } + +PathTraitsUTF8::string_view +PathTraitsUTF8::Relative(string_view base, string_view other) noexcept +{ + return RelativePathImpl(base, other); +} diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx index d2e5f83b0..bcb432f60 100644 --- a/src/fs/Traits.hxx +++ b/src/fs/Traits.hxx @@ -149,6 +149,9 @@ struct PathTraitsFS { gcc_pure gcc_nonnull_all static const_pointer Relative(string_view base, const_pointer other) noexcept; + gcc_pure + static string_view Relative(string_view base, string_view other) noexcept; + /** * Constructs the path from the given components. * If either of the components is empty string, @@ -257,6 +260,9 @@ struct PathTraitsUTF8 { gcc_pure gcc_nonnull_all static const_pointer Relative(string_view base, const_pointer other) noexcept; + gcc_pure + static string_view Relative(string_view base, string_view other) noexcept; + /** * Constructs the path from the given components. * If either of the components is empty string,