diff options
author | Max Kellermann <max@musicpd.org> | 2021-07-16 08:20:18 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2021-07-16 08:30:34 +0200 |
commit | 809a18913a179c1581cea463daaac3cbdae2231f (patch) | |
tree | d7989375e71732781f728626cd18a15fa99dfbc2 | |
parent | 5eab2d96f499ba0dce3df1800e566c7b52b3d05f (diff) |
fs/Traits: add overload GetParent(string_view)
-rw-r--r-- | src/fs/Traits.cxx | 28 | ||||
-rw-r--r-- | src/fs/Traits.hxx | 31 |
2 files changed, 59 insertions, 0 deletions
diff --git a/src/fs/Traits.cxx b/src/fs/Traits.cxx index f3598fdc1..35d7fa1fd 100644 --- a/src/fs/Traits.cxx +++ b/src/fs/Traits.cxx @@ -85,6 +85,22 @@ GetParentPathImpl(typename Traits::const_pointer p) noexcept } template<typename Traits> +typename Traits::string_view +GetParentPathImpl(typename Traits::string_view p) noexcept +{ + auto sep = Traits::FindLastSeparator(p); + if (sep == nullptr) + return Traits::CURRENT_DIRECTORY; + if (sep == p.data()) + return p.substr(0, 1); +#ifdef _WIN32 + if (Traits::IsDrive(p) && sep == p.data() + 2) + return p.substr(0, 3); +#endif + return p.substr(0, sep - p.data()); +} + +template<typename Traits> typename Traits::const_pointer RelativePathImpl(typename Traits::string_view base, typename Traits::const_pointer other) noexcept @@ -166,6 +182,12 @@ PathTraitsFS::GetParent(PathTraitsFS::const_pointer p) noexcept return GetParentPathImpl<PathTraitsFS>(p); } +PathTraitsFS::string_view +PathTraitsFS::GetParent(string_view p) noexcept +{ + return GetParentPathImpl<PathTraitsFS>(p); +} + PathTraitsFS::const_pointer PathTraitsFS::Relative(string_view base, const_pointer other) noexcept { @@ -210,6 +232,12 @@ PathTraitsUTF8::GetParent(const_pointer p) noexcept return GetParentPathImpl<PathTraitsUTF8>(p); } +PathTraitsUTF8::string_view +PathTraitsUTF8::GetParent(string_view p) noexcept +{ + return GetParentPathImpl<PathTraitsUTF8>(p); +} + PathTraitsUTF8::const_pointer PathTraitsUTF8::Relative(string_view base, const_pointer other) noexcept { diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx index 9f22e2f7a..a5495a29f 100644 --- a/src/fs/Traits.hxx +++ b/src/fs/Traits.hxx @@ -88,6 +88,18 @@ struct PathTraitsFS { #endif } + [[gnu::pure]] + static const_pointer FindLastSeparator(string_view p) noexcept { +#ifdef _WIN32 + const_pointer pos = p.data() + p.size(); + while (p.data() != pos && !IsSeparator(*pos)) + --pos; + return IsSeparator(*pos) ? pos : nullptr; +#else + return StringFindLast(p.data(), SEPARATOR, p.size()); +#endif + } + gcc_pure static const_pointer GetFilenameSuffix(const_pointer filename) noexcept { const_pointer dot = StringFindLast(filename, '.'); @@ -106,6 +118,10 @@ struct PathTraitsFS { static constexpr bool IsDrive(const_pointer p) noexcept { return IsAlphaASCII(p[0]) && p[1] == ':'; } + + static constexpr bool IsDrive(string_view p) noexcept { + return p.size() >= 2 && IsAlphaASCII(p[0]) && p[1] == ':'; + } #endif gcc_pure gcc_nonnull_all @@ -153,6 +169,9 @@ struct PathTraitsFS { gcc_pure gcc_nonnull_all static string_view GetParent(const_pointer p) noexcept; + [[gnu::pure]] + static string_view GetParent(string_view p) noexcept; + /** * Determine the relative part of the given path to this * object, not including the directory separator. Returns an @@ -212,6 +231,11 @@ struct PathTraitsUTF8 { return std::strrchr(p, SEPARATOR); } + [[gnu::pure]] + static const_pointer FindLastSeparator(string_view p) noexcept { + return StringFindLast(p.data(), SEPARATOR, p.size()); + } + gcc_pure static const_pointer GetFilenameSuffix(const_pointer filename) noexcept { const_pointer dot = StringFindLast(filename, '.'); @@ -230,6 +254,10 @@ struct PathTraitsUTF8 { static constexpr bool IsDrive(const_pointer p) noexcept { return IsAlphaASCII(p[0]) && p[1] == ':'; } + + static constexpr bool IsDrive(string_view p) noexcept { + return p.size() >= 2 && IsAlphaASCII(p[0]) && p[1] == ':'; + } #endif gcc_pure gcc_nonnull_all @@ -277,6 +305,9 @@ struct PathTraitsUTF8 { gcc_pure gcc_nonnull_all static string_view GetParent(const_pointer p) noexcept; + [[gnu::pure]] + static string_view GetParent(string_view p) noexcept; + /** * Determine the relative part of the given path to this * object, not including the directory separator. Returns an |