Skip to content

Commit 4b84226

Browse files
committed
Refactored path implementation for better support Windows path prefixes.
- Unified root name and root directory parsing that was scattered and duplicated across different algorithms. The new implementation is consolidated in a single function for parsing root name and root directory, which is used from various algorithms. - The new root name parsing now supports Windows local device ("\\.\") and NT path ("\??\") prefixes. It also adds support for filesystem ("\\?\") prefix to some of the higher level algorithms that were using custom parsing previously. Tests updated to verify these prefixes. - Some of the path decomposition methods were unified with presence checking methods (e.g. root_name with has_root_name). This makes these methods work consistently and also makes the has_* methods less expensive as they no longer have to construct a path only to check if it is empty. - The filename accessor no longer returns root name if the whole path only consists of a root name. This also affects stem and extension as those accessors are based on filename. This is a breaking change. - Cleaned up code: - Removed redundant checks for std::wstring support. - Added header/footer headers to globally disable compiler warnings. - Removed commented out super-deprecated code. - Added missing includes and removed includes that are not needed. - Nonessential code formatting.
1 parent af6ac28 commit 4b84226

24 files changed

+834
-566
lines changed

doc/release_history.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ <h2>1.77.0</h2>
5151
<li>In <code>canonical</code>, fixed the check for a symlink referencing a directory above root, if an earlier symlink was resolved to an absolute path with a different root from the original path.</li>
5252
<li>In <code>canonical</code>, added a limit for the maximum number of symlinks that can be resolved during the call. The limit is currently at least 40 symlinks.</li>
5353
<li><b>New:</b> Added <code>weakly_canonical</code> overloads taking <code>base</code> path as an argument.</li>
54+
<li><b>Breaking change:</b><code>path::filename</code>, <code>path::stem</code> and <code>path::extension</code> no longer consider root name of the path as a filename if the path only consists of a root name. For example, <code>path("C:").filename()</code> used to return "C:" on Windows and will return an empty path now.</li>
55+
<li><b>New:</b> Improved support for various path prefixes on Windows. Added support for local device prefix ("\\.\") and experimental support for NT path prefix ("\??\"). The prefixes will be included in the root name of a path.</li>
5456
</ul>
5557

5658
<h2>1.76.0</h2>

include/boost/filesystem/config.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
#undef BOOST_FILESYSTEM_NO_DEPRECATED // fixes #9454, src bld fails if NO_DEP defined
3737
#endif
3838

39+
#if defined(BOOST_FILESYSTEM_DEPRECATED) && defined(BOOST_FILESYSTEM_NO_DEPRECATED)
40+
#error Both BOOST_FILESYSTEM_DEPRECATED and BOOST_FILESYSTEM_NO_DEPRECATED are defined
41+
#endif
42+
3943
// throw an exception ----------------------------------------------------------------//
4044
//
4145
// Exceptions were originally thrown via boost::throw_exception().

include/boost/filesystem/convenience.hpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,11 @@
1313
#ifndef BOOST_FILESYSTEM3_CONVENIENCE_HPP
1414
#define BOOST_FILESYSTEM3_CONVENIENCE_HPP
1515

16-
#include <boost/config.hpp>
17-
18-
#if defined(BOOST_NO_STD_WSTRING)
19-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
20-
#endif
21-
16+
#include <boost/filesystem/config.hpp>
2217
#include <boost/filesystem/operations.hpp>
2318
#include <boost/system/error_code.hpp>
2419

25-
#include <boost/config/abi_prefix.hpp> // must be the last #include
20+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
2621

2722
namespace boost {
2823
namespace filesystem {
@@ -51,6 +46,6 @@ inline path change_extension(const path& p, const path& new_extension)
5146
} // namespace filesystem
5247
} // namespace boost
5348

54-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
49+
#include <boost/filesystem/detail/footer.hpp>
5550

5651
#endif // BOOST_FILESYSTEM3_CONVENIENCE_HPP
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright Andrey Semashev 2021.
3+
* Distributed under the Boost Software License, Version 1.0.
4+
* (See accompanying file LICENSE_1_0.txt or copy at
5+
* http://www.boost.org/LICENSE_1_0.txt)
6+
*/
7+
8+
#if !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS)
9+
10+
#if defined(_MSC_VER) && !defined(__clang__)
11+
12+
#pragma warning(pop)
13+
14+
#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
15+
&& (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__)
16+
17+
#pragma GCC diagnostic pop
18+
19+
#endif
20+
21+
#endif // !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS)
22+
23+
#include <boost/config/abi_suffix.hpp>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright Andrey Semashev 2021.
3+
* Distributed under the Boost Software License, Version 1.0.
4+
* (See accompanying file LICENSE_1_0.txt or copy at
5+
* http://www.boost.org/LICENSE_1_0.txt)
6+
*/
7+
8+
#include <boost/config/abi_prefix.hpp>
9+
10+
#if !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS)
11+
12+
#if defined(_MSC_VER) && !defined(__clang__)
13+
14+
#pragma warning(push, 3)
15+
// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
16+
#pragma warning(disable: 4251)
17+
// non dll-interface class 'A' used as base for dll-interface class 'B'
18+
#pragma warning(disable: 4275)
19+
// 'int' : forcing value to bool 'true' or 'false' (performance warning)
20+
#pragma warning(disable: 4800)
21+
// unreferenced formal parameter
22+
#pragma warning(disable: 4100)
23+
// conditional expression is constant
24+
#pragma warning(disable: 4127)
25+
// decorated name length exceeded, name was truncated
26+
#pragma warning(disable: 4503)
27+
// 'X': This function or variable may be unsafe. Consider using Y instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
28+
#pragma warning(disable: 4996)
29+
30+
#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
31+
&& (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__)
32+
33+
// Note: clang-cl goes here as well, as it seems to support gcc-style warning control pragmas.
34+
35+
#pragma GCC diagnostic push
36+
// unused parameter 'arg'
37+
#pragma GCC diagnostic ignored "-Wunused-parameter"
38+
39+
#endif
40+
41+
#endif // !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS)

include/boost/filesystem/directory.hpp

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@
1616
#ifndef BOOST_FILESYSTEM3_DIRECTORY_HPP
1717
#define BOOST_FILESYSTEM3_DIRECTORY_HPP
1818

19-
#include <boost/config.hpp>
20-
21-
#if defined(BOOST_NO_STD_WSTRING)
22-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
23-
#endif
24-
2519
#include <boost/filesystem/config.hpp>
2620
#include <boost/filesystem/path.hpp>
2721
#include <boost/filesystem/file_status.hpp>
@@ -39,7 +33,7 @@
3933
#include <boost/iterator/iterator_facade.hpp>
4034
#include <boost/iterator/iterator_categories.hpp>
4135

42-
#include <boost/config/abi_prefix.hpp> // must be the last #include
36+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
4337

4438
//--------------------------------------------------------------------------------------//
4539

@@ -63,12 +57,12 @@ class directory_entry
6357

6458
directory_entry() BOOST_NOEXCEPT {}
6559

66-
explicit directory_entry(const boost::filesystem::path& p) :
60+
explicit directory_entry(boost::filesystem::path const& p) :
6761
m_path(p), m_status(file_status()), m_symlink_status(file_status())
6862
{
6963
}
7064

71-
directory_entry(const boost::filesystem::path& p, file_status st, file_status symlink_st = file_status()) :
65+
directory_entry(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) :
7266
m_path(p), m_status(st), m_symlink_status(symlink_st)
7367
{
7468
}
@@ -107,14 +101,14 @@ class directory_entry
107101
}
108102
#endif
109103

110-
void assign(const boost::filesystem::path& p, file_status st = file_status(), file_status symlink_st = file_status())
104+
void assign(boost::filesystem::path const& p, file_status st = file_status(), file_status symlink_st = file_status())
111105
{
112106
m_path = p;
113107
m_status = st;
114108
m_symlink_status = symlink_st;
115109
}
116110

117-
void replace_filename(const boost::filesystem::path& p, file_status st = file_status(), file_status symlink_st = file_status())
111+
void replace_filename(boost::filesystem::path const& p, file_status st = file_status(), file_status symlink_st = file_status())
118112
{
119113
m_path.remove_filename();
120114
m_path /= p;
@@ -123,13 +117,13 @@ class directory_entry
123117
}
124118

125119
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
126-
void replace_leaf(const boost::filesystem::path& p, file_status st, file_status symlink_st)
120+
void replace_leaf(boost::filesystem::path const& p, file_status st, file_status symlink_st)
127121
{
128122
replace_filename(p, st, symlink_st);
129123
}
130124
#endif
131125

132-
const boost::filesystem::path& path() const BOOST_NOEXCEPT
126+
boost::filesystem::path const& path() const BOOST_NOEXCEPT
133127
{
134128
return m_path;
135129
}
@@ -163,7 +157,7 @@ class directory_entry
163157
//--------------------------------------------------------------------------------------//
164158

165159
// Without these functions, calling (for example) 'is_directory' with a 'directory_entry' results in:
166-
// - a conversion to 'path' using 'operator const boost::filesystem::path&()',
160+
// - a conversion to 'path' using 'operator boost::filesystem::path const&()',
167161
// - then a call to 'is_directory(path const& p)' which recomputes the status with 'detail::status(p)'.
168162
//
169163
// These functions avoid a costly recomputation of the status if one calls 'is_directory(e)' instead of 'is_directory(e.status())'
@@ -299,7 +293,6 @@ struct dir_itr_imp :
299293
}
300294
};
301295

302-
// see path::iterator: comment below
303296
BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, system::error_code* ec);
304297
BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec);
305298

@@ -378,7 +371,7 @@ class directory_iterator :
378371

379372
void increment() { detail::directory_iterator_increment(*this, 0); }
380373

381-
bool equal(const directory_iterator& rhs) const BOOST_NOEXCEPT
374+
bool equal(directory_iterator const& rhs) const BOOST_NOEXCEPT
382375
{
383376
return m_imp == rhs.m_imp || (is_end() && rhs.is_end());
384377
}
@@ -657,7 +650,7 @@ class recursive_directory_iterator :
657650

658651
void increment() { detail::recursive_directory_iterator_increment(*this, 0); }
659652

660-
bool equal(const recursive_directory_iterator& rhs) const BOOST_NOEXCEPT
653+
bool equal(recursive_directory_iterator const& rhs) const BOOST_NOEXCEPT
661654
{
662655
return m_imp == rhs.m_imp || (is_end() && rhs.is_end());
663656
}
@@ -744,6 +737,6 @@ struct range_const_iterator< boost::filesystem::recursive_directory_iterator, vo
744737

745738
} // namespace boost
746739

747-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
740+
#include <boost/filesystem/detail/footer.hpp>
748741

749742
#endif // BOOST_FILESYSTEM3_DIRECTORY_HPP

include/boost/filesystem/exception.hpp

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111
#ifndef BOOST_FILESYSTEM3_EXCEPTION_HPP
1212
#define BOOST_FILESYSTEM3_EXCEPTION_HPP
1313

14-
#include <boost/config.hpp>
15-
16-
#if defined(BOOST_NO_STD_WSTRING)
17-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
18-
#endif
19-
2014
#include <boost/filesystem/config.hpp>
2115
#include <boost/filesystem/path.hpp>
2216

@@ -26,15 +20,7 @@
2620
#include <boost/smart_ptr/intrusive_ptr.hpp>
2721
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
2822

29-
#include <boost/config/abi_prefix.hpp> // must be the last #include
30-
31-
#if defined(BOOST_MSVC)
32-
#pragma warning(push)
33-
// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
34-
#pragma warning(disable : 4251)
35-
// non dll-interface class 'A' used as base for dll-interface class 'B'
36-
#pragma warning(disable : 4275)
37-
#endif
23+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
3824

3925
namespace boost {
4026
namespace filesystem {
@@ -101,10 +87,6 @@ class BOOST_SYMBOL_VISIBLE filesystem_error :
10187
} // namespace filesystem
10288
} // namespace boost
10389

104-
#if defined(BOOST_MSVC)
105-
#pragma warning(pop)
106-
#endif
107-
108-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
90+
#include <boost/filesystem/detail/footer.hpp>
10991

11092
#endif // BOOST_FILESYSTEM3_EXCEPTION_HPP

include/boost/filesystem/file_status.hpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,10 @@
1616
#ifndef BOOST_FILESYSTEM3_FILE_STATUS_HPP
1717
#define BOOST_FILESYSTEM3_FILE_STATUS_HPP
1818

19-
#include <boost/config.hpp>
20-
21-
#if defined(BOOST_NO_STD_WSTRING)
22-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
23-
#endif
24-
2519
#include <boost/filesystem/config.hpp>
2620
#include <boost/detail/bitmask.hpp>
2721

28-
#include <boost/config/abi_prefix.hpp> // must be the last #include
22+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
2923

3024
//--------------------------------------------------------------------------------------//
3125

@@ -246,6 +240,6 @@ inline bool is_regular(file_status f) BOOST_NOEXCEPT
246240
} // namespace filesystem
247241
} // namespace boost
248242

249-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
243+
#include <boost/filesystem/detail/footer.hpp> // pops abi_prefix.hpp pragmas
250244

251245
#endif // BOOST_FILESYSTEM3_FILE_STATUS_HPP

include/boost/filesystem/fstream.hpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,12 @@
1212
#ifndef BOOST_FILESYSTEM3_FSTREAM_HPP
1313
#define BOOST_FILESYSTEM3_FSTREAM_HPP
1414

15-
#include <boost/config.hpp>
16-
17-
#if defined(BOOST_NO_STD_WSTRING)
18-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
19-
#endif
20-
15+
#include <boost/filesystem/config.hpp>
2116
#include <boost/filesystem/path.hpp>
2217
#include <iosfwd>
2318
#include <fstream>
2419

25-
#include <boost/config/abi_prefix.hpp> // must be the last #include
20+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
2621

2722
// on Windows, except for standard libaries known to have wchar_t overloads for
2823
// file stream I/O, use path::string() to get a narrow character c_str()
@@ -188,6 +183,6 @@ typedef basic_fstream< wchar_t > wfstream;
188183
#pragma warning(pop)
189184
#endif
190185

191-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
186+
#include <boost/filesystem/detail/footer.hpp>
192187

193188
#endif // BOOST_FILESYSTEM3_FSTREAM_HPP

include/boost/filesystem/operations.hpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@
1616
#ifndef BOOST_FILESYSTEM3_OPERATIONS_HPP
1717
#define BOOST_FILESYSTEM3_OPERATIONS_HPP
1818

19-
#include <boost/config.hpp>
20-
21-
#if defined(BOOST_NO_STD_WSTRING)
22-
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
23-
#endif
24-
2519
#include <boost/filesystem/config.hpp>
2620
#include <boost/filesystem/path.hpp>
2721
#include <boost/filesystem/file_status.hpp>
@@ -39,7 +33,7 @@
3933
#include <string>
4034
#include <ctime>
4135

42-
#include <boost/config/abi_prefix.hpp> // must be the last #include
36+
#include <boost/filesystem/detail/header.hpp> // must be the last #include
4337

4438
//--------------------------------------------------------------------------------------//
4539

@@ -720,6 +714,6 @@ BOOST_FILESYSTEM_DECL bool possible_large_file_size_support();
720714
} // namespace filesystem
721715
} // namespace boost
722716

723-
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
717+
#include <boost/filesystem/detail/footer.hpp>
724718

725719
#endif // BOOST_FILESYSTEM3_OPERATIONS_HPP

0 commit comments

Comments
 (0)