From b87d2790e7538f3bbab5e96b10aa0459808586f2 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 4 Jan 2024 00:59:21 +0300 Subject: [PATCH] v4: Avoid converting slashes in path root name in path::make_preferred. Similarly to other methods, make_preferred is only supposed to affect directory separators and not the slashes that are part of the path root name. --- doc/release_history.html | 2 +- doc/v4.html | 2 +- include/boost/filesystem/path.hpp | 24 +++++++++++++-------- src/path.cpp | 36 ++++++++++++++++++++++--------- test/path_test.cpp | 4 ++++ 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/doc/release_history.html b/doc/release_history.html index 823c0a2..3987b93 100644 --- a/doc/release_history.html +++ b/doc/release_history.html @@ -42,7 +42,7 @@

1.85.0

1.84.0

diff --git a/doc/v4.html b/doc/v4.html index 424afb4..5c43f1e 100644 --- a/doc/v4.html +++ b/doc/v4.html @@ -51,7 +51,7 @@ It removes the features that were deprecated in Ve
  • path::stem and path::extension no longer treat a filename that starts with a dot and has no other dots as an extension. Filenames starting with a dot are commonly treated as filenames with an empty extension. The leading dot is used to indicate a hidden file on most UNIX-like systems.
  • path::filename and path::iterator no longer return an implicit trailing dot (".") element if the path ends with a directory separator. Instead, an empty path is returned, similar to C++17 std::filesystem. This also affects other methods that are defined in terms of iterators or filename, such as path::stem, path::compare or lexicographical_compare. For example, path("a/b/") == path("a/b/.") no longer holds true.
  • path::lexically_normal no longer produces a trailing dot (".") element and omits a directory separator after a trailing dot-dot ("..") element in the normalized paths.
  • -
  • path::lexically_normal, path::generic_string and similar methods no longer convert between forward and backward slashes in root names of the returned paths.
  • +
  • path::lexically_normal, path::make_preferred, path::generic_string and similar methods no longer convert between forward and backward slashes in root names of the returned paths.
  • path appends consider root name and root directory of the appended path. If the appended path is absolute, or root name is present and differs from the source path, the resulting path is equivalent to the appended path. If root directory is present, the result is the root directory and relative path rebased on top of the root name of the source path. Otherwise, the behavior is similar to v3. This behavior is similar to C++17 std::filesystem.
  • path no longer supports construction, assignment or appending from containers of characters. Use string types or iterators as the source for these opereations instead.
  • path::remove_filename preserves the trailing directory separator, so that path::has_filename returns false after a successful call to path::remove_filename.
  • diff --git a/include/boost/filesystem/path.hpp b/include/boost/filesystem/path.hpp index 3503e2b..3385a1f 100644 --- a/include/boost/filesystem/path.hpp +++ b/include/boost/filesystem/path.hpp @@ -110,6 +110,11 @@ struct path_algorithms BOOST_FILESYSTEM_DECL static path generic_path_v3(path const& p); BOOST_FILESYSTEM_DECL static path generic_path_v4(path const& p); +#if defined(BOOST_WINDOWS_API) + BOOST_FILESYSTEM_DECL static void make_preferred_v3(path& p); + BOOST_FILESYSTEM_DECL static void make_preferred_v4(path& p); +#endif + BOOST_FILESYSTEM_DECL static int compare_v3(path const& left, path const& right); BOOST_FILESYSTEM_DECL static int compare_v4(path const& left, path const& right); @@ -886,15 +891,7 @@ public: // ----- modifiers ----- void clear() BOOST_NOEXCEPT { m_pathname.clear(); } -#ifdef BOOST_POSIX_API - path& make_preferred() - { - // No effect on POSIX - return *this; - } -#else // BOOST_WINDOWS_API - BOOST_FILESYSTEM_DECL path& make_preferred(); // change slashes to backslashes -#endif + path& make_preferred(); path& remove_filename(); BOOST_FILESYSTEM_DECL path& remove_filename_and_trailing_separators(); BOOST_FILESYSTEM_DECL path& remove_trailing_separator(); @@ -1741,6 +1738,15 @@ BOOST_FORCEINLINE path path::generic_path() const return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::generic_path)(*this); } +BOOST_FORCEINLINE path& path::make_preferred() +{ + // No effect on POSIX +#if defined(BOOST_WINDOWS_API) + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::make_preferred)(*this); +#endif + return *this; +} + namespace path_detail { BOOST_FORCEINLINE void path_iterator::increment() diff --git a/src/path.cpp b/src/path.cpp index a1bf98e..5396f5d 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -447,6 +447,32 @@ BOOST_FILESYSTEM_DECL path path_algorithms::generic_path_v4(path const& p) return tmp; } +#if defined(BOOST_WINDOWS_API) + +// make_preferred -------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL void path_algorithms::make_preferred_v3(path& p) +{ + std::replace(p.m_pathname.begin(), p.m_pathname.end(), L'/', L'\\'); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::make_preferred_v4(path& p) +{ + const size_type pathname_size = p.m_pathname.size(); + if (pathname_size > 0u) + { + value_type* const pathname = &p.m_pathname[0]; + + // Avoid converting slashes in the root name + size_type root_name_size = 0u; + find_root_directory_start(pathname, pathname_size, root_name_size); + + std::replace(pathname + root_name_size, pathname + pathname_size, L'/', L'\\'); + } +} + +#endif // defined(BOOST_WINDOWS_API) + // append --------------------------------------------------------------------------// BOOST_FILESYSTEM_DECL void path_algorithms::append_v3(path& p, const value_type* begin, const value_type* end) @@ -907,16 +933,6 @@ BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const return tmp; } -#if defined(BOOST_WINDOWS_API) - -BOOST_FILESYSTEM_DECL path& path::make_preferred() -{ - std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\'); - return *this; -} - -#endif // defined(BOOST_WINDOWS_API) - } // namespace filesystem } // namespace boost diff --git a/test/path_test.cpp b/test/path_test.cpp index ebaa4ea..4ac419c 100644 --- a/test/path_test.cpp +++ b/test/path_test.cpp @@ -2610,7 +2610,11 @@ void make_preferred_tests() if (platform == "Windows") { +#if BOOST_FILESYSTEM_VERSION == 3 BOOST_TEST(path("//abc\\def/ghi").make_preferred().native() == path("\\\\abc\\def\\ghi").native()); +#else + BOOST_TEST(path("//abc\\def/ghi").make_preferred().native() == path("//abc\\def\\ghi").native()); +#endif } else {