aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/filesystem
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2023-12-27 23:31:58 +0100
committerGitHub <noreply@github.com>2023-12-27 23:31:58 +0100
commitd67bfb4b4b7549081543e87a31bc6cb5c46ac973 (patch)
tree8674f2f1570877cb653e7ddcff37ba00288de15a /contrib/restricted/boost/filesystem
parent1f6bef05ed441c3aa2d565ac792b26cded704ac7 (diff)
downloadydb-d67bfb4b4b7549081543e87a31bc6cb5c46ac973.tar.gz
Import libs 4 (#758)
Diffstat (limited to 'contrib/restricted/boost/filesystem')
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/config.hpp29
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp9
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp737
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp514
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp48
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp105
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp1439
-rw-r--r--contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp384
-rw-r--r--contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp2
-rw-r--r--contrib/restricted/boost/filesystem/src/directory.cpp209
-rw-r--r--contrib/restricted/boost/filesystem/src/operations.cpp356
-rw-r--r--contrib/restricted/boost/filesystem/src/path.cpp1055
-rw-r--r--contrib/restricted/boost/filesystem/src/path_traits.cpp66
-rw-r--r--contrib/restricted/boost/filesystem/src/windows_tools.hpp14
-rw-r--r--contrib/restricted/boost/filesystem/ya.make6
15 files changed, 3144 insertions, 1829 deletions
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/config.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/config.hpp
index 68d0557fb4..cf7584a790 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/config.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/config.hpp
@@ -1,7 +1,7 @@
// boost/filesystem/v3/config.hpp ----------------------------------------------------//
// Copyright Beman Dawes 2003
-// Copyright Andrey Semashev 2021
+// Copyright Andrey Semashev 2021-2023
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -67,6 +67,15 @@
#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
#endif
+// Deprecated symbols markup -----------------------------------------------------------//
+
+#if !defined(BOOST_FILESYSTEM_ALLOW_DEPRECATED)
+#define BOOST_FILESYSTEM_DETAIL_DEPRECATED(msg) BOOST_DEPRECATED(msg)
+#else
+#define BOOST_FILESYSTEM_DETAIL_DEPRECATED(msg)
+#endif
+
+
// This header implements separate compilation features as described in
// http://www.boost.org/more/separate_compilation.html
@@ -122,4 +131,22 @@
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ||\
+ (defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 50000)) ||\
+ (defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION < 100))
+// Indicates that the standard library fstream types do not support move constructor/assignment.
+#define BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS
+#endif
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) && \
+ (\
+ (defined(BOOST_DINKUMWARE_STDLIB) && defined(_HAS_CXX23) && (_HAS_CXX23 != 0) && defined(_MSVC_STL_UPDATE) && (_MSVC_STL_UPDATE < 202208L)) || \
+ (defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 110400 || (BOOST_LIBSTDCXX_VERSION >= 120000 && BOOST_LIBSTDCXX_VERSION < 120200)) && (BOOST_CXX_VERSION > 202002L))\
+ )
+// Indicates that std::string_view has implicit constructor from ranges that was present in an early C++23 draft (N4892).
+// This was later rectified by marking the constructor explicit (https://wg21.link/p2499). Unfortunately, some compilers
+// were released with the constructor being implicit.
+#define BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR
+#endif
+
#endif // BOOST_FILESYSTEM_CONFIG_HPP
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp
index 10f49a658e..f98b0aba95 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp
@@ -28,6 +28,10 @@
#pragma warning(disable: 4503)
// '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.
#pragma warning(disable: 4996)
+// qualifier applied to function type has no meaning; ignored
+#pragma warning(disable: 4180)
+// qualifier applied to reference type; ignored
+#pragma warning(disable: 4181)
#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
&& (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__)
@@ -40,6 +44,11 @@
// unused function 'foo'
#pragma GCC diagnostic ignored "-Wunused-function"
+#if defined(__clang__)
+// template argument uses unnamed type
+#pragma clang diagnostic ignored "-Wunnamed-type-template-args"
+#endif // defined(__clang__)
+
#endif
#endif // !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS)
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp
new file mode 100644
index 0000000000..562b96764e
--- /dev/null
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp
@@ -0,0 +1,737 @@
+// filesystem path_traits.hpp --------------------------------------------------------//
+
+// Copyright Beman Dawes 2009
+// Copyright Andrey Semashev 2022
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+// Library home page: http://www.boost.org/libs/filesystem
+
+#ifndef BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP
+#define BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP
+
+#include <boost/filesystem/config.hpp>
+#include <cstddef>
+#include <cstring> // for strlen
+#include <cwchar> // for mbstate_t, wcslen
+#include <locale>
+#include <string>
+#include <iterator>
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+#include <string_view>
+#endif
+#include <boost/assert.hpp>
+#include <boost/system/error_category.hpp>
+#include <boost/iterator/is_iterator.hpp>
+#include <boost/type_traits/declval.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/conjunction.hpp>
+#if defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+#include <boost/type_traits/disjunction.hpp>
+#include <boost/core/enable_if.hpp>
+#endif
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4
+#include <vector>
+#include <list>
+#endif
+
+#include <boost/filesystem/detail/header.hpp> // must be the last #include
+
+namespace boost {
+
+template< typename, typename > class basic_string_view;
+
+namespace container {
+template< typename, typename, typename > class basic_string;
+} // namespace container
+
+namespace filesystem {
+
+BOOST_FILESYSTEM_DECL system::error_category const& codecvt_error_category() BOOST_NOEXCEPT;
+
+class directory_entry;
+
+namespace detail {
+namespace path_traits {
+
+#if defined(BOOST_WINDOWS_API)
+typedef wchar_t path_native_char_type;
+#define BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE false
+#define BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE true
+#else
+typedef char path_native_char_type;
+#define BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE true
+#define BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE false
+#endif
+
+typedef std::codecvt< wchar_t, char, std::mbstate_t > codecvt_type;
+
+struct unknown_type_tag {};
+struct ntcts_type_tag {};
+struct char_ptr_tag : ntcts_type_tag {};
+struct char_array_tag : ntcts_type_tag {};
+struct string_class_tag {};
+struct std_string_tag : string_class_tag {};
+struct boost_container_string_tag : string_class_tag {};
+struct std_string_view_tag : string_class_tag {};
+struct boost_string_view_tag : string_class_tag {};
+struct range_type_tag {};
+struct directory_entry_tag {};
+
+//! The traits define a number of properties of a path source
+template< typename T >
+struct path_source_traits
+{
+ //! The kind of the path source. Useful for dispatching.
+ typedef unknown_type_tag tag_type;
+ //! Character type that the source contains
+ typedef void char_type;
+ //! Indicates whether the source is natively supported by \c path::string_type as arguments for constructors/assignment/appending
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct path_source_traits< char* >
+{
+ typedef char_ptr_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< const char* >
+{
+ typedef char_ptr_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< wchar_t* >
+{
+ typedef char_ptr_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< >
+struct path_source_traits< const wchar_t* >
+{
+ typedef char_ptr_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< >
+struct path_source_traits< char[] >
+{
+ typedef char_array_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< const char[] >
+{
+ typedef char_array_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< wchar_t[] >
+{
+ typedef char_array_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< >
+struct path_source_traits< const wchar_t[] >
+{
+ typedef char_array_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< std::size_t N >
+struct path_source_traits< char[N] >
+{
+ typedef char_array_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< std::size_t N >
+struct path_source_traits< const char[N] >
+{
+ typedef char_array_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< std::size_t N >
+struct path_source_traits< wchar_t[N] >
+{
+ typedef char_array_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< std::size_t N >
+struct path_source_traits< const wchar_t[N] >
+{
+ typedef char_array_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< >
+struct path_source_traits< std::string >
+{
+ typedef std_string_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< std::wstring >
+{
+ typedef std_string_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+template< >
+struct path_source_traits< boost::container::basic_string< char, std::char_traits< char >, void > >
+{
+ typedef boost_container_string_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct path_source_traits< boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > >
+{
+ typedef boost_container_string_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< >
+struct path_source_traits< std::string_view >
+{
+ typedef std_string_view_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE;
+};
+
+template< >
+struct path_source_traits< std::wstring_view >
+{
+ typedef std_string_view_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE;
+};
+
+#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< >
+struct path_source_traits< boost::basic_string_view< char, std::char_traits< char > > >
+{
+ typedef boost_string_view_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct path_source_traits< boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > >
+{
+ typedef boost_string_view_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4
+template< >
+struct
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.")
+path_source_traits< std::vector< char > >
+{
+ // Since C++11 this could be string_class_tag as std::vector gained data() member
+ typedef range_type_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.")
+path_source_traits< std::vector< wchar_t > >
+{
+ // Since C++11 this could be string_class_tag as std::vector gained data() member
+ typedef range_type_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.")
+path_source_traits< std::list< char > >
+{
+ typedef range_type_tag tag_type;
+ typedef char char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+template< >
+struct
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.")
+path_source_traits< std::list< wchar_t > >
+{
+ typedef range_type_tag tag_type;
+ typedef wchar_t char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4
+
+template< >
+struct path_source_traits< directory_entry >
+{
+ typedef directory_entry_tag tag_type;
+ typedef path_native_char_type char_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_native = false;
+};
+
+#undef BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE
+#undef BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE
+
+
+//! The trait tests if the type is a known path Source tag
+template< typename Tag >
+struct is_known_path_source_tag :
+ public boost::true_type
+{
+};
+
+template< >
+struct is_known_path_source_tag< unknown_type_tag > :
+ public boost::false_type
+{
+};
+
+//! The trait tests if the type is compatible with path Source requirements
+template< typename T >
+struct is_path_source :
+ public is_known_path_source_tag< typename path_source_traits< T >::tag_type >::type
+{
+};
+
+
+//! The trait indicates whether the type is a path Source that is natively supported by path::string_type as the source for construction/assignment/appending
+template< typename T >
+struct is_native_path_source :
+ public boost::integral_constant< bool, path_source_traits< T >::is_native >
+{
+};
+
+
+//! The trait indicates whether the type is one of the supported path character types
+template< typename T >
+struct is_path_char_type :
+ public boost::false_type
+{
+};
+
+template< >
+struct is_path_char_type< char > :
+ public boost::true_type
+{
+};
+
+template< >
+struct is_path_char_type< wchar_t > :
+ public boost::true_type
+{
+};
+
+
+template< typename Iterator >
+struct is_iterator_to_path_chars :
+ public is_path_char_type< typename std::iterator_traits< Iterator >::value_type >::type
+{
+};
+
+//! The trait indicates whether the type is an iterator over a sequence of path characters
+template< typename Iterator >
+struct is_path_source_iterator :
+ public boost::conjunction<
+ boost::iterators::is_iterator< Iterator >,
+ is_iterator_to_path_chars< Iterator >
+ >::type
+{
+};
+
+
+//! The trait indicates whether the type is a pointer to a sequence of native path characters
+template< typename T >
+struct is_native_char_ptr :
+ public boost::false_type
+{
+};
+
+template< >
+struct is_native_char_ptr< path_native_char_type* > :
+ public boost::true_type
+{
+};
+
+template< >
+struct is_native_char_ptr< const path_native_char_type* > :
+ public boost::true_type
+{
+};
+
+
+//! Converts character encoding using the supplied codecvt facet. If \a cvt is \c NULL then \c path::codecvt() will be used.
+BOOST_FILESYSTEM_DECL
+void convert(const char* from, const char* from_end, std::wstring& to, const codecvt_type* cvt = NULL);
+
+//! \overload convert
+BOOST_FILESYSTEM_DECL
+void convert(const wchar_t* from, const wchar_t* from_end, std::string& to, const codecvt_type* cvt = NULL);
+
+
+// Source dispatch -----------------------------------------------------------------//
+
+template< typename Source, typename Callback >
+typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt = NULL);
+
+template< typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(const char* source, Callback cb, const codecvt_type* cvt, ntcts_type_tag)
+{
+ return cb(source, source + std::strlen(source), cvt);
+}
+
+template< typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(const wchar_t* source, Callback cb, const codecvt_type* cvt, ntcts_type_tag)
+{
+ return cb(source, source + std::wcslen(source), cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt, string_class_tag)
+{
+ return cb(source.data(), source.data() + source.size(), cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt, range_type_tag)
+{
+ std::basic_string< typename Source::value_type > src(source.begin(), source.end());
+ return cb(src.data(), src.data() + src.size(), cvt);
+}
+
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4
+
+template< typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(std::vector< char > const& source, Callback cb, const codecvt_type* cvt, range_type_tag)
+{
+ const char* data = NULL, *data_end = NULL;
+ if (!source.empty())
+ {
+ data = &source[0];
+ data_end = data + source.size();
+ }
+ return cb(data, data_end, cvt);
+}
+
+template< typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(std::vector< wchar_t > const& source, Callback cb, const codecvt_type* cvt, range_type_tag)
+{
+ const wchar_t* data = NULL, *data_end = NULL;
+ if (!source.empty())
+ {
+ data = &source[0];
+ data_end = data + source.size();
+ }
+ return cb(data, data_end, cvt);
+}
+
+#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4
+
+// Defined in directory.hpp to avoid circular header dependencies
+template< typename Callback >
+typename Callback::result_type dispatch(directory_entry const& de, Callback cb, const codecvt_type* cvt, directory_entry_tag);
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt)
+{
+ return path_traits::dispatch(source, cb, cvt,
+ typename path_traits::path_source_traits< typename boost::remove_cv< Source >::type >::tag_type());
+}
+
+
+typedef char yes_type;
+struct no_type { char buf[2]; };
+
+#if !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+namespace is_convertible_to_path_source_impl {
+
+yes_type check(const char*);
+yes_type check(const wchar_t*);
+yes_type check(std::string const&);
+yes_type check(std::wstring const&);
+yes_type check(boost::container::basic_string< char, std::char_traits< char >, void > const&);
+yes_type check(boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const&);
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+yes_type check(std::string_view const&);
+yes_type check(std::wstring_view const&);
+#endif
+yes_type check(boost::basic_string_view< char, std::char_traits< char > > const&);
+yes_type check(boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const&);
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+no_type check(std::nullptr_t);
+#endif
+no_type check(...);
+
+} // namespace is_convertible_to_path_source_impl
+
+//! The type trait indicates whether the type has a conversion path to one of the path source types
+template< typename T >
+struct is_convertible_to_path_source :
+ public boost::integral_constant<
+ bool,
+ sizeof(is_convertible_to_path_source_impl::check(boost::declval< T const& >())) == sizeof(yes_type)
+ >
+{
+};
+
+#else // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+// Note: We use separate checks for convertibility to std::string_view and other types to avoid ambiguity with an implicit range constructor
+// of std::string_view in the early C++23 draft (N4892). If a user's type is convertible to e.g. std::string and also satisfies
+// ranges::contiguous_range and ranges::sized_range concepts then the conversion is ambiguous: the type is convertible to std::string
+// through the conversion operator in the user's class and is also convertible to std::string_view through the implicit conversion
+// constructor in std::string_view. The solution is to check convertibility to std::string_view separately first.
+
+namespace is_convertible_to_std_string_view_impl {
+
+yes_type check(std::string_view const&);
+yes_type check(std::wstring_view const&);
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+no_type check(std::nullptr_t);
+#endif
+no_type check(...);
+
+} // namespace is_convertible_to_std_string_view_impl
+
+template< typename T >
+struct is_convertible_to_std_string_view :
+ public boost::integral_constant<
+ bool,
+ sizeof(is_convertible_to_std_string_view_impl::check(boost::declval< T const& >())) == sizeof(yes_type)
+ >
+{
+};
+
+namespace is_convertible_to_path_source_non_std_string_view_impl {
+
+yes_type check(const char*);
+yes_type check(const wchar_t*);
+yes_type check(std::string const&);
+yes_type check(std::wstring const&);
+yes_type check(boost::container::basic_string< char, std::char_traits< char >, void > const&);
+yes_type check(boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const&);
+yes_type check(boost::basic_string_view< char, std::char_traits< char > > const&);
+yes_type check(boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const&);
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+no_type check(std::nullptr_t);
+#endif
+no_type check(...);
+
+} // namespace is_convertible_to_path_source_non_std_string_view_impl
+
+template< typename T >
+struct is_convertible_to_path_source_non_std_string_view :
+ public boost::integral_constant<
+ bool,
+ sizeof(is_convertible_to_path_source_non_std_string_view_impl::check(boost::declval< T const& >())) == sizeof(yes_type)
+ >
+{
+};
+
+//! The type trait indicates whether the type has a conversion path to one of the path source types
+template< typename T >
+struct is_convertible_to_path_source :
+ public boost::disjunction<
+ is_convertible_to_std_string_view< T >,
+ is_convertible_to_path_source_non_std_string_view< T >
+ >::type
+{
+};
+
+#endif // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+//! The type trait makes \a T dependent on the second template argument. Used to delay type resolution and name binding.
+template< typename T, typename >
+struct make_dependent
+{
+ typedef T type;
+};
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(const char* source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< const char*, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(const wchar_t* source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< const wchar_t*, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::string const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::string, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::wstring const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::wstring, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl
+(
+ boost::container::basic_string< char, std::char_traits< char >, void > const& source,
+ Callback cb,
+ const codecvt_type* cvt
+)
+{
+ typedef typename path_traits::make_dependent< boost::container::basic_string< char, std::char_traits< char >, void >, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl
+(
+ boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const& source,
+ Callback cb,
+ const codecvt_type* cvt
+)
+{
+ typedef typename path_traits::make_dependent< boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void >, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl
+(
+ boost::basic_string_view< char, std::char_traits< char > > const& source,
+ Callback cb,
+ const codecvt_type* cvt
+)
+{
+ typedef typename path_traits::make_dependent< boost::basic_string_view< char, std::char_traits< char > >, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl
+(
+ boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const& source,
+ Callback cb,
+ const codecvt_type* cvt
+)
+{
+ typedef typename path_traits::make_dependent< boost::basic_string_view< wchar_t, std::char_traits< wchar_t > >, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+#if !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::string_view const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::string_view, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::wstring_view const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::wstring_view, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL)
+{
+ typedef typename boost::remove_cv< Source >::type source_t;
+ return path_traits::dispatch_convertible_impl< source_t >(source, cb, cvt);
+}
+
+#else // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_sv_impl(std::string_view const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::string_view, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_sv_impl(std::wstring_view const& source, Callback cb, const codecvt_type* cvt)
+{
+ typedef typename path_traits::make_dependent< std::wstring_view, Source >::type source_t;
+ return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename boost::disable_if_c<
+ is_convertible_to_std_string_view< typename boost::remove_cv< Source >::type >::value,
+ typename Callback::result_type
+>::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL)
+{
+ typedef typename boost::remove_cv< Source >::type source_t;
+ return path_traits::dispatch_convertible_impl< source_t >(source, cb, cvt);
+}
+
+template< typename Source, typename Callback >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ is_convertible_to_std_string_view< typename boost::remove_cv< Source >::type >::value,
+ typename Callback::result_type
+>::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL)
+{
+ typedef typename boost::remove_cv< Source >::type source_t;
+ return path_traits::dispatch_convertible_sv_impl< source_t >(source, cb, cvt);
+}
+
+#endif // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR)
+
+} // namespace path_traits
+} // namespace detail
+} // namespace filesystem
+} // namespace boost
+
+#include <boost/filesystem/detail/footer.hpp>
+
+#endif // BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp
index 68b13638e1..2afcfb6735 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp
@@ -4,7 +4,7 @@
// Copyright Jan Langer 2002
// Copyright Dietmar Kuehl 2001
// Copyright Vladimir Prus 2002
-// Copyright Andrey Semashev 2019
+// Copyright Andrey Semashev 2019, 2022
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -19,11 +19,11 @@
#include <boost/filesystem/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/file_status.hpp>
+#include <boost/filesystem/detail/path_traits.hpp>
#include <cstddef>
#include <string>
#include <vector>
-#include <utility> // std::move
#include <boost/assert.hpp>
#include <boost/core/scoped_enum.hpp>
@@ -41,6 +41,17 @@
namespace boost {
namespace filesystem {
+class directory_iterator;
+
+namespace detail {
+
+struct directory_iterator_params;
+
+BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec);
+BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec);
+
+} // namespace detail
+
//--------------------------------------------------------------------------------------//
// //
// directory_entry //
@@ -53,20 +64,30 @@ namespace filesystem {
class directory_entry
{
+ friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, detail::directory_iterator_params* params, system::error_code* ec);
+ friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec);
+
public:
typedef boost::filesystem::path::value_type value_type; // enables class path ctor taking directory_entry
directory_entry() BOOST_NOEXCEPT {}
- explicit directory_entry(boost::filesystem::path const& p) :
- m_path(p), m_status(file_status()), m_symlink_status(file_status())
+ explicit directory_entry(boost::filesystem::path const& p);
+
+#if BOOST_FILESYSTEM_VERSION >= 4
+ directory_entry(boost::filesystem::path const& p, system::error_code& ec) :
+ m_path(p)
{
+ refresh_impl(&ec);
+ if (ec)
+ m_path.clear();
}
-
+#else
directory_entry(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) :
m_path(p), m_status(st), m_symlink_status(symlink_st)
{
}
+#endif
directory_entry(directory_entry const& rhs) :
m_path(rhs.m_path), m_status(rhs.m_status), m_symlink_status(rhs.m_symlink_status)
@@ -87,69 +108,349 @@ public:
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
directory_entry(directory_entry&& rhs) BOOST_NOEXCEPT :
- m_path(std::move(rhs.m_path)),
- m_status(std::move(rhs.m_status)),
- m_symlink_status(std::move(rhs.m_symlink_status))
+ m_path(static_cast< boost::filesystem::path&& >(rhs.m_path)),
+ m_status(static_cast< file_status&& >(rhs.m_status)),
+ m_symlink_status(static_cast< file_status&& >(rhs.m_symlink_status))
{
}
directory_entry& operator=(directory_entry&& rhs) BOOST_NOEXCEPT
{
- m_path = std::move(rhs.m_path);
- m_status = std::move(rhs.m_status);
- m_symlink_status = std::move(rhs.m_symlink_status);
+ m_path = static_cast< boost::filesystem::path&& >(rhs.m_path);
+ m_status = static_cast< file_status&& >(rhs.m_status);
+ m_symlink_status = static_cast< file_status&& >(rhs.m_symlink_status);
return *this;
}
+
+ void assign(boost::filesystem::path&& p);
+
+#if BOOST_FILESYSTEM_VERSION >= 4
+ void assign(boost::filesystem::path&& p, system::error_code& ec)
+ {
+ m_path = static_cast< boost::filesystem::path&& >(p);
+ refresh_impl(&ec);
+ }
+#else
+ void assign(boost::filesystem::path&& p, file_status st, file_status symlink_st = file_status())
+ {
+ assign_with_status(static_cast< boost::filesystem::path&& >(p), st, symlink_st);
+ }
#endif
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- void assign(boost::filesystem::path const& p, file_status st = file_status(), file_status symlink_st = file_status())
+ void assign(boost::filesystem::path const& p);
+
+#if BOOST_FILESYSTEM_VERSION >= 4
+ void assign(boost::filesystem::path const& p, system::error_code& ec)
{
m_path = p;
- m_status = st;
- m_symlink_status = symlink_st;
+ refresh_impl(&ec);
+ }
+#else
+ void assign(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status())
+ {
+ assign_with_status(p, st, symlink_st);
}
+#endif
+
+ void replace_filename(boost::filesystem::path const& p);
- void replace_filename(boost::filesystem::path const& p, file_status st = file_status(), file_status symlink_st = file_status())
+#if BOOST_FILESYSTEM_VERSION >= 4
+ void replace_filename(boost::filesystem::path const& p, system::error_code& ec)
{
- m_path.remove_filename();
- m_path /= p;
- m_status = st;
- m_symlink_status = symlink_st;
+ m_path.replace_filename(p);
+ refresh_impl(&ec);
+ }
+#else
+ void replace_filename(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status())
+ {
+ replace_filename_with_status(p, st, symlink_st);
}
-#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_entry::replace_filename() instead")
void replace_leaf(boost::filesystem::path const& p, file_status st, file_status symlink_st)
{
- replace_filename(p, st, symlink_st);
+ replace_filename_with_status(p, st, symlink_st);
}
#endif
- boost::filesystem::path const& path() const BOOST_NOEXCEPT
+ boost::filesystem::path const& path() const BOOST_NOEXCEPT { return m_path; }
+ operator boost::filesystem::path const&() const BOOST_NOEXCEPT { return m_path; }
+
+ void refresh() { refresh_impl(); }
+ void refresh(system::error_code& ec) BOOST_NOEXCEPT { refresh_impl(&ec); }
+
+ file_status status() const
{
- return m_path;
+ if (!filesystem::status_known(m_status))
+ refresh_impl();
+ return m_status;
+ }
+
+ file_status status(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ if (!filesystem::status_known(m_status))
+ refresh_impl(&ec);
+ return m_status;
+ }
+
+ file_status symlink_status() const
+ {
+ if (!filesystem::status_known(m_symlink_status))
+ refresh_impl();
+ return m_symlink_status;
+ }
+
+ file_status symlink_status(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ if (!filesystem::status_known(m_symlink_status))
+ refresh_impl(&ec);
+ return m_symlink_status;
+ }
+
+ filesystem::file_type file_type() const
+ {
+ if (!filesystem::type_present(m_status))
+ refresh_impl();
+ return m_status.type();
+ }
+
+ filesystem::file_type file_type(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ if (!filesystem::type_present(m_status))
+ refresh_impl(&ec);
+ return m_status.type();
+ }
+
+ filesystem::file_type symlink_file_type() const
+ {
+ if (!filesystem::type_present(m_symlink_status))
+ refresh_impl();
+ return m_symlink_status.type();
+ }
+
+ filesystem::file_type symlink_file_type(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ if (!filesystem::type_present(m_symlink_status))
+ refresh_impl(&ec);
+ return m_symlink_status.type();
+ }
+
+ bool exists() const
+ {
+ filesystem::file_type ft = this->file_type();
+ return ft != filesystem::status_error && ft != filesystem::file_not_found;
+ }
+
+ bool exists(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ filesystem::file_type ft = this->file_type(ec);
+ return ft != filesystem::status_error && ft != filesystem::file_not_found;
+ }
+
+ bool is_regular_file() const
+ {
+ return this->file_type() == filesystem::regular_file;
+ }
+
+ bool is_regular_file(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::regular_file;
+ }
+
+ bool is_directory() const
+ {
+ return this->file_type() == filesystem::directory_file;
+ }
+
+ bool is_directory(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::directory_file;
+ }
+
+ bool is_symlink() const
+ {
+ return this->symlink_file_type() == filesystem::symlink_file;
+ }
+
+ bool is_symlink(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->symlink_file_type(ec) == filesystem::symlink_file;
}
- operator boost::filesystem::path const&() const BOOST_NOEXCEPT { return m_path; }
- file_status status() const { return get_status(); }
- file_status status(system::error_code& ec) const BOOST_NOEXCEPT { return get_status(&ec); }
- file_status symlink_status() const { return get_symlink_status(); }
- file_status symlink_status(system::error_code& ec) const BOOST_NOEXCEPT { return get_symlink_status(&ec); }
-
- bool operator==(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path == rhs.m_path; }
- bool operator!=(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path != rhs.m_path; }
- bool operator<(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path < rhs.m_path; }
- bool operator<=(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path <= rhs.m_path; }
- bool operator>(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path > rhs.m_path; }
- bool operator>=(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path >= rhs.m_path; }
+
+ bool is_block_file() const
+ {
+ return this->file_type() == filesystem::block_file;
+ }
+
+ bool is_block_file(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::block_file;
+ }
+
+ bool is_character_file() const
+ {
+ return this->file_type() == filesystem::character_file;
+ }
+
+ bool is_character_file(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::character_file;
+ }
+
+ bool is_fifo() const
+ {
+ return this->file_type() == filesystem::fifo_file;
+ }
+
+ bool is_fifo(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::fifo_file;
+ }
+
+ bool is_socket() const
+ {
+ return this->file_type() == filesystem::socket_file;
+ }
+
+ bool is_socket(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->file_type(ec) == filesystem::socket_file;
+ }
+
+ bool is_reparse_file() const
+ {
+ return this->symlink_file_type() == filesystem::reparse_file;
+ }
+
+ bool is_reparse_file(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ return this->symlink_file_type(ec) == filesystem::reparse_file;
+ }
+
+ bool is_other() const
+ {
+ filesystem::file_type ft = this->file_type();
+ return ft != filesystem::status_error && ft != filesystem::file_not_found &&
+ ft != filesystem::regular_file && ft != filesystem::directory_file;
+ }
+
+ bool is_other(system::error_code& ec) const BOOST_NOEXCEPT
+ {
+ filesystem::file_type ft = this->file_type(ec);
+ return ft != filesystem::status_error && ft != filesystem::file_not_found &&
+ ft != filesystem::regular_file && ft != filesystem::directory_file;
+ }
+
+ bool operator==(directory_entry const& rhs) const { return m_path == rhs.m_path; }
+ bool operator!=(directory_entry const& rhs) const { return m_path != rhs.m_path; }
+ bool operator<(directory_entry const& rhs) const { return m_path < rhs.m_path; }
+ bool operator<=(directory_entry const& rhs) const { return m_path <= rhs.m_path; }
+ bool operator>(directory_entry const& rhs) const { return m_path > rhs.m_path; }
+ bool operator>=(directory_entry const& rhs) const { return m_path >= rhs.m_path; }
private:
- BOOST_FILESYSTEM_DECL file_status get_status(system::error_code* ec = NULL) const;
- BOOST_FILESYSTEM_DECL file_status get_symlink_status(system::error_code* ec = NULL) const;
+ BOOST_FILESYSTEM_DECL void refresh_impl(system::error_code* ec = NULL) const;
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ void assign_with_status(boost::filesystem::path&& p, file_status st, file_status symlink_st)
+ {
+ m_path = static_cast< boost::filesystem::path&& >(p);
+ m_status = static_cast< file_status&& >(st);
+ m_symlink_status = static_cast< file_status&& >(symlink_st);
+ }
+#endif
+
+ void assign_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st)
+ {
+ m_path = p;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ m_status = static_cast< file_status&& >(st);
+ m_symlink_status = static_cast< file_status&& >(symlink_st);
+#else
+ m_status = st;
+ m_symlink_status = symlink_st;
+#endif
+ }
+
+ void replace_filename_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st)
+ {
+ m_path.replace_filename(p);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ m_status = static_cast< file_status&& >(st);
+ m_symlink_status = static_cast< file_status&& >(symlink_st);
+#else
+ m_status = st;
+ m_symlink_status = symlink_st;
+#endif
+ }
private:
boost::filesystem::path m_path;
mutable file_status m_status; // stat()-like
mutable file_status m_symlink_status; // lstat()-like
-}; // directory_entry
+};
+
+#if !defined(BOOST_FILESYSTEM_SOURCE)
+
+inline directory_entry::directory_entry(boost::filesystem::path const& p) :
+ m_path(p)
+{
+#if BOOST_FILESYSTEM_VERSION >= 4
+ refresh_impl();
+#endif
+}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+inline void directory_entry::assign(boost::filesystem::path&& p)
+{
+ m_path = static_cast< boost::filesystem::path&& >(p);
+#if BOOST_FILESYSTEM_VERSION >= 4
+ refresh_impl();
+#else
+ m_status = file_status();
+ m_symlink_status = file_status();
+#endif
+}
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+inline void directory_entry::assign(boost::filesystem::path const& p)
+{
+ m_path = p;
+#if BOOST_FILESYSTEM_VERSION >= 4
+ refresh_impl();
+#else
+ m_status = file_status();
+ m_symlink_status = file_status();
+#endif
+}
+
+inline void directory_entry::replace_filename(boost::filesystem::path const& p)
+{
+ m_path.replace_filename(p);
+#if BOOST_FILESYSTEM_VERSION >= 4
+ refresh_impl();
+#else
+ m_status = file_status();
+ m_symlink_status = file_status();
+#endif
+}
+
+#endif // !defined(BOOST_FILESYSTEM_SOURCE)
+
+namespace detail {
+namespace path_traits {
+
+// Dispatch function for integration with path class
+template< typename Callback >
+BOOST_FORCEINLINE typename Callback::result_type dispatch(directory_entry const& de, Callback cb, const codecvt_type* cvt, directory_entry_tag)
+{
+ boost::filesystem::path::string_type const& source = de.path().native();
+ return cb(source.data(), source.data() + source.size(), cvt);
+}
+
+} // namespace path_traits
+} // namespace detail
//--------------------------------------------------------------------------------------//
// //
@@ -167,70 +468,147 @@ inline file_status status(directory_entry const& e)
{
return e.status();
}
+
inline file_status status(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
return e.status(ec);
}
+
+inline file_status symlink_status(directory_entry const& e)
+{
+ return e.symlink_status();
+}
+
+inline file_status symlink_status(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.symlink_status(ec);
+}
+
inline bool type_present(directory_entry const& e)
{
- return filesystem::type_present(e.status());
+ return e.file_type() != filesystem::status_error;
}
+
inline bool type_present(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::type_present(e.status(ec));
+ return e.file_type(ec) != filesystem::status_error;
}
+
inline bool status_known(directory_entry const& e)
{
return filesystem::status_known(e.status());
}
+
inline bool status_known(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
return filesystem::status_known(e.status(ec));
}
+
inline bool exists(directory_entry const& e)
{
- return filesystem::exists(e.status());
+ return e.exists();
}
+
inline bool exists(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::exists(e.status(ec));
+ return e.exists(ec);
}
+
inline bool is_regular_file(directory_entry const& e)
{
- return filesystem::is_regular_file(e.status());
+ return e.is_regular_file();
}
+
inline bool is_regular_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::is_regular_file(e.status(ec));
+ return e.is_regular_file(ec);
}
+
inline bool is_directory(directory_entry const& e)
{
- return filesystem::is_directory(e.status());
+ return e.is_directory();
}
+
inline bool is_directory(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::is_directory(e.status(ec));
+ return e.is_directory(ec);
}
+
inline bool is_symlink(directory_entry const& e)
{
- return filesystem::is_symlink(e.symlink_status());
+ return e.is_symlink();
}
+
inline bool is_symlink(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::is_symlink(e.symlink_status(ec));
+ return e.is_symlink(ec);
+}
+
+inline bool is_block_file(directory_entry const& e)
+{
+ return e.is_block_file();
+}
+
+inline bool is_block_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.is_block_file(ec);
+}
+
+inline bool is_character_file(directory_entry const& e)
+{
+ return e.is_character_file();
+}
+
+inline bool is_character_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.is_character_file(ec);
}
+
+inline bool is_fifo(directory_entry const& e)
+{
+ return e.is_fifo();
+}
+
+inline bool is_fifo(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.is_fifo(ec);
+}
+
+inline bool is_socket(directory_entry const& e)
+{
+ return e.is_socket();
+}
+
+inline bool is_socket(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.is_socket(ec);
+}
+
+inline bool is_reparse_file(directory_entry const& e)
+{
+ return e.is_reparse_file();
+}
+
+inline bool is_reparse_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return e.is_reparse_file(ec);
+}
+
inline bool is_other(directory_entry const& e)
{
- return filesystem::is_other(e.status());
+ return e.is_other();
}
+
inline bool is_other(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT
{
- return filesystem::is_other(e.status(ec));
+ return e.is_other(ec);
}
+
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead")
inline bool is_regular(directory_entry const& e)
{
- return filesystem::is_regular(e.status());
+ return filesystem::is_regular_file(e);
}
#endif
@@ -243,20 +621,18 @@ inline bool is_regular(directory_entry const& e)
BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(directory_options, unsigned int)
{
none = 0u,
- skip_permission_denied = 1u, // if a directory cannot be opened because of insufficient permissions, pretend that the directory is empty
- follow_directory_symlink = 1u << 1, // recursive_directory_iterator: follow directory symlinks
- skip_dangling_symlinks = 1u << 2, // non-standard extension for recursive_directory_iterator: don't follow dangling directory symlinks,
- pop_on_error = 1u << 3, // non-standard extension for recursive_directory_iterator: instead of producing an end iterator on errors,
- // repeatedly invoke pop() until it succeeds or the iterator becomes equal to end iterator
- _detail_no_follow = 1u << 4, // internal use only
- _detail_no_push = 1u << 5 // internal use only
+ skip_permission_denied = 1u, // if a directory cannot be opened because of insufficient permissions, pretend that the directory is empty
+ follow_directory_symlink = 1u << 1u, // recursive_directory_iterator: follow directory symlinks
+ skip_dangling_symlinks = 1u << 2u, // non-standard extension for recursive_directory_iterator: don't follow dangling directory symlinks,
+ pop_on_error = 1u << 3u, // non-standard extension for recursive_directory_iterator: instead of producing an end iterator on errors,
+ // repeatedly invoke pop() until it succeeds or the iterator becomes equal to end iterator
+ _detail_no_follow = 1u << 4u, // internal use only
+ _detail_no_push = 1u << 5u // internal use only
}
BOOST_SCOPED_ENUM_DECLARE_END(directory_options)
BOOST_BITMASK(BOOST_SCOPED_ENUM_NATIVE(directory_options))
-class directory_iterator;
-
namespace detail {
struct dir_itr_imp :
@@ -286,11 +662,6 @@ struct dir_itr_imp :
BOOST_FILESYSTEM_DECL static void operator delete(void* p) BOOST_NOEXCEPT;
};
-struct directory_iterator_params;
-
-BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec);
-BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec);
-
} // namespace detail
//--------------------------------------------------------------------------------------//
@@ -336,13 +707,13 @@ public:
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
directory_iterator(directory_iterator&& that) BOOST_NOEXCEPT :
- m_imp(std::move(that.m_imp))
+ m_imp(static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp))
{
}
directory_iterator& operator=(directory_iterator&& that) BOOST_NOEXCEPT
{
- m_imp = std::move(that.m_imp);
+ m_imp = static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp);
return *this;
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -540,11 +911,13 @@ public:
#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
// Deprecated constructors
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_options instead of symlink_option")
recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts)
{
detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), NULL);
}
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_options instead of symlink_option")
recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts, system::error_code& ec) BOOST_NOEXCEPT
{
detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), &ec);
@@ -556,13 +929,13 @@ public:
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
recursive_directory_iterator(recursive_directory_iterator&& that) BOOST_NOEXCEPT :
- m_imp(std::move(that.m_imp))
+ m_imp(static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp))
{
}
recursive_directory_iterator& operator=(recursive_directory_iterator&& that) BOOST_NOEXCEPT
{
- m_imp = std::move(that.m_imp);
+ m_imp = static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp);
return *this;
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -586,6 +959,7 @@ public:
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator::depth() instead")
int level() const BOOST_NOEXCEPT
{
return depth();
@@ -614,6 +988,7 @@ public:
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator::disable_recursion_pending() instead")
void no_push(bool value = true) BOOST_NOEXCEPT
{
disable_recursion_pending(value);
@@ -664,6 +1039,7 @@ private:
};
#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator instead")
typedef recursive_directory_iterator wrecursive_directory_iterator;
#endif
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp
index 90eca99e84..fb36240127 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp
@@ -155,13 +155,13 @@ public:
// Note: std::move is not constexpr in C++11, that's why we're not using it here
BOOST_CONSTEXPR file_status(file_status&& rhs) BOOST_NOEXCEPT :
m_value(static_cast< file_type&& >(rhs.m_value)),
- m_perms(static_cast< enum perms&& >(rhs.m_perms))
+ m_perms(static_cast< perms&& >(rhs.m_perms))
{
}
BOOST_CXX14_CONSTEXPR file_status& operator=(file_status&& rhs) BOOST_NOEXCEPT
{
m_value = static_cast< file_type&& >(rhs.m_value);
- m_perms = static_cast< enum perms&& >(rhs.m_perms);
+ m_perms = static_cast< perms&& >(rhs.m_perms);
return *this;
}
#endif
@@ -174,28 +174,28 @@ public:
BOOST_CXX14_CONSTEXPR void type(file_type v) BOOST_NOEXCEPT { m_value = v; }
BOOST_CXX14_CONSTEXPR void permissions(perms prms) BOOST_NOEXCEPT { m_perms = prms; }
- BOOST_CONSTEXPR bool operator==(const file_status& rhs) const BOOST_NOEXCEPT
+ BOOST_CONSTEXPR bool operator==(file_status const& rhs) const BOOST_NOEXCEPT
{
return type() == rhs.type() && permissions() == rhs.permissions();
}
- BOOST_CONSTEXPR bool operator!=(const file_status& rhs) const BOOST_NOEXCEPT
+ BOOST_CONSTEXPR bool operator!=(file_status const& rhs) const BOOST_NOEXCEPT
{
return !(*this == rhs);
}
private:
file_type m_value;
- enum perms m_perms;
+ perms m_perms;
};
inline BOOST_CONSTEXPR bool type_present(file_status f) BOOST_NOEXCEPT
{
- return f.type() != status_error;
+ return f.type() != filesystem::status_error;
}
inline BOOST_CONSTEXPR bool permissions_present(file_status f) BOOST_NOEXCEPT
{
- return f.permissions() != perms_not_known;
+ return f.permissions() != filesystem::perms_not_known;
}
inline BOOST_CONSTEXPR bool status_known(file_status f) BOOST_NOEXCEPT
@@ -205,22 +205,47 @@ inline BOOST_CONSTEXPR bool status_known(file_status f) BOOST_NOEXCEPT
inline BOOST_CONSTEXPR bool exists(file_status f) BOOST_NOEXCEPT
{
- return f.type() != status_error && f.type() != file_not_found;
+ return f.type() != filesystem::status_error && f.type() != filesystem::file_not_found;
}
inline BOOST_CONSTEXPR bool is_regular_file(file_status f) BOOST_NOEXCEPT
{
- return f.type() == regular_file;
+ return f.type() == filesystem::regular_file;
}
inline BOOST_CONSTEXPR bool is_directory(file_status f) BOOST_NOEXCEPT
{
- return f.type() == directory_file;
+ return f.type() == filesystem::directory_file;
}
inline BOOST_CONSTEXPR bool is_symlink(file_status f) BOOST_NOEXCEPT
{
- return f.type() == symlink_file;
+ return f.type() == filesystem::symlink_file;
+}
+
+inline BOOST_CONSTEXPR bool is_block_file(file_status f) BOOST_NOEXCEPT
+{
+ return f.type() == filesystem::block_file;
+}
+
+inline BOOST_CONSTEXPR bool is_character_file(file_status f) BOOST_NOEXCEPT
+{
+ return f.type() == filesystem::character_file;
+}
+
+inline BOOST_CONSTEXPR bool is_fifo(file_status f) BOOST_NOEXCEPT
+{
+ return f.type() == filesystem::fifo_file;
+}
+
+inline BOOST_CONSTEXPR bool is_socket(file_status f) BOOST_NOEXCEPT
+{
+ return f.type() == filesystem::socket_file;
+}
+
+inline BOOST_CONSTEXPR bool is_reparse_file(file_status f) BOOST_NOEXCEPT
+{
+ return f.type() == filesystem::reparse_file;
}
inline BOOST_CONSTEXPR bool is_other(file_status f) BOOST_NOEXCEPT
@@ -229,6 +254,7 @@ inline BOOST_CONSTEXPR bool is_other(file_status f) BOOST_NOEXCEPT
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead")
inline bool is_regular(file_status f) BOOST_NOEXCEPT
{
return filesystem::is_regular_file(f);
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp
index 856de7c1a5..0b7f736878 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp
@@ -176,7 +176,7 @@ inline file_status status(path const& p)
return detail::status(p);
}
-inline file_status status(path const& p, system::error_code& ec)
+inline file_status status(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
return detail::status(p, &ec);
}
@@ -186,70 +186,122 @@ inline file_status symlink_status(path const& p)
return detail::symlink_status(p);
}
-inline file_status symlink_status(path const& p, system::error_code& ec)
+inline file_status symlink_status(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
return detail::symlink_status(p, &ec);
}
inline bool exists(path const& p)
{
- return exists(detail::status(p));
+ return filesystem::exists(detail::status(p));
}
-inline bool exists(path const& p, system::error_code& ec)
+inline bool exists(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return exists(detail::status(p, &ec));
+ return filesystem::exists(detail::status(p, &ec));
+}
+
+inline bool is_regular_file(path const& p)
+{
+ return filesystem::is_regular_file(detail::status(p));
+}
+
+inline bool is_regular_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return filesystem::is_regular_file(detail::status(p, &ec));
}
inline bool is_directory(path const& p)
{
- return is_directory(detail::status(p));
+ return filesystem::is_directory(detail::status(p));
}
-inline bool is_directory(path const& p, system::error_code& ec)
+inline bool is_directory(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return is_directory(detail::status(p, &ec));
+ return filesystem::is_directory(detail::status(p, &ec));
}
-inline bool is_regular_file(path const& p)
+inline bool is_symlink(path const& p)
{
- return is_regular_file(detail::status(p));
+ return filesystem::is_symlink(detail::symlink_status(p));
}
-inline bool is_regular_file(path const& p, system::error_code& ec)
+inline bool is_symlink(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return is_regular_file(detail::status(p, &ec));
+ return filesystem::is_symlink(detail::symlink_status(p, &ec));
}
-inline bool is_other(path const& p)
+inline bool is_block_file(path const& p)
{
- return is_other(detail::status(p));
+ return filesystem::is_block_file(detail::status(p));
}
-inline bool is_other(path const& p, system::error_code& ec)
+inline bool is_block_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return is_other(detail::status(p, &ec));
+ return filesystem::is_block_file(detail::status(p, &ec));
}
-inline bool is_symlink(path const& p)
+inline bool is_character_file(path const& p)
+{
+ return filesystem::is_character_file(detail::status(p));
+}
+
+inline bool is_character_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return filesystem::is_character_file(detail::status(p, &ec));
+}
+
+inline bool is_fifo(path const& p)
+{
+ return filesystem::is_fifo(detail::status(p));
+}
+
+inline bool is_fifo(path const& p, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return filesystem::is_fifo(detail::status(p, &ec));
+}
+
+inline bool is_socket(path const& p)
+{
+ return filesystem::is_socket(detail::status(p));
+}
+
+inline bool is_socket(path const& p, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return filesystem::is_socket(detail::status(p, &ec));
+}
+
+inline bool is_reparse_file(path const& p)
+{
+ return filesystem::is_reparse_file(detail::symlink_status(p));
+}
+
+inline bool is_reparse_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT
+{
+ return filesystem::is_reparse_file(detail::symlink_status(p, &ec));
+}
+
+inline bool is_other(path const& p)
{
- return is_symlink(detail::symlink_status(p));
+ return filesystem::is_other(detail::status(p));
}
-inline bool is_symlink(path const& p, system::error_code& ec)
+inline bool is_other(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return is_symlink(detail::symlink_status(p, &ec));
+ return filesystem::is_other(detail::status(p, &ec));
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead")
inline bool is_regular(path const& p)
{
- return is_regular(detail::status(p));
+ return filesystem::is_regular_file(p);
}
-inline bool is_regular(path const& p, system::error_code& ec)
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead")
+inline bool is_regular(path const& p, system::error_code& ec) BOOST_NOEXCEPT
{
- return is_regular(detail::status(p, &ec));
+ return filesystem::is_regular_file(p, ec);
}
#endif
@@ -347,11 +399,13 @@ inline path canonical(path const& p, path const& base, system::error_code& ec)
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use absolute() instead")
inline path complete(path const& p)
{
return absolute(p, initial_path());
}
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use absolute() instead")
inline path complete(path const& p, path const& base)
{
return absolute(p, base);
@@ -379,11 +433,13 @@ inline void copy(path const& from, path const& to, BOOST_SCOPED_ENUM_NATIVE(copy
}
#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use create_directory() instead")
inline void copy_directory(path const& from, path const& to)
{
detail::copy_directory(from, to);
}
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use create_directory() instead")
inline void copy_directory(path const& from, path const& to, system::error_code& ec) BOOST_NOEXCEPT
{
detail::copy_directory(from, to, &ec);
@@ -413,12 +469,14 @@ inline bool copy_file(path const& from, path const& to, // See ticket #2925
}
#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use copy_options instead of copy_option")
inline bool copy_file(path const& from, path const& to, // See ticket #2925
BOOST_SCOPED_ENUM_NATIVE(copy_option) options)
{
return detail::copy_file(from, to, static_cast< unsigned int >(options));
}
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use copy_options instead of copy_option")
inline bool copy_file(path const& from, path const& to, // See ticket #2925
BOOST_SCOPED_ENUM_NATIVE(copy_option) options, system::error_code& ec) BOOST_NOEXCEPT
{
@@ -646,6 +704,7 @@ inline space_info space(path const& p, system::error_code& ec) BOOST_NOEXCEPT
}
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_symlink(symlink_status(path)) instead")
inline bool symbolic_link_exists(path const& p)
{
return is_symlink(filesystem::symlink_status(p));
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp
index 0554c987a1..729e188125 100644
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp
+++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp
@@ -2,7 +2,7 @@
// Copyright Vladimir Prus 2002
// Copyright Beman Dawes 2002-2005, 2009
-// Copyright Andrey Semashev 2021
+// Copyright Andrey Semashev 2021-2023
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -18,25 +18,25 @@
#include <boost/assert.hpp>
#include <boost/filesystem/config.hpp>
-#include <boost/filesystem/path_traits.hpp> // includes <cwchar>
+#include <boost/filesystem/detail/path_traits.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/io/quoted.hpp>
#include <boost/functional/hash_fwd.hpp>
-#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/negation.hpp>
+#include <boost/type_traits/conjunction.hpp>
+#include <boost/type_traits/disjunction.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
-#include <boost/type_traits/decay.hpp>
#include <cstddef>
-#include <cwchar> // for mbstate_t
-#include <string>
#include <iosfwd>
-#include <iterator>
#include <locale>
-#include <utility>
+#include <string>
+#include <iterator>
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+#include <string_view>
+#endif
#include <boost/filesystem/detail/header.hpp> // must be the last #include
@@ -69,59 +69,82 @@ BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSepa
path_constants< Char, Separator, PreferredSeparator, Dot >::dot;
#endif
-// A struct that denotes a contiguous range of characters in a string. A lightweight alternative to string_view.
-struct substring
+class path_iterator;
+class path_reverse_iterator;
+
+} // namespace path_detail
+
+namespace detail {
+
+struct path_algorithms
{
- std::size_t pos;
- std::size_t size;
-};
+ // A struct that denotes a contiguous range of characters in a string. A lightweight alternative to string_view.
+ struct substring
+ {
+ std::size_t pos;
+ std::size_t size;
+ };
-template< typename T >
-struct is_native_char_ptr_impl : public boost::false_type {};
+ typedef path_traits::path_native_char_type value_type;
+ typedef std::basic_string< value_type > string_type;
-#if defined(BOOST_WINDOWS_API)
-template< >
-struct is_native_char_ptr_impl< wchar_t* > : public boost::true_type {};
-template< >
-struct is_native_char_ptr_impl< const wchar_t* > : public boost::true_type {};
-#else // defined(BOOST_WINDOWS_API)
-template< >
-struct is_native_char_ptr_impl< char* > : public boost::true_type {};
-template< >
-struct is_native_char_ptr_impl< const char* > : public boost::true_type {};
-#endif // defined(BOOST_WINDOWS_API)
+ static bool has_filename_v3(path const& p);
+ static bool has_filename_v4(path const& p);
+ BOOST_FILESYSTEM_DECL static path filename_v3(path const& p);
+ static path filename_v4(path const& p);
-template< typename T >
-struct is_native_char_ptr : public is_native_char_ptr_impl< typename boost::remove_cv< typename boost::remove_reference< T >::type >::type > {};
+ BOOST_FILESYSTEM_DECL static path stem_v3(path const& p);
+ BOOST_FILESYSTEM_DECL static path stem_v4(path const& p);
+ BOOST_FILESYSTEM_DECL static path extension_v3(path const& p);
+ static path extension_v4(path const& p);
-template< typename T >
-struct is_native_pathable_impl : public boost::false_type {};
+ BOOST_FILESYSTEM_DECL static void remove_filename_v3(path& p);
+ BOOST_FILESYSTEM_DECL static void remove_filename_v4(path& p);
-template< typename T >
-struct is_native_pathable_impl< T* > : public is_native_char_ptr_impl< T* > {};
+ BOOST_FILESYSTEM_DECL static void replace_extension_v3(path& p, path const& new_extension);
+ BOOST_FILESYSTEM_DECL static void replace_extension_v4(path& p, path const& new_extension);
-#if defined(BOOST_WINDOWS_API)
-template< >
-struct is_native_pathable_impl< const wchar_t[] > : public boost::true_type {};
-template< std::size_t N >
-struct is_native_pathable_impl< const wchar_t[N] > : public boost::true_type {};
-template< >
-struct is_native_pathable_impl< std::basic_string< wchar_t > > : public boost::true_type {};
-#else // defined(BOOST_WINDOWS_API)
-template< >
-struct is_native_pathable_impl< const char[] > : public boost::true_type {};
-template< std::size_t N >
-struct is_native_pathable_impl< const char[N] > : public boost::true_type {};
-template< >
-struct is_native_pathable_impl< std::basic_string< char > > : public boost::true_type {};
-#endif // defined(BOOST_WINDOWS_API)
-template< >
-struct is_native_pathable_impl< filesystem::path > : public boost::true_type {};
+ BOOST_FILESYSTEM_DECL static path lexically_normal_v3(path const& p);
+ BOOST_FILESYSTEM_DECL static path lexically_normal_v4(path const& p);
-template< typename T >
-struct is_native_pathable : public is_native_pathable_impl< typename boost::remove_cv< typename boost::remove_reference< T >::type >::type > {};
+ 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);
-} // namespace path_detail
+ BOOST_FILESYSTEM_DECL static void append_v3(path& p, const value_type* b, const value_type* e);
+ BOOST_FILESYSTEM_DECL static void append_v4(path& p, const value_type* b, const value_type* e);
+ static void append_v4(path& left, path const& right);
+
+ // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0.
+ // Note: An append is never performed if size()==0, so a returned 0 is unambiguous.
+ BOOST_FILESYSTEM_DECL static string_type::size_type append_separator_if_needed(path& p);
+ BOOST_FILESYSTEM_DECL static void erase_redundant_separator(path& p, string_type::size_type sep_pos);
+
+ BOOST_FILESYSTEM_DECL static string_type::size_type find_root_name_size(path const& p);
+ BOOST_FILESYSTEM_DECL static string_type::size_type find_root_path_size(path const& p);
+ BOOST_FILESYSTEM_DECL static substring find_root_directory(path const& p);
+ BOOST_FILESYSTEM_DECL static substring find_relative_path(path const& p);
+ BOOST_FILESYSTEM_DECL static string_type::size_type find_parent_path_size(path const& p);
+ BOOST_FILESYSTEM_DECL static string_type::size_type find_filename_v4_size(path const& p);
+ BOOST_FILESYSTEM_DECL static string_type::size_type find_extension_v4_size(path const& p);
+
+ BOOST_FILESYSTEM_DECL static int lex_compare_v3
+ (
+ path_detail::path_iterator first1, path_detail::path_iterator const& last1,
+ path_detail::path_iterator first2, path_detail::path_iterator const& last2
+ );
+ BOOST_FILESYSTEM_DECL static int lex_compare_v4
+ (
+ path_detail::path_iterator first1, path_detail::path_iterator const& last1,
+ path_detail::path_iterator first2, path_detail::path_iterator const& last2
+ );
+
+ BOOST_FILESYSTEM_DECL static void increment_v3(path_detail::path_iterator& it);
+ BOOST_FILESYSTEM_DECL static void increment_v4(path_detail::path_iterator& it);
+ BOOST_FILESYSTEM_DECL static void decrement_v3(path_detail::path_iterator& it);
+ BOOST_FILESYSTEM_DECL static void decrement_v4(path_detail::path_iterator& it);
+};
+
+} // namespace detail
//------------------------------------------------------------------------------------//
// //
@@ -132,19 +155,23 @@ struct is_native_pathable : public is_native_pathable_impl< typename boost::remo
class path :
public filesystem::path_detail::path_constants<
#ifdef BOOST_WINDOWS_API
- wchar_t, L'/', L'\\', L'.'
+ detail::path_traits::path_native_char_type, L'/', L'\\', L'.'
#else
- char, '/', '/', '.'
+ detail::path_traits::path_native_char_type, '/', '/', '.'
#endif
>
{
+ friend class path_detail::path_iterator;
+ friend class path_detail::path_reverse_iterator;
+ friend struct detail::path_algorithms;
+
public:
// value_type is the character type used by the operating system API to
// represent paths.
- typedef path_constants_base::value_type value_type;
- typedef std::basic_string< value_type > string_type;
- typedef std::codecvt< wchar_t, char, std::mbstate_t > codecvt_type;
+ typedef detail::path_algorithms::value_type value_type;
+ typedef detail::path_algorithms::string_type string_type;
+ typedef detail::path_traits::codecvt_type codecvt_type;
// ----- character encoding conversions -----
@@ -201,131 +228,302 @@ public:
// that actually depend on locale(""). It further ensures that exceptions thrown
// as a result of such failues occur after main() has started, so can be caught.
+private:
+ //! Assignment operation
+ class assign_op
+ {
+ private:
+ path& m_self;
+
+ public:
+ typedef void result_type;
+
+ explicit assign_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
+
+ result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
+ {
+ m_self.m_pathname.assign(source, source_end);
+ }
+
+ template< typename OtherChar >
+ result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
+ {
+ m_self.m_pathname.clear();
+ detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt);
+ }
+ };
+
+ //! Concatenation operation
+ class concat_op
+ {
+ private:
+ path& m_self;
+
+ public:
+ typedef void result_type;
+
+ explicit concat_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
+
+ result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
+ {
+ m_self.m_pathname.append(source, source_end);
+ }
+
+ template< typename OtherChar >
+ result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
+ {
+ detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt);
+ }
+ };
+
+ //! Path appending operation
+ class append_op
+ {
+ private:
+ path& m_self;
+
+ public:
+ typedef void result_type;
+
+ explicit append_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
+
+ BOOST_FORCEINLINE result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
+ {
+ m_self.append(source, source_end);
+ }
+
+ template< typename OtherChar >
+ BOOST_FORCEINLINE result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
+ {
+ string_type src;
+ detail::path_traits::convert(source, source_end, src, cvt);
+ m_self.append(src.data(), src.data() + src.size());
+ }
+ };
+
+ //! Path comparison operation
+ class compare_op
+ {
+ private:
+ path const& m_self;
+
+ public:
+ typedef int result_type;
+
+ explicit compare_op(path const& self) BOOST_NOEXCEPT : m_self(self) {}
+
+ result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const;
+
+ template< typename OtherChar >
+ result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const;
+ };
+
+public:
+ typedef path_detail::path_iterator iterator;
+ typedef iterator const_iterator;
+ typedef path_detail::path_reverse_iterator reverse_iterator;
+ typedef reverse_iterator const_reverse_iterator;
+
+public:
// ----- constructors -----
path() BOOST_NOEXCEPT {}
path(path const& p) : m_pathname(p.m_pathname) {}
+ path(path const& p, codecvt_type const&) : m_pathname(p.m_pathname) {}
- template< class Source >
+ path(const value_type* s) : m_pathname(s) {}
+ path(const value_type* s, codecvt_type const&) : m_pathname(s) {}
+ path(string_type const& s) : m_pathname(s) {}
+ path(string_type const& s, codecvt_type const&) : m_pathname(s) {}
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ path(std::basic_string_view< value_type > const& s) : m_pathname(s) {}
+ path(std::basic_string_view< value_type > const& s, codecvt_type const&) : m_pathname(s) {}
+#endif
+
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<
+ typename Source,
+ typename = typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
+ >::value
+ >::type
+ >
+ path(Source const& source)
+#else
+ template< typename Source >
path(Source const& source, typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value
+ boost::conjunction<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
+ >::value
>::type* = NULL)
+#endif
{
- path_traits::dispatch(source, m_pathname);
+ assign(source);
}
- path(const value_type* s) : m_pathname(s) {}
- path(string_type const& s) : m_pathname(s) {}
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<
+ typename Source,
+ typename = typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
+ >::value
+ >::type
+ >
+ explicit path(Source const& source, codecvt_type const& cvt)
+#else
+ template< typename Source >
+ explicit path(Source const& source, codecvt_type const& cvt, typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
+ >::value
+ >::type* = NULL)
+#endif
+ {
+ assign(source, cvt);
+ }
// As of October 2015 the interaction between noexcept and =default is so troublesome
// for VC++, GCC, and probably other compilers, that =default is not used with noexcept
// functions. GCC is not even consistent for the same release on different platforms.
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- path(path&& p) BOOST_NOEXCEPT : m_pathname(std::move(p.m_pathname))
+ path(path&& p) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname))
{
}
- path(path&& p, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(std::move(p.m_pathname))
+ path(path&& p, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname))
{
}
path& operator=(path&& p) BOOST_NOEXCEPT
{
- m_pathname = std::move(p.m_pathname);
+ m_pathname = static_cast< string_type&& >(p.m_pathname);
return *this;
}
path& assign(path&& p) BOOST_NOEXCEPT
{
- m_pathname = std::move(p.m_pathname);
+ m_pathname = static_cast< string_type&& >(p.m_pathname);
return *this;
}
path& assign(path&& p, codecvt_type const&) BOOST_NOEXCEPT
{
- m_pathname = std::move(p.m_pathname);
+ m_pathname = static_cast< string_type&& >(p.m_pathname);
return *this;
}
- path(string_type&& s) BOOST_NOEXCEPT : m_pathname(std::move(s))
+ path(string_type&& s) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s))
{
}
- path(string_type&& s, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(std::move(s))
+ path(string_type&& s, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s))
{
}
path& operator=(string_type&& p) BOOST_NOEXCEPT
{
- m_pathname = std::move(p);
+ m_pathname = static_cast< string_type&& >(p);
return *this;
}
path& assign(string_type&& p) BOOST_NOEXCEPT
{
- m_pathname = std::move(p);
+ m_pathname = static_cast< string_type&& >(p);
return *this;
}
path& assign(string_type&& p, codecvt_type const&) BOOST_NOEXCEPT
{
- m_pathname = std::move(p);
+ m_pathname = static_cast< string_type&& >(p);
return *this;
}
#endif
- path(path const& p, codecvt_type const&) : m_pathname(p.m_pathname) {}
- path(const value_type* s, codecvt_type const&) : m_pathname(s) {}
- path(string_type const& s, codecvt_type const&) : m_pathname(s) {}
-
- template< class Source >
- path(Source const& source, codecvt_type const& cvt, typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value
- >::type* = NULL)
- {
- path_traits::dispatch(source, m_pathname, cvt);
- }
-
path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {}
+ path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {}
- template< class InputIterator >
- path(InputIterator begin, InputIterator end, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = NULL)
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<
+ typename InputIterator,
+ typename = typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value
+ >::type
+ >
+ path(InputIterator begin, InputIterator end)
+#else
+ template< typename InputIterator >
+ path(InputIterator begin, InputIterator end, typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value
+ >::type* = NULL)
+#endif
{
if (begin != end)
{
- // convert requires contiguous string, so copy
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname);
+ typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
+ source_t source(begin, end);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ assign(static_cast< source_t&& >(source));
+#else
+ assign(source);
+#endif
}
}
- path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {}
-
- template< class InputIterator >
- path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = NULL)
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<
+ typename InputIterator,
+ typename = typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value
+ >::type
+ >
+ path(InputIterator begin, InputIterator end, codecvt_type const& cvt)
+#else
+ template< typename InputIterator >
+ path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value
+ >::type* = NULL)
+#endif
{
if (begin != end)
{
- // convert requires contiguous string, so copy
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname, cvt);
+ typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
+ source_t source(begin, end);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ assign(static_cast< source_t&& >(source), cvt);
+#else
+ assign(source, cvt);
+#endif
}
}
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_DELETED_FUNCTION(path(std::nullptr_t))
+ BOOST_DELETED_FUNCTION(path& operator= (std::nullptr_t))
+#endif
+
+public:
// ----- assignments -----
// We need to explicitly define copy assignment as otherwise it will be implicitly defined as deleted because there is move assignment
- path& operator=(path const& p)
- {
- return assign(p);
- }
-
- path& operator=(string_type const& s)
- {
- return assign(s);
- }
-
- path& operator=(const value_type* ptr)
- {
- return assign(ptr);
- }
+ path& operator=(path const& p);
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ boost::disjunction<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
path&
>::type operator=(Source const& source)
{
@@ -338,26 +536,26 @@ public:
return *this;
}
- path& assign(string_type const& s)
- {
- m_pathname = s;
- return *this;
- }
-
- path& assign(const value_type* ptr)
+ template< typename Source >
+ typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type assign(Source const& source)
{
- m_pathname = ptr;
+ detail::path_traits::dispatch(source, assign_op(*this));
return *this;
}
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type assign(Source const& source)
{
- m_pathname.clear();
- path_traits::dispatch(source, m_pathname);
+ detail::path_traits::dispatch_convertible(source, assign_op(*this));
return *this;
}
@@ -367,26 +565,26 @@ public:
return *this;
}
- path& assign(string_type const& s, codecvt_type const&)
- {
- m_pathname = s;
- return *this;
- }
-
- path& assign(const value_type* ptr, codecvt_type const&)
+ template< typename Source >
+ typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type assign(Source const& source, codecvt_type const& cvt)
{
- m_pathname = ptr;
+ detail::path_traits::dispatch(source, assign_op(*this), &cvt);
return *this;
}
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type assign(Source const& source, codecvt_type const& cvt)
{
- m_pathname.clear();
- path_traits::dispatch(source, m_pathname, cvt);
+ detail::path_traits::dispatch_convertible(source, assign_op(*this), &cvt);
return *this;
}
@@ -396,15 +594,25 @@ public:
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- assign(InputIterator begin, InputIterator end)
+ template< typename InputIterator >
+ typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type assign(InputIterator begin, InputIterator end)
{
m_pathname.clear();
if (begin != end)
{
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname);
+ typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
+ source_t source(begin, end);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ assign(static_cast< source_t&& >(source));
+#else
+ assign(source);
+#endif
}
return *this;
}
@@ -415,39 +623,36 @@ public:
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- assign(InputIterator begin, InputIterator end, codecvt_type const& cvt)
+ template< typename InputIterator >
+ typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type assign(InputIterator begin, InputIterator end, codecvt_type const& cvt)
{
m_pathname.clear();
if (begin != end)
{
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname, cvt);
+ typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
+ source_t source(begin, end);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ assign(static_cast< source_t&& >(source), cvt);
+#else
+ assign(source, cvt);
+#endif
}
return *this;
}
// ----- concatenation -----
- path& operator+=(path const& p)
- {
- return concat(p);
- }
-
- path& operator+=(const value_type* ptr)
- {
- return concat(ptr);
- }
+ path& operator+=(path const& p);
- path& operator+=(string_type const& s)
- {
- return concat(s);
- }
-
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
path&
>::type operator+=(Source const& source)
{
@@ -460,69 +665,74 @@ public:
return *this;
}
- template< class CharT >
- typename boost::enable_if< boost::is_integral< CharT >, path& >::type
- operator+=(CharT c)
+ template< typename CharT >
+ typename boost::enable_if_c<
+ detail::path_traits::is_path_char_type< CharT >::value,
+ path&
+ >::type operator+=(CharT c)
{
CharT tmp[2];
tmp[0] = c;
tmp[1] = static_cast< CharT >(0);
- return concat(tmp);
- }
-
- path& concat(path const& p)
- {
- m_pathname += p.m_pathname;
+ concat_op(*this)(tmp, tmp + 1);
return *this;
}
- path& concat(const value_type* ptr)
+ path& concat(path const& p)
{
- m_pathname += ptr;
+ m_pathname.append(p.m_pathname);
return *this;
}
- path& concat(string_type const& s)
+ template< typename Source >
+ typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type concat(Source const& source)
{
- m_pathname += s;
+ detail::path_traits::dispatch(source, concat_op(*this));
return *this;
}
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type concat(Source const& source)
{
- path_traits::dispatch(source, m_pathname);
+ detail::path_traits::dispatch_convertible(source, concat_op(*this));
return *this;
}
path& concat(path const& p, codecvt_type const&)
{
- m_pathname += p.m_pathname;
+ m_pathname.append(p.m_pathname);
return *this;
}
- path& concat(const value_type* ptr, codecvt_type const&)
- {
- m_pathname += ptr;
- return *this;
- }
-
- path& concat(string_type const& s, codecvt_type const&)
+ template< typename Source >
+ typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type concat(Source const& source, codecvt_type const& cvt)
{
- m_pathname += s;
+ detail::path_traits::dispatch(source, concat_op(*this), &cvt);
return *this;
}
- template< class Source >
+ template< typename Source >
typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type concat(Source const& source, codecvt_type const& cvt)
{
- path_traits::dispatch(source, m_pathname, cvt);
+ detail::path_traits::dispatch_convertible(source, concat_op(*this), &cvt);
return *this;
}
@@ -532,14 +742,19 @@ public:
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- concat(InputIterator begin, InputIterator end)
+ template< typename InputIterator >
+ typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type concat(InputIterator begin, InputIterator end)
{
if (begin != end)
{
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname);
+ std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
+ detail::path_traits::dispatch(source, concat_op(*this));
}
return *this;
}
@@ -550,14 +765,19 @@ public:
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- concat(InputIterator begin, InputIterator end, codecvt_type const& cvt)
+ template< typename InputIterator >
+ typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type concat(InputIterator begin, InputIterator end, codecvt_type const& cvt)
{
if (begin != end)
{
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), m_pathname, cvt);
+ std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
+ detail::path_traits::dispatch(source, concat_op(*this), &cvt);
}
return *this;
}
@@ -567,124 +787,97 @@ public:
// if a separator is added, it is the preferred separator for the platform;
// slash for POSIX, backslash for Windows
- path& operator/=(path const& p)
- {
- return append(p);
- }
+ path& operator/=(path const& p);
- path& operator/=(const value_type* ptr)
- {
- return append(ptr);
- }
-
- path& operator/=(string_type const& s)
- {
- return append(s);
- }
-
- template< class Source >
+ template< typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
path&
>::type operator/=(Source const& source)
{
return append(source);
}
- BOOST_FORCEINLINE path& append(path const& p)
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(p);
- return *this;
- }
-
- BOOST_FORCEINLINE path& append(string_type const& p)
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(p.c_str(), p.c_str() + p.size());
- return *this;
- }
+ path& append(path const& p);
- BOOST_FORCEINLINE path& append(const value_type* ptr)
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type append(Source const& source)
{
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(ptr, ptr + string_type::traits_type::length(ptr));
+ detail::path_traits::dispatch(source, append_op(*this));
return *this;
}
- template< class Source >
- typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type append(Source const& source)
{
- path p;
- path_traits::dispatch(source, p.m_pathname);
- return append(p);
- }
-
- BOOST_FORCEINLINE path& append(path const& p, codecvt_type const&)
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(p);
+ detail::path_traits::dispatch_convertible(source, append_op(*this));
return *this;
}
- BOOST_FORCEINLINE path& append(string_type const& p, codecvt_type const&)
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(p.c_str(), p.c_str() + p.size());
- return *this;
- }
+ path& append(path const& p, codecvt_type const&);
- BOOST_FORCEINLINE path& append(const value_type* ptr, codecvt_type const&)
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ path&
+ >::type append(Source const& source, codecvt_type const& cvt)
{
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(ptr, ptr + string_type::traits_type::length(ptr));
+ detail::path_traits::dispatch(source, append_op(*this), &cvt);
return *this;
}
- template< class Source >
- typename boost::enable_if_c<
- path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value,
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
path&
>::type append(Source const& source, codecvt_type const& cvt)
{
- path p;
- path_traits::dispatch(source, p.m_pathname, cvt);
- return append(p);
- }
-
- BOOST_FORCEINLINE path& append(const value_type* begin, const value_type* end)
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(begin, end);
+ detail::path_traits::dispatch_convertible(source, append_op(*this), &cvt);
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- append(InputIterator begin, InputIterator end)
- {
- path p;
- if (begin != end)
- {
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), p.m_pathname);
- }
- return append(p);
- }
+ path& append(const value_type* begin, const value_type* end);
- BOOST_FORCEINLINE path& append(const value_type* begin, const value_type* end, codecvt_type const&)
+ template< typename InputIterator >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type append(InputIterator begin, InputIterator end)
{
- BOOST_FILESYSTEM_VERSIONED_SYM(append)(begin, end);
+ std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
+ detail::path_traits::dispatch(source, append_op(*this));
return *this;
}
- template< class InputIterator >
- typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator >, path& >::type
- append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
+ path& append(const value_type* begin, const value_type* end, codecvt_type const&);
+
+ template< typename InputIterator >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_path_source_iterator< InputIterator >,
+ boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
+ >::value,
+ path&
+ >::type append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
{
- path p;
- if (begin != end)
- {
- std::basic_string< typename std::iterator_traits< InputIterator >::value_type > seq(begin, end);
- path_traits::convert(seq.c_str(), seq.c_str() + seq.size(), p.m_pathname, cvt);
- }
- return append(p);
+ std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
+ detail::path_traits::dispatch(source, append_op(*this), &cvt);
+ return *this;
}
// ----- modifiers -----
@@ -699,13 +892,12 @@ public:
#else // BOOST_WINDOWS_API
BOOST_FILESYSTEM_DECL path& make_preferred(); // change slashes to backslashes
#endif
- BOOST_FILESYSTEM_DECL path& remove_filename();
+ path& remove_filename();
+ BOOST_FILESYSTEM_DECL path& remove_filename_and_trailing_separators();
BOOST_FILESYSTEM_DECL path& remove_trailing_separator();
- BOOST_FORCEINLINE path& replace_extension(path const& new_extension = path())
- {
- BOOST_FILESYSTEM_VERSIONED_SYM(replace_extension)(new_extension);
- return *this;
- }
+ BOOST_FILESYSTEM_DECL path& replace_filename(path const& replacement);
+ path& replace_extension(path const& new_extension = path());
+
void swap(path& rhs) BOOST_NOEXCEPT { m_pathname.swap(rhs.m_pathname); }
// ----- observers -----
@@ -733,10 +925,10 @@ public:
const value_type* c_str() const BOOST_NOEXCEPT { return m_pathname.c_str(); }
string_type::size_type size() const BOOST_NOEXCEPT { return m_pathname.size(); }
- template< class String >
+ template< typename String >
String string() const;
- template< class String >
+ template< typename String >
String string(codecvt_type const& cvt) const;
#ifdef BOOST_WINDOWS_API
@@ -744,14 +936,14 @@ public:
{
std::string tmp;
if (!m_pathname.empty())
- path_traits::convert(m_pathname.c_str(), m_pathname.c_str() + m_pathname.size(), tmp);
+ detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp);
return tmp;
}
std::string string(codecvt_type const& cvt) const
{
std::string tmp;
if (!m_pathname.empty())
- path_traits::convert(m_pathname.c_str(), m_pathname.c_str() + m_pathname.size(), tmp, cvt);
+ detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt);
return tmp;
}
@@ -767,14 +959,14 @@ public:
{
std::wstring tmp;
if (!m_pathname.empty())
- path_traits::convert(m_pathname.c_str(), m_pathname.c_str() + m_pathname.size(), tmp);
+ detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp);
return tmp;
}
std::wstring wstring(codecvt_type const& cvt) const
{
std::wstring tmp;
if (!m_pathname.empty())
- path_traits::convert(m_pathname.c_str(), m_pathname.c_str() + m_pathname.size(), tmp, cvt);
+ detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt);
return tmp;
}
#endif
@@ -787,13 +979,13 @@ public:
#ifdef BOOST_WINDOWS_API
BOOST_FILESYSTEM_DECL path generic_path() const;
#else
- path generic_path() const { return path(*this); }
+ path generic_path() const;
#endif
- template< class String >
+ template< typename String >
String generic_string() const;
- template< class String >
+ template< typename String >
String generic_string(codecvt_type const& cvt) const;
#ifdef BOOST_WINDOWS_API
@@ -811,51 +1003,88 @@ public:
// ----- compare -----
- BOOST_FORCEINLINE int compare(path const& p) const BOOST_NOEXCEPT // generic, lexicographical
+ int compare(path const& p) const; // generic, lexicographical
+
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ int
+ >::type compare(Source const& source) const
+ {
+ return detail::path_traits::dispatch(source, compare_op(*this));
+ }
+
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
+ int
+ >::type compare(Source const& source) const
{
- return BOOST_FILESYSTEM_VERSIONED_SYM(compare)(p);
+ return detail::path_traits::dispatch_convertible(source, compare_op(*this));
+ }
+
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
+ int
+ >::type compare(Source const& source, codecvt_type const& cvt) const
+ {
+ return detail::path_traits::dispatch(source, compare_op(*this), &cvt);
+ }
+
+ template< typename Source >
+ BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
+ boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
+ >::value,
+ int
+ >::type compare(Source const& source, codecvt_type const& cvt) const
+ {
+ return detail::path_traits::dispatch_convertible(source, compare_op(*this), &cvt);
}
- int compare(std::string const& s) const { return compare(path(s)); }
- int compare(const value_type* s) const { return compare(path(s)); }
// ----- decomposition -----
- path root_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + find_root_path_size()); }
+ path root_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_path_size(*this)); }
// returns 0 or 1 element path even on POSIX, root_name() is non-empty() for network paths
- path root_name() const { return path(m_pathname.c_str(), m_pathname.c_str() + find_root_name_size()); }
+ path root_name() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_name_size(*this)); }
// returns 0 or 1 element path
path root_directory() const
{
- path_detail::substring root_dir = find_root_directory();
+ detail::path_algorithms::substring root_dir = detail::path_algorithms::find_root_directory(*this);
const value_type* p = m_pathname.c_str() + root_dir.pos;
return path(p, p + root_dir.size);
}
path relative_path() const
{
- path_detail::substring root_dir = find_relative_path();
- const value_type* p = m_pathname.c_str() + root_dir.pos;
- return path(p, p + root_dir.size);
+ detail::path_algorithms::substring rel_path = detail::path_algorithms::find_relative_path(*this);
+ const value_type* p = m_pathname.c_str() + rel_path.pos;
+ return path(p, p + rel_path.size);
}
- path parent_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + find_parent_path_size()); }
+ path parent_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_parent_path_size(*this)); }
- BOOST_FORCEINLINE path filename() const { return BOOST_FILESYSTEM_VERSIONED_SYM(filename)(); } // returns 0 or 1 element path
- BOOST_FORCEINLINE path stem() const { return BOOST_FILESYSTEM_VERSIONED_SYM(stem)(); } // returns 0 or 1 element path
- BOOST_FORCEINLINE path extension() const { return BOOST_FILESYSTEM_VERSIONED_SYM(extension)(); } // returns 0 or 1 element path
+ path filename() const; // returns 0 or 1 element path
+ path stem() const; // returns 0 or 1 element path
+ path extension() const; // returns 0 or 1 element path
// ----- query -----
bool empty() const BOOST_NOEXCEPT { return m_pathname.empty(); }
bool filename_is_dot() const;
bool filename_is_dot_dot() const;
- bool has_root_path() const { return find_root_path_size() > 0; }
- bool has_root_name() const { return find_root_name_size() > 0; }
- bool has_root_directory() const { return find_root_directory().size > 0; }
- bool has_relative_path() const { return find_relative_path().size > 0; }
- bool has_parent_path() const { return find_parent_path_size() > 0; }
- BOOST_FORCEINLINE bool has_filename() const { return BOOST_FILESYSTEM_VERSIONED_SYM(has_filename)(); }
+ bool has_root_path() const { return detail::path_algorithms::find_root_path_size(*this) > 0; }
+ bool has_root_name() const { return detail::path_algorithms::find_root_name_size(*this) > 0; }
+ bool has_root_directory() const { return detail::path_algorithms::find_root_directory(*this).size > 0; }
+ bool has_relative_path() const { return detail::path_algorithms::find_relative_path(*this).size > 0; }
+ bool has_parent_path() const { return detail::path_algorithms::find_parent_path_size(*this) > 0; }
+ bool has_filename() const;
bool has_stem() const { return !stem().empty(); }
bool has_extension() const { return !extension().empty(); }
bool is_relative() const { return !is_absolute(); }
@@ -871,22 +1100,12 @@ public:
// ----- lexical operations -----
- BOOST_FORCEINLINE path lexically_normal() const { return BOOST_FILESYSTEM_VERSIONED_SYM(lexically_normal)(); }
+ path lexically_normal() const;
BOOST_FILESYSTEM_DECL path lexically_relative(path const& base) const;
- path lexically_proximate(path const& base) const
- {
- path tmp(lexically_relative(base));
- return tmp.empty() ? *this : tmp;
- }
+ path lexically_proximate(path const& base) const;
// ----- iterators -----
- class iterator;
- friend class iterator;
- typedef iterator const_iterator;
- class reverse_iterator;
- typedef reverse_iterator const_reverse_iterator;
-
BOOST_FILESYSTEM_DECL iterator begin() const;
BOOST_FILESYSTEM_DECL iterator end() const;
reverse_iterator rbegin() const;
@@ -901,29 +1120,37 @@ public:
#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
// recently deprecated functions supplied by default
- path& normalize()
- {
- path tmp(lexically_normal());
- m_pathname.swap(tmp.m_pathname);
- return *this;
- }
+ path& normalize();
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::remove_filename() instead")
path& remove_leaf() { return remove_filename(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::filename() instead")
path leaf() const { return filename(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::parent_path() instead")
path branch_path() const { return parent_path(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::generic_path() instead")
path generic() const { return generic_path(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use !path::empty() instead")
bool has_leaf() const { return !m_pathname.empty(); }
- bool has_branch_path() const { return !parent_path().empty(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::has_parent_path() instead")
+ bool has_branch_path() const { return has_parent_path(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::is_absolute() instead")
bool is_complete() const { return is_absolute(); }
#endif
#if defined(BOOST_FILESYSTEM_DEPRECATED)
// deprecated functions with enough signature or semantic changes that they are
// not supplied by default
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
std::string file_string() const { return string(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
std::string directory_string() const { return string(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
std::string native_file_string() const { return string(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
std::string native_directory_string() const { return string(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead")
string_type external_file_string() const { return native(); }
+ BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead")
string_type external_directory_string() const { return native(); }
#endif
@@ -931,55 +1158,6 @@ public:
// class path private members //
//--------------------------------------------------------------------------------------//
private:
- bool has_filename_v3() const { return !m_pathname.empty(); }
- bool has_filename_v4() const { return find_filename_v4_size() > 0; }
- BOOST_FILESYSTEM_DECL path filename_v3() const;
- path filename_v4() const
- {
- string_type::size_type filename_size = find_filename_v4_size();
- string_type::size_type pos = m_pathname.size() - filename_size;
- const value_type* p = m_pathname.c_str() + pos;
- return path(p, p + filename_size);
- }
- BOOST_FILESYSTEM_DECL path stem_v3() const;
- BOOST_FILESYSTEM_DECL path stem_v4() const;
- BOOST_FILESYSTEM_DECL path extension_v3() const;
- path extension_v4() const
- {
- string_type::size_type extension_size = find_extension_v4_size();
- string_type::size_type pos = m_pathname.size() - extension_size;
- const value_type* p = m_pathname.c_str() + pos;
- return path(p, p + extension_size);
- }
-
- BOOST_FILESYSTEM_DECL void replace_extension_v3(path const& new_extension);
- BOOST_FILESYSTEM_DECL void replace_extension_v4(path const& new_extension);
-
- BOOST_FILESYSTEM_DECL path lexically_normal_v3() const;
- BOOST_FILESYSTEM_DECL path lexically_normal_v4() const;
-
- BOOST_FILESYSTEM_DECL int compare_v3(path const& p) const BOOST_NOEXCEPT;
- BOOST_FILESYSTEM_DECL int compare_v4(path const& p) const BOOST_NOEXCEPT;
-
- BOOST_FILESYSTEM_DECL void append_v3(const value_type* b, const value_type* e);
- BOOST_FILESYSTEM_DECL void append_v4(const value_type* b, const value_type* e);
- BOOST_FILESYSTEM_DECL void append_v3(path const& p);
- BOOST_FILESYSTEM_DECL void append_v4(path const& p);
-
- // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0.
- // Note: An append is never performed if size()==0, so a returned 0 is unambiguous.
- BOOST_FILESYSTEM_DECL string_type::size_type append_separator_if_needed();
- BOOST_FILESYSTEM_DECL void erase_redundant_separator(string_type::size_type sep_pos);
-
- BOOST_FILESYSTEM_DECL string_type::size_type find_root_name_size() const;
- BOOST_FILESYSTEM_DECL string_type::size_type find_root_path_size() const;
- BOOST_FILESYSTEM_DECL path_detail::substring find_root_directory() const;
- BOOST_FILESYSTEM_DECL path_detail::substring find_relative_path() const;
- BOOST_FILESYSTEM_DECL string_type::size_type find_parent_path_size() const;
- BOOST_FILESYSTEM_DECL string_type::size_type find_filename_v4_size() const;
- BOOST_FILESYSTEM_DECL string_type::size_type find_extension_v4_size() const;
-
-private:
/*
* m_pathname has the type, encoding, and format required by the native
* operating system. Thus for POSIX and Windows there is no conversion for
@@ -993,8 +1171,6 @@ private:
};
namespace detail {
-BOOST_FILESYSTEM_DECL int lex_compare_v3(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2);
-BOOST_FILESYSTEM_DECL int lex_compare_v4(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2);
BOOST_FILESYSTEM_DECL path const& dot_path();
BOOST_FILESYSTEM_DECL path const& dot_dot_path();
} // namespace detail
@@ -1003,13 +1179,15 @@ BOOST_FILESYSTEM_DECL path const& dot_dot_path();
typedef path wpath;
#endif
+namespace path_detail {
+
//------------------------------------------------------------------------------------//
// class path::iterator //
//------------------------------------------------------------------------------------//
-class path::iterator :
+class path_iterator :
public boost::iterator_facade<
- path::iterator,
+ path_iterator,
const path,
boost::bidirectional_traversal_tag
>
@@ -1017,24 +1195,18 @@ class path::iterator :
private:
friend class boost::iterator_core_access;
friend class boost::filesystem::path;
- friend class boost::filesystem::path::reverse_iterator;
- friend BOOST_FILESYSTEM_DECL int detail::lex_compare_v3(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2);
+ friend class path_reverse_iterator;
+ friend struct boost::filesystem::detail::path_algorithms;
path const& dereference() const { return m_element; }
- bool equal(iterator const& rhs) const
+ bool equal(path_iterator const& rhs) const BOOST_NOEXCEPT
{
return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos;
}
- BOOST_FORCEINLINE void increment() { BOOST_FILESYSTEM_VERSIONED_SYM(increment)(); }
- BOOST_FORCEINLINE void decrement() { BOOST_FILESYSTEM_VERSIONED_SYM(decrement)(); }
-
-private:
- BOOST_FILESYSTEM_DECL void increment_v3();
- BOOST_FILESYSTEM_DECL void increment_v4();
- BOOST_FILESYSTEM_DECL void decrement_v3();
- BOOST_FILESYSTEM_DECL void decrement_v4();
+ void increment();
+ void decrement();
private:
// current element
@@ -1046,22 +1218,22 @@ private:
// position of the last separator in the path.
// end() iterator is indicated by
// m_pos == m_path_ptr->m_pathname.size()
- string_type::size_type m_pos;
+ path::string_type::size_type m_pos;
};
//------------------------------------------------------------------------------------//
// class path::reverse_iterator //
//------------------------------------------------------------------------------------//
-class path::reverse_iterator :
+class path_reverse_iterator :
public boost::iterator_facade<
- path::reverse_iterator,
+ path_reverse_iterator,
const path,
boost::bidirectional_traversal_tag
>
{
public:
- explicit reverse_iterator(iterator itr) :
+ explicit path_reverse_iterator(path_iterator itr) :
m_itr(itr)
{
if (itr != itr.m_path_ptr->begin())
@@ -1073,14 +1245,14 @@ private:
friend class boost::filesystem::path;
path const& dereference() const { return m_element; }
- bool equal(reverse_iterator const& rhs) const { return m_itr == rhs.m_itr; }
+ bool equal(path_reverse_iterator const& rhs) const BOOST_NOEXCEPT { return m_itr == rhs.m_itr; }
void increment()
{
--m_itr;
if (m_itr != m_itr.m_path_ptr->begin())
{
- iterator tmp = m_itr;
+ path_iterator tmp = m_itr;
m_element = *--tmp;
}
}
@@ -1092,99 +1264,209 @@ private:
}
private:
- iterator m_itr;
+ path_iterator m_itr;
path m_element;
};
+// std::lexicographical_compare would infinitely recurse because path iterators
+// yield paths, so provide a path aware version
+bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2);
+
+} // namespace path_detail
+
+using path_detail::lexicographical_compare;
+
//------------------------------------------------------------------------------------//
// //
// non-member functions //
// //
//------------------------------------------------------------------------------------//
-// std::lexicographical_compare would infinitely recurse because path iterators
-// yield paths, so provide a path aware version
-inline bool lexicographical_compare(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2)
+BOOST_FORCEINLINE bool operator==(path const& lhs, path const& rhs)
{
- return BOOST_FILESYSTEM_VERSIONED_SYM(detail::lex_compare)(first1, last1, first2, last2) < 0;
+ return lhs.compare(rhs) == 0;
}
-inline bool operator==(path const& lhs, path const& rhs)
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator==(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) == 0;
}
-inline bool operator==(path const& lhs, path::string_type const& rhs)
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator==(Source const& lhs, Path const& rhs)
{
- return lhs.compare(rhs) == 0;
+ return rhs.compare(lhs) == 0;
}
-inline bool operator==(path::string_type const& lhs, path const& rhs)
+BOOST_FORCEINLINE bool operator!=(path const& lhs, path const& rhs)
{
- return rhs.compare(lhs) == 0;
+ return lhs.compare(rhs) != 0;
}
-inline bool operator==(path const& lhs, const path::value_type* rhs)
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator!=(Path const& lhs, Source const& rhs)
{
- return lhs.compare(rhs) == 0;
+ return lhs.compare(rhs) != 0;
}
-inline bool operator==(const path::value_type* lhs, path const& rhs)
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator!=(Source const& lhs, Path const& rhs)
{
- return rhs.compare(lhs) == 0;
+ return rhs.compare(lhs) != 0;
}
-inline bool operator!=(path const& lhs, path const& rhs)
+BOOST_FORCEINLINE bool operator<(path const& lhs, path const& rhs)
{
- return lhs.compare(rhs) != 0;
+ return lhs.compare(rhs) < 0;
}
-inline bool operator!=(path const& lhs, path::string_type const& rhs)
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator<(Path const& lhs, Source const& rhs)
{
- return lhs.compare(rhs) != 0;
+ return lhs.compare(rhs) < 0;
}
-inline bool operator!=(path::string_type const& lhs, path const& rhs)
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator<(Source const& lhs, Path const& rhs)
{
- return rhs.compare(lhs) != 0;
+ return rhs.compare(lhs) > 0;
}
-inline bool operator!=(path const& lhs, const path::value_type* rhs)
+BOOST_FORCEINLINE bool operator<=(path const& lhs, path const& rhs)
{
- return lhs.compare(rhs) != 0;
+ return lhs.compare(rhs) <= 0;
}
-inline bool operator!=(const path::value_type* lhs, path const& rhs)
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator<=(Path const& lhs, Source const& rhs)
{
- return rhs.compare(lhs) != 0;
+ return lhs.compare(rhs) <= 0;
}
-// TODO: why do == and != have additional overloads, but the others don't?
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator<=(Source const& lhs, Path const& rhs)
+{
+ return rhs.compare(lhs) >= 0;
+}
-inline bool operator<(path const& lhs, path const& rhs)
+BOOST_FORCEINLINE bool operator>(path const& lhs, path const& rhs)
{
- return lhs.compare(rhs) < 0;
+ return lhs.compare(rhs) > 0;
}
-inline bool operator<=(path const& lhs, path const& rhs)
+
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator>(Path const& lhs, Source const& rhs)
+{
+ return lhs.compare(rhs) > 0;
+}
+
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator>(Source const& lhs, Path const& rhs)
+{
+ return rhs.compare(lhs) < 0;
+}
+
+BOOST_FORCEINLINE bool operator>=(path const& lhs, path const& rhs)
{
- return !(rhs < lhs);
+ return lhs.compare(rhs) >= 0;
}
-inline bool operator>(path const& lhs, path const& rhs)
+
+template< typename Path, typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator>=(Path const& lhs, Source const& rhs)
{
- return rhs < lhs;
+ return lhs.compare(rhs) >= 0;
}
-inline bool operator>=(path const& lhs, path const& rhs)
+
+template< typename Source, typename Path >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
+ bool
+>::type operator>=(Source const& lhs, Path const& rhs)
{
- return !(lhs < rhs);
+ return rhs.compare(lhs) <= 0;
}
+
// Note: Declared as a template to delay binding to Boost.ContainerHash functions and make the dependency optional
-template< typename T >
-inline typename boost::enable_if< boost::is_same< T, path >, std::size_t >::type hash_value(T const& p) BOOST_NOEXCEPT
+template< typename Path >
+inline typename boost::enable_if_c<
+ boost::is_same< Path, path >::value,
+ std::size_t
+>::type hash_value(Path const& p) BOOST_NOEXCEPT
{
#ifdef BOOST_WINDOWS_API
std::size_t seed = 0u;
- for (typename T::value_type const* it = p.c_str(); *it; ++it)
+ for (typename Path::value_type const* it = p.c_str(); *it; ++it)
hash_combine(seed, *it == L'/' ? L'\\' : *it);
return seed;
#else // BOOST_POSIX_API
@@ -1197,33 +1479,34 @@ inline void swap(path& lhs, path& rhs) BOOST_NOEXCEPT
lhs.swap(rhs);
}
-inline path operator/(path const& lhs, path const& rhs)
+BOOST_FORCEINLINE path operator/(path lhs, path const& rhs)
{
- path p = lhs;
- p /= rhs;
- return p;
+ lhs.append(rhs);
+ return lhs;
}
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-inline path operator/(path&& lhs, path const& rhs)
+template< typename Source >
+BOOST_FORCEINLINE typename boost::enable_if_c<
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ path
+>::type operator/(path lhs, Source const& rhs)
{
- lhs /= rhs;
- return std::move(lhs);
+ lhs.append(rhs);
+ return lhs;
}
-#endif
// inserters and extractors
// use boost::io::quoted() to handle spaces in paths
// use '&' as escape character to ease use for Windows paths
-template< class Char, class Traits >
+template< typename Char, typename Traits >
inline std::basic_ostream< Char, Traits >&
operator<<(std::basic_ostream< Char, Traits >& os, path const& p)
{
return os << boost::io::quoted(p.template string< std::basic_string< Char > >(), static_cast< Char >('&'));
}
-template< class Char, class Traits >
+template< typename Char, typename Traits >
inline std::basic_istream< Char, Traits >&
operator>>(std::basic_istream< Char, Traits >& is, path& p)
{
@@ -1275,10 +1558,96 @@ inline bool is_element_separator(path::value_type c) BOOST_NOEXCEPT
// class path miscellaneous function implementations //
//------------------------------------------------------------------------------------//
+namespace detail {
+
+inline bool path_algorithms::has_filename_v3(path const& p)
+{
+ return !p.m_pathname.empty();
+}
+
+inline bool path_algorithms::has_filename_v4(path const& p)
+{
+ return path_algorithms::find_filename_v4_size(p) > 0;
+}
+
+inline path path_algorithms::filename_v4(path const& p)
+{
+ string_type::size_type filename_size = path_algorithms::find_filename_v4_size(p);
+ string_type::size_type pos = p.m_pathname.size() - filename_size;
+ const value_type* ptr = p.m_pathname.c_str() + pos;
+ return path(ptr, ptr + filename_size);
+}
+
+inline path path_algorithms::extension_v4(path const& p)
+{
+ string_type::size_type extension_size = path_algorithms::find_extension_v4_size(p);
+ string_type::size_type pos = p.m_pathname.size() - extension_size;
+ const value_type* ptr = p.m_pathname.c_str() + pos;
+ return path(ptr, ptr + extension_size);
+}
+
+inline void path_algorithms::append_v4(path& left, path const& right)
+{
+ path_algorithms::append_v4(left, right.m_pathname.c_str(), right.m_pathname.c_str() + right.m_pathname.size());
+}
+
+} // namespace detail
+
+// Note: Because of the range constructor in C++23 std::string_view that involves a check for contiguous_range concept,
+// any non-template function call that requires a check whether the source argument (which may be fs::path)
+// is convertible to std::string_view must be made after fs::path::iterator is defined. This includes overload
+// resolution and SFINAE checks. Otherwise, the concept check result formally changes between fs::path::iterator
+// is not defined and defined, which causes compilation errors with gcc 11 and later.
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106808
+
+BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const value_type* source, const value_type* source_end, const codecvt_type*) const
+{
+ path src;
+ src.m_pathname.assign(source, source_end);
+ return m_self.compare(src);
+}
+
+template< typename OtherChar >
+BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt) const
+{
+ path src;
+ detail::path_traits::convert(source, source_end, src.m_pathname, cvt);
+ return m_self.compare(src);
+}
+
+inline path& path::operator=(path const& p)
+{
+ return assign(p);
+}
+
+inline path& path::operator+=(path const& p)
+{
+ return concat(p);
+}
+
+BOOST_FORCEINLINE path& path::operator/=(path const& p)
+{
+ return append(p);
+}
+
+#if !defined(BOOST_WINDOWS_API)
+inline path path::generic_path() const
+{
+ return path(*this);
+}
+#endif
+
+inline path path::lexically_proximate(path const& base) const
+{
+ path tmp(lexically_relative(base));
+ return tmp.empty() ? *this : tmp;
+}
+
inline path::reverse_iterator path::rbegin() const
{
return reverse_iterator(end());
}
+
inline path::reverse_iterator path::rend() const
{
return reverse_iterator(begin());
@@ -1299,92 +1668,164 @@ inline bool path::filename_is_dot_dot() const
// to deal with "c:.." edge case on Windows when ':' acts as a separator
}
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+
+BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::lexically_normal() instead")
+BOOST_FORCEINLINE path& path::normalize()
+{
+ path tmp(lexically_normal());
+ m_pathname.swap(tmp.m_pathname);
+ return *this;
+}
+
+#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+
+// The following functions are defined differently, depending on Boost.Filesystem version in use.
+// To avoid ODR violation, these functions are not defined when the library itself is built.
+// This makes sure they are not compiled when the library is built, and the only version there is
+// is the one in user's code. Users are supposed to consistently use the same Boost.Filesystem version
+// in all their translation units.
+#if !defined(BOOST_FILESYSTEM_SOURCE)
+
+BOOST_FORCEINLINE path& path::append(path const& p)
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size());
+ return *this;
+}
+
+BOOST_FORCEINLINE path& path::append(path const& p, codecvt_type const&)
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size());
+ return *this;
+}
+
+BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end)
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end);
+ return *this;
+}
+
+BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end, codecvt_type const&)
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end);
+ return *this;
+}
+
+BOOST_FORCEINLINE path& path::remove_filename()
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::remove_filename)(*this);
+ return *this;
+}
+
+BOOST_FORCEINLINE path& path::replace_extension(path const& new_extension)
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::replace_extension)(*this, new_extension);
+ return *this;
+}
+
+BOOST_FORCEINLINE int path::compare(path const& p) const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::compare)(*this, p);
+}
+
+BOOST_FORCEINLINE path path::filename() const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::filename)(*this);
+}
+
+BOOST_FORCEINLINE path path::stem() const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::stem)(*this);
+}
+
+BOOST_FORCEINLINE path path::extension() const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::extension)(*this);
+}
+
+BOOST_FORCEINLINE bool path::has_filename() const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::has_filename)(*this);
+}
+
+BOOST_FORCEINLINE path path::lexically_normal() const
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lexically_normal)(*this);
+}
+
+namespace path_detail {
+
+BOOST_FORCEINLINE void path_iterator::increment()
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::increment)(*this);
+}
+
+BOOST_FORCEINLINE void path_iterator::decrement()
+{
+ BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::decrement)(*this);
+}
+
+BOOST_FORCEINLINE bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2)
+{
+ return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lex_compare)(first1, last1, first2, last2) < 0;
+}
+
+} // namespace path_detail
+
+#endif // !defined(BOOST_FILESYSTEM_SOURCE)
+
//--------------------------------------------------------------------------------------//
// class path member template specializations //
//--------------------------------------------------------------------------------------//
-template<>
+template< >
inline std::string path::string< std::string >() const
{
return string();
}
-template<>
+template< >
inline std::wstring path::string< std::wstring >() const
{
return wstring();
}
-template<>
-inline std::string path::string< std::string >(const codecvt_type& cvt) const
+template< >
+inline std::string path::string< std::string >(codecvt_type const& cvt) const
{
return string(cvt);
}
-template<>
-inline std::wstring path::string< std::wstring >(const codecvt_type& cvt) const
+template< >
+inline std::wstring path::string< std::wstring >(codecvt_type const& cvt) const
{
return wstring(cvt);
}
-template<>
+template< >
inline std::string path::generic_string< std::string >() const
{
return generic_string();
}
-template<>
+template< >
inline std::wstring path::generic_string< std::wstring >() const
{
return generic_wstring();
}
-template<>
+template< >
inline std::string path::generic_string< std::string >(codecvt_type const& cvt) const
{
return generic_string(cvt);
}
-template<>
+template< >
inline std::wstring path::generic_string< std::wstring >(codecvt_type const& cvt) const
{
return generic_wstring(cvt);
}
-//--------------------------------------------------------------------------------------//
-// path_traits convert function implementations //
-// requiring path::codecvt() be visable //
-//--------------------------------------------------------------------------------------//
-
-namespace path_traits { // without codecvt
-
-inline void convert(const char* from,
- const char* from_end, // NULL for null terminated MBCS
- std::wstring& to)
-{
- convert(from, from_end, to, path::codecvt());
-}
-
-inline void convert(const wchar_t* from,
- const wchar_t* from_end, // NULL for null terminated MBCS
- std::string& to)
-{
- convert(from, from_end, to, path::codecvt());
-}
-
-inline void convert(const char* from, std::wstring& to)
-{
- BOOST_ASSERT(!!from);
- convert(from, NULL, to, path::codecvt());
-}
-
-inline void convert(const wchar_t* from, std::string& to)
-{
- BOOST_ASSERT(!!from);
- convert(from, NULL, to, path::codecvt());
-}
-
-} // namespace path_traits
} // namespace filesystem
} // namespace boost
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp
deleted file mode 100644
index e4f9b52c0d..0000000000
--- a/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp
+++ /dev/null
@@ -1,384 +0,0 @@
-// filesystem path_traits.hpp --------------------------------------------------------//
-
-// Copyright Beman Dawes 2009
-
-// Distributed under the Boost Software License, Version 1.0.
-// See http://www.boost.org/LICENSE_1_0.txt
-
-// Library home page: http://www.boost.org/libs/filesystem
-
-#ifndef BOOST_FILESYSTEM_PATH_TRAITS_HPP
-#define BOOST_FILESYSTEM_PATH_TRAITS_HPP
-
-#include <boost/filesystem/config.hpp>
-#include <boost/system/error_category.hpp>
-#include <boost/type_traits/is_array.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/core/enable_if.hpp>
-#include <cstddef>
-#include <cwchar> // for mbstate_t
-#include <string>
-#include <vector>
-#include <list>
-#include <iterator>
-#include <locale>
-#include <boost/assert.hpp>
-
-#include <boost/filesystem/detail/header.hpp> // must be the last #include
-
-namespace boost {
-namespace filesystem {
-
-BOOST_FILESYSTEM_DECL system::error_category const& codecvt_error_category() BOOST_NOEXCEPT;
-// uses std::codecvt_base::result used for error codes:
-//
-// ok: Conversion successful.
-// partial: Not all source characters converted; one or more additional source
-// characters are needed to produce the final target character, or the
-// size of the target intermediate buffer was too small to hold the result.
-// error: A character in the source could not be converted to the target encoding.
-// noconv: The source and target characters have the same type and encoding, so no
-// conversion was necessary.
-
-class directory_entry;
-
-namespace path_traits {
-
-typedef std::codecvt< wchar_t, char, std::mbstate_t > codecvt_type;
-
-// is_pathable type trait; allows disabling over-agressive class path member templates
-
-template< class T >
-struct is_pathable
-{
- static const bool value = false;
-};
-
-template<>
-struct is_pathable< char* >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< const char* >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< wchar_t* >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< const wchar_t* >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::string >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::wstring >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::vector< char > >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::vector< wchar_t > >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::list< char > >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< std::list< wchar_t > >
-{
- static const bool value = true;
-};
-
-template<>
-struct is_pathable< directory_entry >
-{
- static const bool value = true;
-};
-
-// Pathable empty
-
-template< class Container >
-inline
- // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
- // conforming compilers. Replace by plain "bool" at some future date (2012?)
- typename boost::disable_if< boost::is_array< Container >, bool >::type
- empty(Container const& c)
-{
- return c.begin() == c.end();
-}
-
-template< class T >
-inline bool empty(T* const& c_str)
-{
- BOOST_ASSERT(c_str);
- return !*c_str;
-}
-
-template< typename T, std::size_t N >
-inline bool empty(T (&x)[N])
-{
- return !x[0];
-}
-
-// value types differ ---------------------------------------------------------------//
-//
-// A from_end argument of NULL is less efficient than a known end, so use only if needed
-
-// with codecvt
-
-BOOST_FILESYSTEM_DECL
-void convert(const char* from,
- const char* from_end, // NULL for null terminated MBCS
- std::wstring& to, codecvt_type const& cvt);
-
-BOOST_FILESYSTEM_DECL
-void convert(const wchar_t* from,
- const wchar_t* from_end, // NULL for null terminated MBCS
- std::string& to, codecvt_type const& cvt);
-
-inline void convert(const char* from, std::wstring& to, codecvt_type const& cvt)
-{
- BOOST_ASSERT(from);
- convert(from, NULL, to, cvt);
-}
-
-inline void convert(const wchar_t* from, std::string& to, codecvt_type const& cvt)
-{
- BOOST_ASSERT(from);
- convert(from, NULL, to, cvt);
-}
-
-// without codecvt
-
-inline void convert(const char* from,
- const char* from_end, // NULL for null terminated MBCS
- std::wstring& to);
-
-inline void convert(const wchar_t* from,
- const wchar_t* from_end, // NULL for null terminated MBCS
- std::string& to);
-
-inline void convert(const char* from, std::wstring& to);
-
-inline void convert(const wchar_t* from, std::string& to);
-
-// value types same -----------------------------------------------------------------//
-
-// char with codecvt
-
-inline void convert(const char* from, const char* from_end, std::string& to, codecvt_type const&)
-{
- BOOST_ASSERT(from);
- BOOST_ASSERT(from_end);
- to.append(from, from_end);
-}
-
-inline void convert(const char* from, std::string& to, codecvt_type const&)
-{
- BOOST_ASSERT(from);
- to += from;
-}
-
-// wchar_t with codecvt
-
-inline void convert(const wchar_t* from, const wchar_t* from_end, std::wstring& to, codecvt_type const&)
-{
- BOOST_ASSERT(from);
- BOOST_ASSERT(from_end);
- to.append(from, from_end);
-}
-
-inline void convert(const wchar_t* from, std::wstring& to, codecvt_type const&)
-{
- BOOST_ASSERT(from);
- to += from;
-}
-
-// char without codecvt
-
-inline void convert(const char* from, const char* from_end, std::string& to)
-{
- BOOST_ASSERT(from);
- BOOST_ASSERT(from_end);
- to.append(from, from_end);
-}
-
-inline void convert(const char* from, std::string& to)
-{
- BOOST_ASSERT(from);
- to += from;
-}
-
-// wchar_t without codecvt
-
-inline void convert(const wchar_t* from, const wchar_t* from_end, std::wstring& to)
-{
- BOOST_ASSERT(from);
- BOOST_ASSERT(from_end);
- to.append(from, from_end);
-}
-
-inline void convert(const wchar_t* from, std::wstring& to)
-{
- BOOST_ASSERT(from);
- to += from;
-}
-
-// Source dispatch -----------------------------------------------------------------//
-
-// contiguous containers with codecvt
-template< class U >
-inline void dispatch(std::string const& c, U& to, codecvt_type const& cvt)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
-}
-template< class U >
-inline void dispatch(std::wstring const& c, U& to, codecvt_type const& cvt)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
-}
-template< class U >
-inline void dispatch(std::vector< char > const& c, U& to, codecvt_type const& cvt)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
-}
-template< class U >
-inline void dispatch(std::vector< wchar_t > const& c, U& to, codecvt_type const& cvt)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
-}
-
-// contiguous containers without codecvt
-template< class U >
-inline void dispatch(std::string const& c, U& to)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to);
-}
-template< class U >
-inline void dispatch(std::wstring const& c, U& to)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to);
-}
-template< class U >
-inline void dispatch(std::vector< char > const& c, U& to)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to);
-}
-template< class U >
-inline void dispatch(std::vector< wchar_t > const& c, U& to)
-{
- if (!c.empty())
- convert(&*c.begin(), &*c.begin() + c.size(), to);
-}
-
-// non-contiguous containers with codecvt
-template< class Container, class U >
-inline
- // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
- // conforming compilers. Replace by plain "void" at some future date (2012?)
- typename boost::disable_if< boost::is_array< Container >, void >::type
- dispatch(Container const& c, U& to, codecvt_type const& cvt)
-{
- if (!c.empty())
- {
- std::basic_string< typename Container::value_type > s(c.begin(), c.end());
- convert(s.c_str(), s.c_str() + s.size(), to, cvt);
- }
-}
-
-// c_str
-template< class T, class U >
-inline void dispatch(T* const& c_str, U& to, codecvt_type const& cvt)
-{
- // std::cout << "dispatch() const T *\n";
- BOOST_ASSERT(c_str);
- convert(c_str, to, cvt);
-}
-
-// Note: there is no dispatch on C-style arrays because the array may
-// contain a string smaller than the array size.
-
-BOOST_FILESYSTEM_DECL
-void dispatch(directory_entry const& de,
-#ifdef BOOST_WINDOWS_API
- std::wstring& to,
-#else
- std::string& to,
-#endif
- codecvt_type const&);
-
-// non-contiguous containers without codecvt
-template< class Container, class U >
-inline
- // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
- // conforming compilers. Replace by plain "void" at some future date (2012?)
- typename boost::disable_if< boost::is_array< Container >, void >::type
- dispatch(Container const& c, U& to)
-{
- if (!c.empty())
- {
- std::basic_string< typename Container::value_type > seq(c.begin(), c.end());
- convert(seq.c_str(), seq.c_str() + seq.size(), to);
- }
-}
-
-// c_str
-template< class T, class U >
-inline void dispatch(T* const& c_str, U& to)
-{
- // std::cout << "dispatch() const T *\n";
- BOOST_ASSERT(c_str);
- convert(c_str, to);
-}
-
-// Note: there is no dispatch on C-style arrays because the array may
-// contain a string smaller than the array size.
-
-BOOST_FILESYSTEM_DECL
-void dispatch(directory_entry const& de,
-#ifdef BOOST_WINDOWS_API
- std::wstring& to
-#else
- std::string& to
-#endif
-);
-
-} // namespace path_traits
-} // namespace filesystem
-} // namespace boost
-
-#include <boost/filesystem/detail/footer.hpp>
-
-#endif // BOOST_FILESYSTEM_PATH_TRAITS_HPP
diff --git a/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp b/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp
index 72db677a09..a8d2a42732 100644
--- a/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp
+++ b/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp
@@ -15,7 +15,7 @@
#include <boost/config/warning_disable.hpp>
#include <boost/filesystem/config.hpp>
-#include <boost/filesystem/path_traits.hpp>
+#include <boost/filesystem/detail/path_traits.hpp>
#include <boost/system/error_category.hpp>
#include <locale>
#include <string>
diff --git a/contrib/restricted/boost/filesystem/src/directory.cpp b/contrib/restricted/boost/filesystem/src/directory.cpp
index 6a3e1dc731..f769f8fc18 100644
--- a/contrib/restricted/boost/filesystem/src/directory.cpp
+++ b/contrib/restricted/boost/filesystem/src/directory.cpp
@@ -74,15 +74,6 @@
#include <boost/filesystem/detail/header.hpp> // must be the last #include
-// BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
-// dir_itr_increment. The config tests are placed here because some of the
-// macros being tested come from dirent.h.
-//
-// TODO: find out what macros indicate dirent::d_type present in more libraries
-#if defined(BOOST_WINDOWS_API) || defined(_DIRENT_HAVE_D_TYPE) // defined by GNU C library if d_type present
-#define BOOST_FILESYSTEM_STATUS_CACHE
-#endif
-
namespace fs = boost::filesystem;
using boost::system::error_code;
using boost::system::system_category;
@@ -96,76 +87,34 @@ namespace filesystem {
// //
//--------------------------------------------------------------------------------------//
-BOOST_FILESYSTEM_DECL
-file_status directory_entry::get_status(system::error_code* ec) const
+BOOST_FILESYSTEM_DECL void directory_entry::refresh_impl(system::error_code* ec) const
{
- if (!status_known(m_status))
+ system::error_code local_ec;
+ m_symlink_status = detail::symlink_status(m_path, &local_ec);
+
+ if (!filesystem::is_symlink(m_symlink_status))
{
- // optimization: if the symlink status is known, and it isn't a symlink,
- // then status and symlink_status are identical so just copy the
- // symlink status to the regular status.
- if (status_known(m_symlink_status) && !is_symlink(m_symlink_status))
- {
- m_status = m_symlink_status;
- if (ec)
- ec->clear();
- }
- else
+ // Also works if symlink_status fails - set m_status to status_error as well
+ m_status = m_symlink_status;
+
+ if (BOOST_UNLIKELY(!!local_ec))
{
- m_status = detail::status(m_path, ec);
+ if (!ec)
+ BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::directory_entry::refresh", m_path, local_ec));
+
+ *ec = local_ec;
+ return;
}
+
+ if (ec)
+ ec->clear();
}
- else if (ec)
+ else
{
- ec->clear();
+ m_status = detail::status(m_path, ec);
}
-
- return m_status;
}
-BOOST_FILESYSTEM_DECL
-file_status directory_entry::get_symlink_status(system::error_code* ec) const
-{
- if (!status_known(m_symlink_status))
- m_symlink_status = detail::symlink_status(m_path, ec);
- else if (ec)
- ec->clear();
-
- return m_symlink_status;
-}
-
-// dispatch directory_entry supplied here rather than in
-// <boost/filesystem/path_traits.hpp>, thus avoiding header circularity.
-// test cases are in operations_unit_test.cpp
-
-namespace path_traits {
-
-BOOST_FILESYSTEM_DECL
-void dispatch(directory_entry const& de,
-#ifdef BOOST_WINDOWS_API
- std::wstring& to,
-#else
- std::string& to,
-#endif
- codecvt_type const&)
-{
- to = de.path().native();
-}
-
-BOOST_FILESYSTEM_DECL
-void dispatch(directory_entry const& de,
-#ifdef BOOST_WINDOWS_API
- std::wstring& to
-#else
- std::string& to
-#endif
-)
-{
- to = de.path().native();
-}
-
-} // namespace path_traits
-
//--------------------------------------------------------------------------------------//
// //
// directory_iterator //
@@ -353,24 +302,43 @@ error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_stat
filename = result->d_name;
-#ifdef BOOST_FILESYSTEM_STATUS_CACHE
+#if defined(BOOST_FILESYSTEM_HAS_DIRENT_D_TYPE)
if (result->d_type == DT_UNKNOWN) // filesystem does not supply d_type value
{
sf = symlink_sf = fs::file_status(fs::status_error);
}
else // filesystem supplies d_type value
{
- if (result->d_type == DT_DIR)
- sf = symlink_sf = fs::file_status(fs::directory_file);
- else if (result->d_type == DT_REG)
+ if (result->d_type == DT_REG)
sf = symlink_sf = fs::file_status(fs::regular_file);
+ else if (result->d_type == DT_DIR)
+ sf = symlink_sf = fs::file_status(fs::directory_file);
else if (result->d_type == DT_LNK)
{
sf = fs::file_status(fs::status_error);
symlink_sf = fs::file_status(fs::symlink_file);
}
else
- sf = symlink_sf = fs::file_status(fs::status_error);
+ {
+ switch (result->d_type)
+ {
+ case DT_SOCK:
+ sf = symlink_sf = fs::file_status(fs::socket_file);
+ break;
+ case DT_FIFO:
+ sf = symlink_sf = fs::file_status(fs::fifo_file);
+ break;
+ case DT_BLK:
+ sf = symlink_sf = fs::file_status(fs::block_file);
+ break;
+ case DT_CHR:
+ sf = symlink_sf = fs::file_status(fs::character_file);
+ break;
+ default:
+ sf = symlink_sf = fs::file_status(fs::status_error);
+ break;
+ }
+ }
}
#else
sf = symlink_sf = fs::file_status(fs::status_error);
@@ -599,9 +567,12 @@ extra_data_format g_extra_data_format = file_directory_information_format;
* \brief Extra buffer size for GetFileInformationByHandleEx-based or NtQueryDirectoryFile-based directory iterator.
*
* Must be large enough to accommodate at least one FILE_DIRECTORY_INFORMATION or *_DIR_INFO struct and one filename.
- * NTFS, VFAT, exFAT support filenames up to 255 UTF-16/UCS-2 characters. ReFS supports filenames up to 32768 UTF-16 characters.
+ * NTFS, VFAT, exFAT and ReFS support filenames up to 255 UTF-16/UCS-2 characters. (For ReFS, there is no information
+ * on the on-disk format, and it is possible that it supports longer filenames, up to 32768 UTF-16/UCS-2 characters.)
+ * The buffer cannot be larger than 64k, because up to Windows 8.1, NtQueryDirectoryFile and GetFileInformationByHandleEx
+ * fail with ERROR_INVALID_PARAMETER when trying to retrieve the filenames from a network share.
*/
-BOOST_CONSTEXPR_OR_CONST std::size_t dir_itr_extra_size = sizeof(file_id_extd_dir_info) + 65536u;
+BOOST_CONSTEXPR_OR_CONST std::size_t dir_itr_extra_size = 65536u;
inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT
{
@@ -763,6 +734,28 @@ done:
return error_code();
}
+//! Returns \c true if the error code indicates that the OS or the filesystem does not support a particular directory info class
+inline bool is_dir_info_class_not_supported(DWORD error)
+{
+ // Some mounted filesystems may not support FILE_ID_128 identifiers, which will cause
+ // GetFileInformationByHandleEx(FileIdExtdDirectoryRestartInfo) return ERROR_INVALID_PARAMETER,
+ // even though in general the operation is supported by the kernel. SMBv1 returns a special error
+ // code ERROR_INVALID_LEVEL in this case.
+ // Some other filesystems also don't implement other info classes and return ERROR_INVALID_PARAMETER
+ // (e.g. see https://github.com/boostorg/filesystem/issues/266), ERROR_GEN_FAILURE, ERROR_INVALID_FUNCTION
+ // or ERROR_INTERNAL_ERROR (https://github.com/boostorg/filesystem/issues/286). Treat these error codes
+ // as "non-permanent", even though ERROR_INVALID_PARAMETER is also returned if GetFileInformationByHandleEx
+ // in general does not support a certain info class. Worst case, we will make extra syscalls on directory
+ // iterator construction.
+ // Also note that Wine returns ERROR_CALL_NOT_IMPLEMENTED for unimplemented info classes, and
+ // up until 7.21 it didn't implement FileIdExtdDirectoryRestartInfo and FileFullDirectoryRestartInfo.
+ // (https://bugs.winehq.org/show_bug.cgi?id=53590)
+ return error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER ||
+ error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED ||
+ error == ERROR_GEN_FAILURE || error == ERROR_INVALID_FUNCTION ||
+ error == ERROR_INTERNAL_ERROR;
+}
+
error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params* params, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf)
{
boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (dir_itr_extra_size) detail::dir_itr_imp());
@@ -828,9 +821,14 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
if (BOOST_UNLIKELY((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u))
return make_error_code(system::errc::not_a_directory);
- if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u)
+ if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u && (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u)
{
- if ((info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_a_symlink_ioctl(h.handle))
+ error_code ec;
+ const ULONG reparse_point_tag = detail::get_reparse_point_tag_ioctl(h.handle, dir, &ec);
+ if (BOOST_UNLIKELY(!!ec))
+ return ec;
+
+ if (detail::is_reparse_point_tag_a_symlink(reparse_point_tag))
return make_error_code(system::errc::too_many_symbolic_link_levels);
}
}
@@ -845,14 +843,10 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
{
DWORD error = ::GetLastError();
- if (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER)
+ if (is_dir_info_class_not_supported(error))
{
// Fall back to file_full_dir_info_format.
- // Note that some mounted filesystems may not support FILE_ID_128 identifiers, which will cause
- // GetFileInformationByHandleEx(FileIdExtdDirectoryRestartInfo) return ERROR_INVALID_PARAMETER,
- // even though in general the operation is supported by the kernel. So don't downgrade to
- // FileFullDirectoryRestartInfo permanently in this case - only for this particular iterator.
- if (error == ERROR_NOT_SUPPORTED)
+ if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_full_dir_info_format);
goto fallback_to_file_full_dir_info_format;
}
@@ -879,11 +873,12 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
{
DWORD error = ::GetLastError();
- if (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER)
+ if (is_dir_info_class_not_supported(error))
{
// Fall back to file_id_both_dir_info
- filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_id_both_dir_info_format);
- goto fallback_to_file_id_both_dir_info;
+ if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
+ filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_id_both_dir_info_format);
+ goto fallback_to_file_id_both_dir_info_format;
}
if (error == ERROR_NO_MORE_FILES || error == ERROR_FILE_NOT_FOUND)
@@ -902,12 +897,20 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
break;
case file_id_both_dir_info_format:
- fallback_to_file_id_both_dir_info:
+ fallback_to_file_id_both_dir_info_format:
{
if (!get_file_information_by_handle_ex(iterator_handle, file_id_both_directory_restart_info_class, extra_data, dir_itr_extra_size))
{
DWORD error = ::GetLastError();
+ if (is_dir_info_class_not_supported(error))
+ {
+ // Fall back to file_directory_information
+ if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
+ filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_directory_information_format);
+ goto fallback_to_file_directory_information_format;
+ }
+
if (error == ERROR_NO_MORE_FILES || error == ERROR_FILE_NOT_FOUND)
goto done;
@@ -924,6 +927,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
break;
default:
+ fallback_to_file_directory_information_format:
{
NtQueryDirectoryFile_t* nt_query_directory_file = filesystem::detail::atomic_load_relaxed(boost::filesystem::detail::nt_query_directory_file_api);
if (BOOST_UNLIKELY(!nt_query_directory_file))
@@ -1120,7 +1124,18 @@ void directory_iterator_construct(directory_iterator& it, path const& p, unsigne
&& (filename_str[1] == static_cast< path::string_type::value_type >('\0') ||
(filename_str[1] == path::dot && filename_str[2] == static_cast< path::string_type::value_type >('\0')))))
{
- imp->dir_entry.assign(p / filename, file_stat, symlink_file_stat);
+ path full_path(p);
+ path_algorithms::append_v4(full_path, filename);
+ imp->dir_entry.assign_with_status
+ (
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ static_cast< path&& >(full_path),
+#else
+ full_path,
+#endif
+ file_stat,
+ symlink_file_stat
+ );
it.m_imp.swap(imp);
return;
}
@@ -1180,7 +1195,7 @@ void directory_iterator_increment(directory_iterator& it, system::error_code* ec
&& (filename_str[1] == static_cast< path::string_type::value_type >('\0') ||
(filename_str[1] == path::dot && filename_str[2] == static_cast< path::string_type::value_type >('\0')))))
{
- it.m_imp->dir_entry.replace_filename(filename, file_stat, symlink_file_stat);
+ it.m_imp->dir_entry.replace_filename_with_status(filename, file_stat, symlink_file_stat);
return;
}
}
@@ -1344,14 +1359,14 @@ inline push_directory_result recursive_directory_iterator_push_directory(detail:
return result;
}
- file_status symlink_stat;
+ file_type symlink_ft = status_error;
// If we are not recursing into symlinks, we are going to have to know if the
// stack top is a symlink, so get symlink_status and verify no error occurred.
if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) == 0u ||
(imp->m_options & static_cast< unsigned int >(directory_options::skip_dangling_symlinks)) != 0u)
{
- symlink_stat = imp->m_stack.back()->symlink_status(ec);
+ symlink_ft = imp->m_stack.back()->symlink_file_type(ec);
if (ec)
return result;
}
@@ -1364,12 +1379,12 @@ inline push_directory_result recursive_directory_iterator_push_directory(detail:
// The predicate code has since been rewritten to pass error_code arguments,
// per ticket #5653.
- if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) != 0u || !fs::is_symlink(symlink_stat))
+ if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) != 0u || symlink_ft != symlink_file)
{
- file_status stat = imp->m_stack.back()->status(ec);
+ file_type ft = imp->m_stack.back()->file_type(ec);
if (BOOST_UNLIKELY(!!ec))
{
- if (ec == make_error_condition(system::errc::no_such_file_or_directory) && fs::is_symlink(symlink_stat) &&
+ if (ec == make_error_condition(system::errc::no_such_file_or_directory) && symlink_ft == symlink_file &&
(imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) == static_cast< unsigned int >(directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks))
{
// Skip dangling symlink and continue iteration on the current depth level
@@ -1379,7 +1394,7 @@ inline push_directory_result recursive_directory_iterator_push_directory(detail:
return result;
}
- if (!fs::is_directory(stat))
+ if (ft != directory_file)
return result;
if (BOOST_UNLIKELY((imp->m_stack.size() - 1u) >= static_cast< std::size_t >((std::numeric_limits< int >::max)())))
diff --git a/contrib/restricted/boost/filesystem/src/operations.cpp b/contrib/restricted/boost/filesystem/src/operations.cpp
index dd636e9063..c7808d5941 100644
--- a/contrib/restricted/boost/filesystem/src/operations.cpp
+++ b/contrib/restricted/boost/filesystem/src/operations.cpp
@@ -70,7 +70,7 @@
#include <unistd.h>
#include <fcntl.h>
-#if _POSIX_C_SOURCE < 200809L
+#if !defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS)
#include <utime.h>
#endif
#include <limits.h>
@@ -1116,7 +1116,7 @@ uintmax_t remove_all_impl
count += fs::detail::remove_all_impl
(
#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS)
- itr->path().filename(),
+ path_algorithms::filename_v4(itr->path()),
#else
itr->path(),
#endif
@@ -1511,50 +1511,36 @@ boost::winapi::NTSTATUS_ nt_create_file_handle_at(HANDLE& out, HANDLE basedir_ha
#endif // !defined(UNDER_CE)
-bool is_reparse_point_a_symlink_ioctl(HANDLE h)
+ULONG get_reparse_point_tag_ioctl(HANDLE h, path const& p, error_code* ec)
{
- boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new reparse_data_buffer_with_storage);
+ boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new (std::nothrow) reparse_data_buffer_with_storage);
+ if (BOOST_UNLIKELY(!buf.get()))
+ {
+ if (!ec)
+ BOOST_FILESYSTEM_THROW(filesystem_error("Cannot allocate memory to query reparse point", p, make_error_code(system::errc::not_enough_memory)));
+
+ *ec = make_error_code(system::errc::not_enough_memory);
+ return 0u;
+ }
// Query the reparse data
DWORD dwRetLen = 0u;
BOOL result = ::DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), sizeof(*buf), &dwRetLen, NULL);
if (BOOST_UNLIKELY(!result))
- return false;
-
- return is_reparse_point_tag_a_symlink(buf->rdb.ReparseTag);
-}
-
-namespace {
-
-inline bool is_reparse_point_a_symlink(path const& p)
-{
- handle_wrapper h(create_file_handle(
- p,
- FILE_READ_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT));
- if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE))
- return false;
-
- GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api);
- if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL))
{
- file_attribute_tag_info info;
- BOOL result = get_file_information_by_handle_ex(h.handle, file_attribute_tag_info_class, &info, sizeof(info));
- if (BOOST_UNLIKELY(!result))
- return false;
-
- if ((info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0u)
- return false;
+ DWORD err = ::GetLastError();
+ if (!ec)
+ BOOST_FILESYSTEM_THROW(filesystem_error("Failed to query reparse point", p, error_code(err, system_category())));
- return is_reparse_point_tag_a_symlink(info.ReparseTag);
+ ec->assign(err, system_category());
+ return 0u;
}
- return is_reparse_point_a_symlink_ioctl(h.handle);
+ return buf->rdb.ReparseTag;
}
+namespace {
+
inline std::size_t get_full_path_name(path const& src, std::size_t len, wchar_t* buf, wchar_t** p)
{
return static_cast< std::size_t >(::GetFullPathNameW(src.c_str(), static_cast< DWORD >(len), buf, p));
@@ -1590,6 +1576,7 @@ fs::file_status status_by_handle(HANDLE h, path const& p, error_code* ec)
{
fs::file_type ftype;
DWORD attrs;
+ ULONG reparse_tag = 0u;
GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api);
if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL))
{
@@ -1609,12 +1596,7 @@ fs::file_status status_by_handle(HANDLE h, path const& p, error_code* ec)
}
attrs = info.FileAttributes;
-
- if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
- {
- ftype = is_reparse_point_tag_a_symlink(info.ReparseTag) ? fs::symlink_file : fs::reparse_file;
- goto done;
- }
+ reparse_tag = info.ReparseTag;
}
else
{
@@ -1626,25 +1608,48 @@ fs::file_status status_by_handle(HANDLE h, path const& p, error_code* ec)
attrs = info.dwFileAttributes;
- if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
+ if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0u)
{
- ftype = is_reparse_point_a_symlink_ioctl(h) ? fs::symlink_file : fs::reparse_file;
- goto done;
+ reparse_tag = get_reparse_point_tag_ioctl(h, p, ec);
+ if (ec)
+ {
+ if (BOOST_UNLIKELY(!!ec))
+ return fs::file_status(fs::status_error);
+ }
}
}
- ftype = (attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file;
+ if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0u)
+ {
+ if (reparse_tag == IO_REPARSE_TAG_DEDUP)
+ ftype = fs::regular_file;
+ else if (is_reparse_point_tag_a_symlink(reparse_tag))
+ ftype = fs::symlink_file;
+ else
+ ftype = fs::reparse_file;
+ }
+ else if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0u)
+ {
+ ftype = fs::directory_file;
+ }
+ else
+ {
+ ftype = fs::regular_file;
+ }
-done:
return fs::file_status(ftype, make_permissions(p, attrs));
}
//! symlink_status() implementation
fs::file_status symlink_status_impl(path const& p, error_code* ec)
{
+ // Normally, we only need FILE_READ_ATTRIBUTES access mode. But SMBv1 reports incorrect
+ // file attributes in GetFileInformationByHandleEx in this case (e.g. it reports FILE_ATTRIBUTE_NORMAL
+ // for a directory in a SMBv1 share), so we add FILE_READ_EA as a workaround.
+ // https://github.com/boostorg/filesystem/issues/282
handle_wrapper h(create_file_handle(
p.c_str(),
- FILE_READ_ATTRIBUTES, // dwDesiredAccess; attributes only
+ FILE_READ_ATTRIBUTES | FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // lpSecurityAttributes
OPEN_EXISTING,
@@ -1688,7 +1693,7 @@ fs::file_status status_impl(path const& p, error_code* ec)
// Resolve the symlink
handle_wrapper h(create_file_handle(
p.c_str(),
- FILE_READ_ATTRIBUTES, // dwDesiredAccess; attributes only
+ FILE_READ_ATTRIBUTES | FILE_READ_EA, // see the comment in symlink_status_impl re. access mode
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // lpSecurityAttributes
OPEN_EXISTING,
@@ -1775,7 +1780,7 @@ DWORD remove_nt6_by_handle(HANDLE handle, remove_impl_type impl)
break;
err = ::GetLastError();
- if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED))
+ if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED || err == ERROR_CALL_NOT_IMPLEMENTED))
{
// Downgrade to the older implementation
impl = remove_disp_ex_flag_posix_semantics;
@@ -1833,7 +1838,7 @@ DWORD remove_nt6_by_handle(HANDLE handle, remove_impl_type impl)
break;
}
- else if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED))
+ else if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED || err == ERROR_CALL_NOT_IMPLEMENTED))
{
// Downgrade to the older implementation
impl = remove_disp;
@@ -1902,7 +1907,7 @@ inline bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec
{
handle_wrapper h(create_file_handle(
p,
- DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+ DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
@@ -1999,12 +2004,12 @@ uintmax_t remove_all_nt6_by_handle(HANDLE h, path const& p, error_code* ec)
(
hh.handle,
h,
- nested_path.filename(),
+ path_algorithms::filename_v4(nested_path),
0u, // FileAttributes
- FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
+ FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
- FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
);
if (!NT_SUCCESS(status))
@@ -2027,7 +2032,7 @@ uintmax_t remove_all_nt6_by_handle(HANDLE h, path const& p, error_code* ec)
{
hh.handle = create_file_handle(
nested_path,
- FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
+ FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
@@ -2144,7 +2149,7 @@ inline uintmax_t remove_all_impl(path const& p, error_code* ec)
{
handle_wrapper h(create_file_handle(
p,
- FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
+ FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
@@ -2385,12 +2390,12 @@ path absolute(path const& p, path const& base, system::error_code* ec)
else
{
res.concat(abs_base.root_directory());
- res /= abs_base.relative_path();
+ path_algorithms::append_v4(res, abs_base.relative_path());
}
path p_relative_path(p.relative_path());
if (!p_relative_path.empty())
- res /= p_relative_path;
+ path_algorithms::append_v4(res, p_relative_path);
return res;
}
@@ -2437,14 +2442,14 @@ path canonical(path const& p, path const& base, system::error_code* ec)
path result;
while (true)
{
- for (path::iterator itr(source.begin()), end(source.end()); itr != end; ++itr)
+ for (path::iterator itr(source.begin()), end(source.end()); itr != end; path_algorithms::increment_v4(itr))
{
- if (*itr == dot_p)
+ if (path_algorithms::compare_v4(*itr, dot_p) == 0)
continue;
- if (*itr == dot_dot_p)
+ if (path_algorithms::compare_v4(*itr, dot_dot_p) == 0)
{
- if (result != root)
- result.remove_filename();
+ if (path_algorithms::compare_v4(result, root) != 0)
+ result.remove_filename_and_trailing_separators();
continue;
}
@@ -2459,7 +2464,7 @@ path canonical(path const& p, path const& base, system::error_code* ec)
continue;
}
- result /= *itr;
+ path_algorithms::append_v4(result, *itr);
// If we don't have an absolute path yet then don't check symlink status.
// This avoids checking "C:" which is "the current directory on drive C"
@@ -2484,14 +2489,14 @@ path canonical(path const& p, path const& base, system::error_code* ec)
path link(detail::read_symlink(result, ec));
if (ec && *ec)
goto return_empty_path;
- result.remove_filename();
+ result.remove_filename_and_trailing_separators();
if (link.is_absolute())
{
- for (++itr; itr != end; ++itr)
+ for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr))
{
- if (*itr != dot_p)
- link /= *itr;
+ if (path_algorithms::compare_v4(*itr, dot_p) != 0)
+ path_algorithms::append_v4(link, *itr);
}
source = link;
root = source.root_path();
@@ -2499,15 +2504,15 @@ path canonical(path const& p, path const& base, system::error_code* ec)
else // link is relative
{
link.remove_trailing_separator();
- if (link == dot_p)
+ if (path_algorithms::compare_v4(link, dot_p) == 0)
continue;
path new_source(result);
- new_source /= link;
- for (++itr; itr != end; ++itr)
+ path_algorithms::append_v4(new_source, link);
+ for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr))
{
- if (*itr != dot_p)
- new_source /= *itr;
+ if (path_algorithms::compare_v4(*itr, dot_p) != 0)
+ path_algorithms::append_v4(new_source, *itr);
}
source = new_source;
}
@@ -2603,10 +2608,10 @@ void copy(path const& from, path const& to, unsigned int options, system::error_
relative_from = detail::relative(abs_from, abs_to, ec);
if (ec && *ec)
return;
- if (relative_from != dot_path())
- relative_from /= from.filename();
+ if (path_algorithms::compare_v4(relative_from, dot_path()) != 0)
+ path_algorithms::append_v4(relative_from, path_algorithms::filename_v4(from));
else
- relative_from = from.filename();
+ relative_from = path_algorithms::filename_v4(from);
pfrom = &relative_from;
}
detail::create_symlink(*pfrom, to, ec);
@@ -2642,7 +2647,11 @@ void copy(path const& from, path const& to, unsigned int options, system::error_
}
if (is_directory(to_stat))
- detail::copy_file(from, to / from.filename(), options, ec);
+ {
+ path target(to);
+ path_algorithms::append_v4(target, path_algorithms::filename_v4(from));
+ detail::copy_file(from, target, options, ec);
+ }
else
detail::copy_file(from, to, options, ec);
}
@@ -2697,8 +2706,12 @@ void copy(path const& from, path const& to, unsigned int options, system::error_
while (itr != end_dit)
{
path const& p = itr->path();
- // Set _detail_recursing flag so that we don't recurse more than for one level deeper into the directory if options are copy_options::none
- detail::copy(p, to / p.filename(), options | static_cast< unsigned int >(copy_options::_detail_recursing), ec);
+ {
+ path target(to);
+ path_algorithms::append_v4(target, path_algorithms::filename_v4(p));
+ // Set _detail_recursing flag so that we don't recurse more than for one level deeper into the directory if options are copy_options::none
+ detail::copy(p, target, options | static_cast< unsigned int >(copy_options::_detail_recursing), ec);
+ }
if (ec && *ec)
return;
@@ -2953,7 +2966,14 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod
// Create handle_wrappers here so that CloseHandle calls don't clobber error code returned by GetLastError
handle_wrapper hw_from, hw_to;
- hw_from.handle = create_file_handle(from.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS);
+ // See the comment in last_write_time regarding access rights used here for GetFileTime.
+ hw_from.handle = create_file_handle(
+ from.c_str(),
+ FILE_READ_ATTRIBUTES | FILE_READ_EA,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS);
FILETIME lwt_from;
if (hw_from.handle == INVALID_HANDLE_VALUE)
@@ -2967,7 +2987,13 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod
if (!::GetFileTime(hw_from.handle, NULL, NULL, &lwt_from))
goto fail_last_error;
- hw_to.handle = create_file_handle(to.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS);
+ hw_to.handle = create_file_handle(
+ to.c_str(),
+ FILE_READ_ATTRIBUTES | FILE_READ_EA,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS);
if (hw_to.handle != INVALID_HANDLE_VALUE)
{
@@ -3088,9 +3114,9 @@ bool create_directories(path const& p, system::error_code* ec)
error_code local_ec;
// Find the initial part of the path that exists
- for (path fname = parent.filename(); parent.has_relative_path(); fname = parent.filename())
+ for (path fname = path_algorithms::filename_v4(parent); parent.has_relative_path(); fname = path_algorithms::filename_v4(parent))
{
- if (!fname.empty() && fname != dot_p && fname != dot_dot_p)
+ if (!fname.empty() && path_algorithms::compare_v4(fname, dot_p) != 0 && path_algorithms::compare_v4(fname, dot_dot_p) != 0)
{
file_status existing_status = detail::status_impl(parent, &local_ec);
@@ -3107,19 +3133,19 @@ bool create_directories(path const& p, system::error_code* ec)
}
}
- --it;
- parent.remove_filename();
+ path_algorithms::decrement_v4(it);
+ parent.remove_filename_and_trailing_separators();
}
// Create missing directories
bool created = false;
- for (; it != e; ++it)
+ for (; it != e; path_algorithms::increment_v4(it))
{
path const& fname = *it;
- parent /= fname;
- if (!fname.empty() && fname != dot_p && fname != dot_dot_p)
+ path_algorithms::append_v4(parent, fname);
+ if (!fname.empty() && path_algorithms::compare_v4(fname, dot_p) != 0 && path_algorithms::compare_v4(fname, dot_dot_p) != 0)
{
- created = create_directory(parent, NULL, &local_ec);
+ created = detail::create_directory(parent, NULL, &local_ec);
if (BOOST_UNLIKELY(!!local_ec))
{
if (!ec)
@@ -3749,9 +3775,10 @@ std::time_t creation_time(path const& p, system::error_code* ec)
#else // defined(BOOST_POSIX_API)
+ // See the comment in last_write_time regarding access rights used here for GetFileTime.
handle_wrapper hw(create_file_handle(
p.c_str(),
- FILE_READ_ATTRIBUTES,
+ FILE_READ_ATTRIBUTES | FILE_READ_EA,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
@@ -3765,7 +3792,6 @@ std::time_t creation_time(path const& p, system::error_code* ec)
}
FILETIME ct;
-
if (BOOST_UNLIKELY(!::GetFileTime(hw.handle, &ct, NULL, NULL)))
goto fail;
@@ -3807,9 +3833,12 @@ std::time_t last_write_time(path const& p, system::error_code* ec)
#else // defined(BOOST_POSIX_API)
+ // GetFileTime is documented to require GENERIC_READ access right, but this causes problems if the file
+ // is opened by another process without FILE_SHARE_READ. In practice, FILE_READ_ATTRIBUTES works, and
+ // FILE_READ_EA is also added for good measure, in case if it matters for SMBv1.
handle_wrapper hw(create_file_handle(
p.c_str(),
- FILE_READ_ATTRIBUTES,
+ FILE_READ_ATTRIBUTES | FILE_READ_EA,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
@@ -3823,7 +3852,6 @@ std::time_t last_write_time(path const& p, system::error_code* ec)
}
FILETIME lwt;
-
if (BOOST_UNLIKELY(!::GetFileTime(hw.handle, NULL, NULL, &lwt)))
goto fail;
@@ -4055,9 +4083,8 @@ path read_symlink(path const& p, system::error_code* ec)
DWORD error;
if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE))
{
+ return_last_error:
error = ::GetLastError();
-
- return_error:
emit_error(error, p, ec, "boost::filesystem::read_symlink");
return symlink_path;
}
@@ -4065,10 +4092,7 @@ path read_symlink(path const& p, system::error_code* ec)
boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new reparse_data_buffer_with_storage);
DWORD sz = 0u;
if (BOOST_UNLIKELY(!::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), sizeof(*buf), &sz, NULL)))
- {
- error = ::GetLastError();
- goto return_error;
- }
+ goto return_last_error;
const wchar_t* buffer;
std::size_t offset, len;
@@ -4310,11 +4334,8 @@ path temp_directory_path(system::error_code* ec)
#else // Windows
#if !defined(UNDER_CE)
- const wchar_t* tmp_env = L"TMP";
- const wchar_t* temp_env = L"TEMP";
- const wchar_t* localappdata_env = L"LOCALAPPDATA";
- const wchar_t* userprofile_env = L"USERPROFILE";
- const wchar_t* env_list[] = { tmp_env, temp_env, localappdata_env, userprofile_env };
+ static const wchar_t* env_list[] = { L"TMP", L"TEMP", L"LOCALAPPDATA", L"USERPROFILE" };
+ static const wchar_t temp_dir[] = L"Temp";
path p;
for (unsigned int i = 0; i < sizeof(env_list) / sizeof(*env_list); ++i)
@@ -4324,7 +4345,7 @@ path temp_directory_path(system::error_code* ec)
{
p = env;
if (i >= 2)
- p /= L"Temp";
+ path_algorithms::append_v4(p, temp_dir, temp_dir + (sizeof(temp_dir) / sizeof(*temp_dir) - 1u));
error_code lcl_ec;
if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec)
break;
@@ -4349,7 +4370,7 @@ path temp_directory_path(system::error_code* ec)
goto getwindir_error;
p = buf.get(); // do not depend on initial buf size, see ticket #10388
- p /= L"Temp";
+ path_algorithms::append_v4(p, temp_dir, temp_dir + (sizeof(temp_dir) / sizeof(*temp_dir) - 1u));
}
return p;
@@ -4395,7 +4416,12 @@ path system_complete(path const& p, system::error_code* ec)
{
#ifdef BOOST_POSIX_API
- return (p.empty() || p.is_absolute()) ? p : current_path() / p;
+ if (p.empty() || p.is_absolute())
+ return p;
+
+ path res(current_path());
+ path_algorithms::append_v4(res, p);
+ return res;
#else
if (p.empty())
@@ -4432,9 +4458,9 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec)
path::iterator itr(p_end);
path head(p);
- for (; !head.empty(); --itr)
+ for (; !head.empty(); path_algorithms::decrement_v4(itr))
{
- file_status head_status = detail::status_impl(head, &local_ec);
+ file_status head_status(detail::status_impl(head, &local_ec));
if (BOOST_UNLIKELY(head_status.type() == fs::status_error))
{
if (!ec)
@@ -4447,35 +4473,86 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec)
if (head_status.type() != fs::file_not_found)
break;
- head.remove_filename();
+ head.remove_filename_and_trailing_separators();
}
+ if (head.empty())
+ return path_algorithms::lexically_normal_v4(p);
+
+ path const& dot_p = dot_path();
+ path const& dot_dot_p = dot_dot_path();
+
#else
- // On Windows, filesystem APIs such as GetFileAttributesW perform lexical path normalization internally.
- // As a result, a path like "c:\a\.." can be reported as present even if "c:\a" is not. This would break
- // canonical, as symlink_status that it calls internally would report an error that the file at the intermediate
- // path does not exist. To avoid this, scan the initial path in the forward direction.
- // Also, operate on paths with preferred separators. This can be important on Windows since GetFileAttributesW,
- // which is called in status() may return "file not found" for paths to network shares and mounted cloud
- // storages that have forward slashes as separators.
+ // On Windows, filesystem APIs such as GetFileAttributesW and CreateFileW perform lexical path normalization
+ // internally. As a result, a path like "c:\a\.." can be reported as present even if "c:\a" is not. This would
+ // break canonical, as symlink_status that it calls internally would report an error that the file at the
+ // intermediate path does not exist. To avoid this, scan the initial path in the forward direction.
+ // Also, operate on paths with preferred separators. This can be important on Windows since GetFileAttributesW
+ // or CreateFileW, which is called in status() may return "file not found" for paths to network shares and
+ // mounted cloud storages that have forward slashes as separators.
+ // Also, avoid querying status of the root name such as \\?\c: as CreateFileW returns ERROR_INVALID_FUNCTION for
+ // such path. Querying the status of a root name such as c: is also not right as this path refers to the current
+ // directory on drive C:, which is not what we want to test for existence anyway.
path::iterator itr(p.begin());
path head;
- for (; itr != p_end; ++itr)
+ if (p.has_root_name())
{
- path const& p_elem = *itr;
- if (p_elem.size() == 1u && detail::is_directory_separator(p_elem.native()[0]))
+ BOOST_ASSERT(itr != p_end);
+ head = *itr;
+ path_algorithms::increment_v4(itr);
+ }
+
+ if (p.has_root_directory())
+ {
+ BOOST_ASSERT(itr != p_end);
+ // Convert generic separator returned by the iterator for the root directory to
+ // the preferred separator.
+ head += path::preferred_separator;
+ path_algorithms::increment_v4(itr);
+ }
+
+ if (!head.empty())
+ {
+ file_status head_status(detail::status_impl(head, &local_ec));
+ if (BOOST_UNLIKELY(head_status.type() == fs::status_error))
{
- // Convert generic separator returned by the iterator for the root directory to
- // the preferred separator.
- head += path::preferred_separator;
+ if (!ec)
+ BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::weakly_canonical", head, local_ec));
+
+ *ec = local_ec;
+ return path();
}
- else
+
+ if (head_status.type() == fs::file_not_found)
{
- head /= p_elem;
+ // If the root path does not exist then no path element exists
+ return path_algorithms::lexically_normal_v4(p);
}
+ }
+
+ path const& dot_p = dot_path();
+ path const& dot_dot_p = dot_dot_path();
+ for (; itr != p_end; path_algorithms::increment_v4(itr))
+ {
+ path const& p_elem = *itr;
+
+ // Avoid querying status of paths containing dot and dot-dot elements, as this will break
+ // if the root name starts with "\\?\".
+ if (path_algorithms::compare_v4(p_elem, dot_p) == 0)
+ continue;
+
+ if (path_algorithms::compare_v4(p_elem, dot_dot_p) == 0)
+ {
+ if (head.has_relative_path())
+ head.remove_filename_and_trailing_separators();
- file_status head_status = detail::status_impl(head, &local_ec);
+ continue;
+ }
+
+ path_algorithms::append_v4(head, p_elem);
+
+ file_status head_status(detail::status_impl(head, &local_ec));
if (BOOST_UNLIKELY(head_status.type() == fs::status_error))
{
if (!ec)
@@ -4487,38 +4564,27 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec)
if (head_status.type() == fs::file_not_found)
{
- head.remove_filename();
+ head.remove_filename_and_trailing_separators();
break;
}
}
+ if (head.empty())
+ return path_algorithms::lexically_normal_v4(p);
+
#endif
- path const& dot_p = dot_path();
- path const& dot_dot_p = dot_dot_path();
path tail;
bool tail_has_dots = false;
- for (; itr != p_end; ++itr)
+ for (; itr != p_end; path_algorithms::increment_v4(itr))
{
path const& tail_elem = *itr;
-#if defined(BOOST_WINDOWS_API)
- if (tail_elem.size() == 1u && detail::is_directory_separator(tail_elem.native()[0]))
- {
- // Convert generic separator returned by the iterator for the root directory to
- // the preferred separator.
- tail += path::preferred_separator;
- continue;
- }
-#endif
- tail /= tail_elem;
+ path_algorithms::append_v4(tail, tail_elem);
// for a later optimization, track if any dot or dot-dot elements are present
- if (!tail_has_dots && (tail_elem == dot_p || tail_elem == dot_dot_p))
+ if (!tail_has_dots && (path_algorithms::compare_v4(tail_elem, dot_p) == 0 || path_algorithms::compare_v4(tail_elem, dot_dot_p) == 0))
tail_has_dots = true;
}
- if (head.empty())
- return p.lexically_normal();
-
head = detail::canonical(head, base, &local_ec);
if (BOOST_UNLIKELY(!!local_ec))
{
@@ -4531,11 +4597,11 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec)
if (BOOST_LIKELY(!tail.empty()))
{
- head /= tail;
+ path_algorithms::append_v4(head, tail);
// optimization: only normalize if tail had dot or dot-dot element
if (tail_has_dots)
- return head.lexically_normal();
+ return path_algorithms::lexically_normal_v4(head);
}
return head;
diff --git a/contrib/restricted/boost/filesystem/src/path.cpp b/contrib/restricted/boost/filesystem/src/path.cpp
index 27b32e57c5..1d9748cac7 100644
--- a/contrib/restricted/boost/filesystem/src/path.cpp
+++ b/contrib/restricted/boost/filesystem/src/path.cpp
@@ -1,7 +1,7 @@
// filesystem path.cpp ------------------------------------------------------------- //
// Copyright Beman Dawes 2008
-// Copyright Andrey Semashev 2021
+// Copyright Andrey Semashev 2021-2023
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -12,7 +12,7 @@
#include <boost/filesystem/config.hpp>
#include <boost/filesystem/path.hpp>
-#include <boost/filesystem/path_traits.hpp> // codecvt_error_category()
+#include <boost/filesystem/detail/path_traits.hpp> // codecvt_error_category()
#include <boost/scoped_array.hpp>
#include <boost/system/error_category.hpp> // for BOOST_SYSTEM_HAS_CONSTEXPR
#include <boost/assert.hpp>
@@ -60,7 +60,6 @@ namespace {
typedef path::value_type value_type;
typedef path::string_type string_type;
typedef string_type::size_type size_type;
-using boost::filesystem::path_detail::substring;
#ifdef BOOST_WINDOWS_API
@@ -151,110 +150,247 @@ inline void first_element(string_type const& src, size_type& element_pos, size_t
namespace boost {
namespace filesystem {
+namespace detail {
-BOOST_FILESYSTEM_DECL void path::append_v3(path const& p)
+// C++14 provides a mismatch algorithm with four iterator arguments(), but earlier
+// standard libraries didn't, so provide this needed functionality.
+inline std::pair< path::iterator, path::iterator > mismatch(path::iterator it1, path::iterator it1end, path::iterator it2, path::iterator it2end)
{
- if (!p.empty())
+ for (; it1 != it1end && it2 != it2end && path_algorithms::compare_v4(*it1, *it2) == 0;)
{
- if (BOOST_LIKELY(this != &p))
- {
- if (!detail::is_directory_separator(*p.m_pathname.begin()))
- append_separator_if_needed();
- m_pathname += p.m_pathname;
- }
- else
- {
- // self-append
- path rhs(p);
- append_v3(rhs);
- }
+ path_algorithms::increment_v4(it1);
+ path_algorithms::increment_v4(it2);
}
+ return std::make_pair(it1, it2);
}
-BOOST_FILESYSTEM_DECL void path::append_v3(const value_type* begin, const value_type* end)
+// normal --------------------------------------------------------------------------//
+
+BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v3(path const& p)
{
- if (begin != end)
+ const value_type* const pathname = p.m_pathname.c_str();
+ const size_type pathname_size = p.m_pathname.size();
+ size_type root_name_size = 0;
+ size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
+ path normal(pathname, pathname + root_name_size);
+
+#if defined(BOOST_WINDOWS_API)
+ for (size_type i = 0; i < root_name_size; ++i)
+ {
+ if (normal.m_pathname[i] == path::separator)
+ normal.m_pathname[i] = path::preferred_separator;
+ }
+#endif
+
+ size_type root_path_size = root_name_size;
+ if (root_dir_pos < pathname_size)
{
- if (BOOST_LIKELY(begin < m_pathname.data() || begin >= (m_pathname.data() + m_pathname.size())))
+ root_path_size = root_dir_pos + 1;
+ normal.m_pathname.push_back(path::preferred_separator);
+ }
+
+ size_type i = root_path_size;
+
+ // Skip redundant directory separators after the root directory
+ while (i < pathname_size && detail::is_directory_separator(pathname[i]))
+ ++i;
+
+ if (i < pathname_size)
+ {
+ bool last_element_was_dot = false;
+ while (true)
{
- if (!detail::is_directory_separator(*begin))
- append_separator_if_needed();
- m_pathname.append(begin, end);
+ {
+ const size_type start_pos = i;
+
+ // Find next separator
+ i += find_separator(pathname + i, pathname_size - i);
+
+ const size_type size = i - start_pos;
+
+ // Skip dot elements
+ if (size == 1u && pathname[start_pos] == path::dot)
+ {
+ last_element_was_dot = true;
+ goto skip_append;
+ }
+
+ last_element_was_dot = false;
+
+ // Process dot dot elements
+ if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size)
+ {
+ // Don't remove previous dot dot elements
+ const size_type normal_size = normal.m_pathname.size();
+ size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
+ size_type pos = normal_size - filename_size;
+ if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot)
+ {
+ if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
+ --pos;
+ normal.m_pathname.erase(normal.m_pathname.begin() + pos , normal.m_pathname.end());
+ goto skip_append;
+ }
+ }
+
+ // Append the element
+ path_algorithms::append_separator_if_needed(normal);
+ normal.m_pathname.append(pathname + start_pos, size);
+ }
+
+ skip_append:
+ if (i == pathname_size)
+ break;
+
+ // Skip directory separators, including duplicates
+ while (i < pathname_size && detail::is_directory_separator(pathname[i]))
+ ++i;
+
+ if (i == pathname_size)
+ {
+ // If a path ends with a separator, add a trailing dot element
+ goto append_trailing_dot;
+ }
}
- else
+
+ if (normal.empty() || last_element_was_dot)
{
- // overlapping source
- path rhs(begin, end);
- append_v3(rhs);
+ append_trailing_dot:
+ path_algorithms::append_separator_if_needed(normal);
+ normal.m_pathname.push_back(path::dot);
}
}
+
+ return normal;
}
-BOOST_FILESYSTEM_DECL void path::append_v4(path const& p)
+BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v4(path const& p)
{
- if (!p.empty())
- {
- if (BOOST_LIKELY(this != &p))
- {
- const size_type that_size = p.m_pathname.size();
- size_type that_root_name_size = 0;
- size_type that_root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), that_size, that_root_name_size);
+ const value_type* const pathname = p.m_pathname.c_str();
+ const size_type pathname_size = p.m_pathname.size();
+ size_type root_name_size = 0;
+ size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
+ path normal(pathname, pathname + root_name_size);
- // if (p.is_absolute())
- if
- (
-#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE)
- that_root_name_size > 0 &&
+#if defined(BOOST_WINDOWS_API)
+ for (size_type i = 0; i < root_name_size; ++i)
+ {
+ if (normal.m_pathname[i] == path::separator)
+ normal.m_pathname[i] = path::preferred_separator;
+ }
#endif
- that_root_dir_pos < that_size
- )
+
+ size_type root_path_size = root_name_size;
+ if (root_dir_pos < pathname_size)
+ {
+ root_path_size = root_dir_pos + 1;
+ normal.m_pathname.push_back(path::preferred_separator);
+ }
+
+ size_type i = root_path_size;
+
+ // Skip redundant directory separators after the root directory
+ while (i < pathname_size && detail::is_directory_separator(pathname[i]))
+ ++i;
+
+ if (i < pathname_size)
+ {
+ while (true)
+ {
+ bool last_element_was_dot = false;
{
- return_assign:
- assign(p);
- return;
- }
+ const size_type start_pos = i;
- size_type this_root_name_size = 0;
- find_root_directory_start(m_pathname.c_str(), m_pathname.size(), this_root_name_size);
+ // Find next separator
+ i += find_separator(pathname + i, pathname_size - i);
- if
- (
- that_root_name_size > 0 &&
- (that_root_name_size != this_root_name_size || std::memcmp(m_pathname.c_str(), p.m_pathname.c_str(), this_root_name_size * sizeof(value_type)) != 0)
- )
+ const size_type size = i - start_pos;
+
+ // Skip dot elements
+ if (size == 1u && pathname[start_pos] == path::dot)
+ {
+ last_element_was_dot = true;
+ goto skip_append;
+ }
+
+ // Process dot dot elements
+ if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size)
+ {
+ // Don't remove previous dot dot elements
+ const size_type normal_size = normal.m_pathname.size();
+ size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
+ size_type pos = normal_size - filename_size;
+ if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot)
+ {
+ if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
+ --pos;
+ normal.m_pathname.erase(normal.m_pathname.begin() + pos, normal.m_pathname.end());
+ goto skip_append;
+ }
+ }
+
+ // Append the element
+ path_algorithms::append_separator_if_needed(normal);
+ normal.m_pathname.append(pathname + start_pos, size);
+ }
+
+ skip_append:
+ if (i == pathname_size)
{
- goto return_assign;
+ // If a path ends with a trailing dot after a directory element, add a trailing separator
+ if (last_element_was_dot && !normal.empty() && !normal.filename_is_dot_dot())
+ path_algorithms::append_separator_if_needed(normal);
+
+ break;
}
- if (that_root_dir_pos < that_size)
+ // Skip directory separators, including duplicates
+ while (i < pathname_size && detail::is_directory_separator(pathname[i]))
+ ++i;
+
+ if (i == pathname_size)
{
- // Remove root directory (if any) and relative path to replace with those from p
- m_pathname.erase(m_pathname.begin() + this_root_name_size, m_pathname.end());
+ // If a path ends with a separator, add a trailing separator
+ if (!normal.empty() && !normal.filename_is_dot_dot())
+ path_algorithms::append_separator_if_needed(normal);
+ break;
}
+ }
- const value_type* const that_path = p.m_pathname.c_str() + that_root_name_size;
- if (!detail::is_directory_separator(*that_path))
- append_separator_if_needed();
- m_pathname.append(that_path, that_size - that_root_name_size);
+ // If the original path was not empty and normalized ended up being empty, make it a dot
+ if (normal.empty())
+ normal.m_pathname.push_back(path::dot);
+ }
+
+ return normal;
+}
+
+// append --------------------------------------------------------------------------//
+
+BOOST_FILESYSTEM_DECL void path_algorithms::append_v3(path& p, const value_type* begin, const value_type* end)
+{
+ if (begin != end)
+ {
+ if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size())))
+ {
+ if (!detail::is_directory_separator(*begin))
+ path_algorithms::append_separator_if_needed(p);
+ p.m_pathname.append(begin, end);
}
else
{
- // self-append
- path rhs(p);
- append_v4(rhs);
+ // overlapping source
+ string_type rhs(begin, end);
+ path_algorithms::append_v3(p, rhs.data(), rhs.data() + rhs.size());
}
}
- else if (has_filename_v4())
- {
- m_pathname.push_back(preferred_separator);
- }
}
-BOOST_FILESYSTEM_DECL void path::append_v4(const value_type* begin, const value_type* end)
+BOOST_FILESYSTEM_DECL void path_algorithms::append_v4(path& p, const value_type* begin, const value_type* end)
{
if (begin != end)
{
- if (BOOST_LIKELY(begin < m_pathname.data() || begin >= (m_pathname.data() + m_pathname.size())))
+ if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size())))
{
const size_type that_size = end - begin;
size_type that_root_name_size = 0;
@@ -270,17 +406,17 @@ BOOST_FILESYSTEM_DECL void path::append_v4(const value_type* begin, const value_
)
{
return_assign:
- assign(begin, end);
+ p.assign(begin, end);
return;
}
size_type this_root_name_size = 0;
- find_root_directory_start(m_pathname.c_str(), m_pathname.size(), this_root_name_size);
+ find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), this_root_name_size);
if
(
that_root_name_size > 0 &&
- (that_root_name_size != this_root_name_size || std::memcmp(m_pathname.c_str(), begin, this_root_name_size * sizeof(value_type)) != 0)
+ (that_root_name_size != this_root_name_size || std::memcmp(p.m_pathname.c_str(), begin, this_root_name_size * sizeof(value_type)) != 0)
)
{
goto return_assign;
@@ -289,197 +425,219 @@ BOOST_FILESYSTEM_DECL void path::append_v4(const value_type* begin, const value_
if (that_root_dir_pos < that_size)
{
// Remove root directory (if any) and relative path to replace with those from p
- m_pathname.erase(m_pathname.begin() + this_root_name_size, m_pathname.end());
+ p.m_pathname.erase(p.m_pathname.begin() + this_root_name_size, p.m_pathname.end());
}
const value_type* const that_path = begin + that_root_name_size;
if (!detail::is_directory_separator(*that_path))
- append_separator_if_needed();
- m_pathname.append(that_path, end);
+ path_algorithms::append_separator_if_needed(p);
+ p.m_pathname.append(that_path, end);
}
else
{
// overlapping source
- path rhs(begin, end);
- append_v4(rhs);
+ string_type rhs(begin, end);
+ path_algorithms::append_v4(p, rhs.data(), rhs.data() + rhs.size());
}
}
- else if (has_filename_v4())
+ else if (path_algorithms::has_filename_v4(p))
{
- m_pathname.push_back(preferred_separator);
+ p.m_pathname.push_back(path::preferred_separator);
}
}
-#ifdef BOOST_WINDOWS_API
+// compare -------------------------------------------------------------------------//
-BOOST_FILESYSTEM_DECL path path::generic_path() const
+BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v3
+(
+ path_detail::path_iterator first1, path_detail::path_iterator const& last1,
+ path_detail::path_iterator first2, path_detail::path_iterator const& last2
+)
{
- path tmp(*this);
- std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
- return tmp;
+ for (; first1 != last1 && first2 != last2;)
+ {
+ if (first1->native() < first2->native())
+ return -1;
+ if (first2->native() < first1->native())
+ return 1;
+ BOOST_ASSERT(first2->native() == first1->native());
+ path_algorithms::increment_v3(first1);
+ path_algorithms::increment_v3(first2);
+ }
+ if (first1 == last1 && first2 == last2)
+ return 0;
+ return first1 == last1 ? -1 : 1;
}
-#endif // BOOST_WINDOWS_API
+BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v4
+(
+ path_detail::path_iterator first1, path_detail::path_iterator const& last1,
+ path_detail::path_iterator first2, path_detail::path_iterator const& last2
+)
+{
+ for (; first1 != last1 && first2 != last2;)
+ {
+ if (first1->native() < first2->native())
+ return -1;
+ if (first2->native() < first1->native())
+ return 1;
+ BOOST_ASSERT(first2->native() == first1->native());
+ path_algorithms::increment_v4(first1);
+ path_algorithms::increment_v4(first2);
+ }
+ if (first1 == last1 && first2 == last2)
+ return 0;
+ return first1 == last1 ? -1 : 1;
+}
-BOOST_FILESYSTEM_DECL int path::compare_v3(path const& p) const BOOST_NOEXCEPT
+BOOST_FILESYSTEM_DECL int path_algorithms::compare_v3(path const& left, path const& right)
{
- return detail::lex_compare_v3(begin(), end(), p.begin(), p.end());
+ return path_algorithms::lex_compare_v3(left.begin(), left.end(), right.begin(), right.end());
}
-BOOST_FILESYSTEM_DECL int path::compare_v4(path const& p) const BOOST_NOEXCEPT
+BOOST_FILESYSTEM_DECL int path_algorithms::compare_v4(path const& left, path const& right)
{
- return detail::lex_compare_v4(begin(), end(), p.begin(), p.end());
+ return path_algorithms::lex_compare_v4(left.begin(), left.end(), right.begin(), right.end());
}
-// append_separator_if_needed ----------------------------------------------------//
+// append_separator_if_needed ------------------------------------------------------//
-BOOST_FILESYSTEM_DECL path::string_type::size_type path::append_separator_if_needed()
+BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::append_separator_if_needed(path& p)
{
- if (!m_pathname.empty() &&
+ if (!p.m_pathname.empty() &&
#ifdef BOOST_WINDOWS_API
- *(m_pathname.end() - 1) != colon &&
+ *(p.m_pathname.end() - 1) != colon &&
#endif
- !detail::is_directory_separator(*(m_pathname.end() - 1)))
+ !detail::is_directory_separator(*(p.m_pathname.end() - 1)))
{
- string_type::size_type tmp(m_pathname.size());
- m_pathname += preferred_separator;
+ string_type::size_type tmp(p.m_pathname.size());
+ p.m_pathname.push_back(path::preferred_separator);
return tmp;
}
return 0;
}
-// erase_redundant_separator -----------------------------------------------------//
+// erase_redundant_separator -------------------------------------------------------//
-BOOST_FILESYSTEM_DECL void path::erase_redundant_separator(string_type::size_type sep_pos)
+BOOST_FILESYSTEM_DECL void path_algorithms::erase_redundant_separator(path& p, string_type::size_type sep_pos)
{
- if (sep_pos // a separator was added
- && sep_pos < m_pathname.size() // and something was appended
- && (m_pathname[sep_pos + 1] == separator // and it was also separator
+ if (sep_pos // a separator was added
+ && sep_pos < p.m_pathname.size() // and something was appended
+ && (p.m_pathname[sep_pos + 1] == path::separator // and it was also separator
#ifdef BOOST_WINDOWS_API
- || m_pathname[sep_pos + 1] == preferred_separator // or preferred_separator
+ || p.m_pathname[sep_pos + 1] == path::preferred_separator // or preferred_separator
#endif
))
{
- m_pathname.erase(m_pathname.begin() + sep_pos); // erase the added separator
+ p.m_pathname.erase(p.m_pathname.begin() + sep_pos); // erase the added separator
}
}
// modifiers -----------------------------------------------------------------------//
-#ifdef BOOST_WINDOWS_API
-BOOST_FILESYSTEM_DECL path& path::make_preferred()
+BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v3(path& p)
{
- std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\');
- return *this;
+ p.remove_filename_and_trailing_separators();
}
-#endif
-BOOST_FILESYSTEM_DECL path& path::remove_filename()
+BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v4(path& p)
{
- size_type end_pos = find_parent_path_size();
- m_pathname.erase(m_pathname.begin() + end_pos, m_pathname.end());
- return *this;
+ size_type filename_size = path_algorithms::find_filename_v4_size(p);
+ p.m_pathname.erase(p.m_pathname.begin() + (p.m_pathname.size() - filename_size), p.m_pathname.end());
}
-BOOST_FILESYSTEM_DECL path& path::remove_trailing_separator()
-{
- if (!m_pathname.empty() && detail::is_directory_separator(m_pathname[m_pathname.size() - 1]))
- m_pathname.erase(m_pathname.end() - 1);
- return *this;
-}
-
-BOOST_FILESYSTEM_DECL void path::replace_extension_v3(path const& new_extension)
+BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v3(path& p, path const& new_extension)
{
// erase existing extension, including the dot, if any
- size_type ext_pos = m_pathname.size() - extension_v3().m_pathname.size();
- m_pathname.erase(m_pathname.begin() + ext_pos, m_pathname.end());
+ size_type ext_pos = p.m_pathname.size() - path_algorithms::extension_v3(p).m_pathname.size();
+ p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end());
if (!new_extension.empty())
{
// append new_extension, adding the dot if necessary
- if (new_extension.m_pathname[0] != dot)
- m_pathname.push_back(dot);
- m_pathname.append(new_extension.m_pathname);
+ if (new_extension.m_pathname[0] != path::dot)
+ p.m_pathname.push_back(path::dot);
+ p.m_pathname.append(new_extension.m_pathname);
}
}
-BOOST_FILESYSTEM_DECL void path::replace_extension_v4(path const& new_extension)
+BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v4(path& p, path const& new_extension)
{
// erase existing extension, including the dot, if any
- size_type ext_pos = m_pathname.size() - find_extension_v4_size();
- m_pathname.erase(m_pathname.begin() + ext_pos, m_pathname.end());
+ size_type ext_pos = p.m_pathname.size() - path_algorithms::find_extension_v4_size(p);
+ p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end());
if (!new_extension.empty())
{
// append new_extension, adding the dot if necessary
- if (new_extension.m_pathname[0] != dot)
- m_pathname.push_back(dot);
- m_pathname.append(new_extension.m_pathname);
+ if (new_extension.m_pathname[0] != path::dot)
+ p.m_pathname.push_back(path::dot);
+ p.m_pathname.append(new_extension.m_pathname);
}
}
// decomposition -------------------------------------------------------------------//
-BOOST_FILESYSTEM_DECL size_type path::find_root_name_size() const
+BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_name_size(path const& p)
{
size_type root_name_size = 0;
- find_root_directory_start(m_pathname.c_str(), m_pathname.size(), root_name_size);
+ find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
return root_name_size;
}
-BOOST_FILESYSTEM_DECL size_type path::find_root_path_size() const
+BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_path_size(path const& p)
{
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_pathname.c_str(), m_pathname.size(), root_name_size);
+ size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
size_type size = root_name_size;
- if (root_dir_pos < m_pathname.size())
+ if (root_dir_pos < p.m_pathname.size())
size = root_dir_pos + 1;
return size;
}
-BOOST_FILESYSTEM_DECL substring path::find_root_directory() const
+BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_root_directory(path const& p)
{
substring root_dir;
size_type root_name_size = 0;
- root_dir.pos = find_root_directory_start(m_pathname.c_str(), m_pathname.size(), root_name_size);
- root_dir.size = static_cast< std::size_t >(root_dir.pos < m_pathname.size());
+ root_dir.pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
+ root_dir.size = static_cast< std::size_t >(root_dir.pos < p.m_pathname.size());
return root_dir;
}
-BOOST_FILESYSTEM_DECL substring path::find_relative_path() const
+BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_relative_path(path const& p)
{
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_pathname.c_str(), m_pathname.size(), root_name_size);
+ size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
// Skip root name, root directory and any duplicate separators
size_type size = root_name_size;
- if (root_dir_pos < m_pathname.size())
+ if (root_dir_pos < p.m_pathname.size())
{
size = root_dir_pos + 1;
- for (size_type n = m_pathname.size(); size < n; ++size)
+ for (size_type n = p.m_pathname.size(); size < n; ++size)
{
- if (!detail::is_directory_separator(m_pathname[size]))
+ if (!detail::is_directory_separator(p.m_pathname[size]))
break;
}
}
substring rel_path;
rel_path.pos = size;
- rel_path.size = m_pathname.size() - size;
+ rel_path.size = p.m_pathname.size() - size;
return rel_path;
}
-BOOST_FILESYSTEM_DECL string_type::size_type path::find_parent_path_size() const
+BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_parent_path_size(path const& p)
{
- const size_type size = m_pathname.size();
+ const size_type size = p.m_pathname.size();
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
- size_type filename_size = find_filename_size(m_pathname, root_name_size, size);
+ size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size);
size_type end_pos = size - filename_size;
while (true)
{
@@ -493,7 +651,7 @@ BOOST_FILESYSTEM_DECL string_type::size_type path::find_parent_path_size() const
--end_pos;
- if (!detail::is_directory_separator(m_pathname[end_pos]))
+ if (!detail::is_directory_separator(p.m_pathname[end_pos]))
{
++end_pos;
break;
@@ -510,13 +668,13 @@ BOOST_FILESYSTEM_DECL string_type::size_type path::find_parent_path_size() const
return end_pos;
}
-BOOST_FILESYSTEM_DECL path path::filename_v3() const
+BOOST_FILESYSTEM_DECL path path_algorithms::filename_v3(path const& p)
{
- const size_type size = m_pathname.size();
+ const size_type size = p.m_pathname.size();
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
size_type filename_size, pos;
- if (root_dir_pos < size && detail::is_directory_separator(m_pathname[size - 1]) && is_root_separator(m_pathname, root_dir_pos, size - 1))
+ if (root_dir_pos < size && detail::is_directory_separator(p.m_pathname[size - 1]) && is_root_separator(p.m_pathname, root_dir_pos, size - 1))
{
// Return root directory
pos = root_dir_pos;
@@ -530,77 +688,77 @@ BOOST_FILESYSTEM_DECL path path::filename_v3() const
}
else
{
- filename_size = find_filename_size(m_pathname, root_name_size, size);
+ filename_size = find_filename_size(p.m_pathname, root_name_size, size);
pos = size - filename_size;
- if (filename_size == 0u && pos > root_name_size && detail::is_directory_separator(m_pathname[pos - 1]) && !is_root_separator(m_pathname, root_dir_pos, pos - 1))
+ if (filename_size == 0u && pos > root_name_size && detail::is_directory_separator(p.m_pathname[pos - 1]) && !is_root_separator(p.m_pathname, root_dir_pos, pos - 1))
return detail::dot_path();
}
- const value_type* p = m_pathname.c_str() + pos;
- return path(p, p + filename_size);
+ const value_type* ptr = p.m_pathname.c_str() + pos;
+ return path(ptr, ptr + filename_size);
}
-BOOST_FILESYSTEM_DECL string_type::size_type path::find_filename_v4_size() const
+BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_filename_v4_size(path const& p)
{
- const size_type size = m_pathname.size();
+ const size_type size = p.m_pathname.size();
size_type root_name_size = 0;
- find_root_directory_start(m_pathname.c_str(), size, root_name_size);
- return find_filename_size(m_pathname, root_name_size, size);
+ find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
+ return find_filename_size(p.m_pathname, root_name_size, size);
}
-BOOST_FILESYSTEM_DECL path path::stem_v3() const
+BOOST_FILESYSTEM_DECL path path_algorithms::stem_v3(path const& p)
{
- path name(filename_v3());
- if (name != detail::dot_path() && name != detail::dot_dot_path())
+ path name(path_algorithms::filename_v3(p));
+ if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0)
{
- size_type pos = name.m_pathname.rfind(dot);
+ size_type pos = name.m_pathname.rfind(path::dot);
if (pos != string_type::npos)
name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end());
}
return name;
}
-BOOST_FILESYSTEM_DECL path path::stem_v4() const
+BOOST_FILESYSTEM_DECL path path_algorithms::stem_v4(path const& p)
{
- path name(filename_v4());
- if (name != detail::dot_path() && name != detail::dot_dot_path())
+ path name(path_algorithms::filename_v4(p));
+ if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0)
{
- size_type pos = name.m_pathname.rfind(dot);
+ size_type pos = name.m_pathname.rfind(path::dot);
if (pos != 0 && pos != string_type::npos)
name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end());
}
return name;
}
-BOOST_FILESYSTEM_DECL path path::extension_v3() const
+BOOST_FILESYSTEM_DECL path path_algorithms::extension_v3(path const& p)
{
- path name(filename_v3());
- if (name == detail::dot_path() || name == detail::dot_dot_path())
+ path name(path_algorithms::filename_v3(p));
+ if (path_algorithms::compare_v4(name, detail::dot_path()) == 0 || path_algorithms::compare_v4(name, detail::dot_dot_path()) == 0)
return path();
- size_type pos(name.m_pathname.rfind(dot));
+ size_type pos(name.m_pathname.rfind(path::dot));
return pos == string_type::npos ? path() : path(name.m_pathname.c_str() + pos);
}
-BOOST_FILESYSTEM_DECL string_type::size_type path::find_extension_v4_size() const
+BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_extension_v4_size(path const& p)
{
- const size_type size = m_pathname.size();
+ const size_type size = p.m_pathname.size();
size_type root_name_size = 0;
- find_root_directory_start(m_pathname.c_str(), size, root_name_size);
- size_type filename_size = find_filename_size(m_pathname, root_name_size, size);
+ find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
+ size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size);
size_type filename_pos = size - filename_size;
if
(
filename_size > 0u &&
// Check for "." and ".." filenames
- !(m_pathname[filename_pos] == dot &&
- (filename_size == 1u || (filename_size == 2u && m_pathname[filename_pos + 1u] == dot)))
+ !(p.m_pathname[filename_pos] == path::dot &&
+ (filename_size == 1u || (filename_size == 2u && p.m_pathname[filename_pos + 1u] == path::dot)))
)
{
size_type ext_pos = size;
while (ext_pos > filename_pos)
{
--ext_pos;
- if (m_pathname[ext_pos] == dot)
+ if (p.m_pathname[ext_pos] == path::dot)
break;
}
@@ -611,21 +769,30 @@ BOOST_FILESYSTEM_DECL string_type::size_type path::find_extension_v4_size() cons
return 0u;
}
-// lexical operations --------------------------------------------------------------//
+} // namespace detail
-namespace detail {
-// C++14 provides a mismatch algorithm with four iterator arguments(), but earlier
-// standard libraries didn't, so provide this needed functionality.
-inline std::pair< path::iterator, path::iterator > mismatch(path::iterator it1, path::iterator it1end, path::iterator it2, path::iterator it2end)
+BOOST_FILESYSTEM_DECL path& path::remove_filename_and_trailing_separators()
{
- for (; it1 != it1end && it2 != it2end && *it1 == *it2;)
- {
- ++it1;
- ++it2;
- }
- return std::make_pair(it1, it2);
+ size_type end_pos = detail::path_algorithms::find_parent_path_size(*this);
+ m_pathname.erase(m_pathname.begin() + end_pos, m_pathname.end());
+ return *this;
}
-} // namespace detail
+
+BOOST_FILESYSTEM_DECL path& path::remove_trailing_separator()
+{
+ if (!m_pathname.empty() && detail::is_directory_separator(m_pathname[m_pathname.size() - 1]))
+ m_pathname.erase(m_pathname.end() - 1);
+ return *this;
+}
+
+BOOST_FILESYSTEM_DECL path& path::replace_filename(path const& replacement)
+{
+ detail::path_algorithms::remove_filename_v4(*this);
+ detail::path_algorithms::append_v4(*this, replacement.m_pathname.data(), replacement.m_pathname.data() + replacement.m_pathname.size());
+ return *this;
+}
+
+// lexical operations --------------------------------------------------------------//
BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const
{
@@ -637,12 +804,12 @@ BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const
return detail::dot_path();
std::ptrdiff_t n = 0;
- for (; mm.second != base_e; ++mm.second)
+ for (; mm.second != base_e; detail::path_algorithms::increment_v4(mm.second))
{
path const& p = *mm.second;
- if (p == detail::dot_dot_path())
+ if (detail::path_algorithms::compare_v4(p, detail::dot_dot_path()) == 0)
--n;
- else if (!p.empty() && p != detail::dot_path())
+ else if (!p.empty() && detail::path_algorithms::compare_v4(p, detail::dot_path()) != 0)
++n;
}
if (n < 0)
@@ -652,213 +819,29 @@ BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const
path tmp;
for (; n > 0; --n)
- tmp /= detail::dot_dot_path();
- for (; mm.first != e; ++mm.first)
- tmp /= *mm.first;
+ detail::path_algorithms::append_v4(tmp, detail::dot_dot_path());
+ for (; mm.first != e; detail::path_algorithms::increment_v4(mm.first))
+ detail::path_algorithms::append_v4(tmp, *mm.first);
return tmp;
}
-// normal --------------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path path::lexically_normal_v3() const
-{
- const value_type* const pathname = m_pathname.c_str();
- const size_type pathname_size = m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
- path normal(pathname, pathname + root_name_size);
-
#if defined(BOOST_WINDOWS_API)
- for (size_type i = 0; i < root_name_size; ++i)
- {
- if (normal.m_pathname[i] == path::separator)
- normal.m_pathname[i] = path::preferred_separator;
- }
-#endif
-
- size_type root_path_size = root_name_size;
- if (root_dir_pos < pathname_size)
- {
- root_path_size = root_dir_pos + 1;
- normal.m_pathname.push_back(preferred_separator);
- }
-
- size_type i = root_path_size;
-
- // Skip redundant directory separators after the root directory
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i < pathname_size)
- {
- bool last_element_was_dot = false;
- while (true)
- {
- {
- const size_type start_pos = i;
-
- // Find next separator
- i += find_separator(pathname + i, pathname_size - i);
-
- const size_type size = i - start_pos;
-
- // Skip dot elements
- if (size == 1u && pathname[start_pos] == dot)
- {
- last_element_was_dot = true;
- goto skip_append;
- }
-
- last_element_was_dot = false;
-
- // Process dot dot elements
- if (size == 2u && pathname[start_pos] == dot && pathname[start_pos + 1] == dot && normal.m_pathname.size() > root_path_size)
- {
- // Don't remove previous dot dot elements
- const size_type normal_size = normal.m_pathname.size();
- size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
- size_type pos = normal_size - filename_size;
- if (filename_size != 2u || normal.m_pathname[pos] != dot || normal.m_pathname[pos + 1] != dot)
- {
- if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
- --pos;
- normal.m_pathname.erase(normal.m_pathname.begin() + pos , normal.m_pathname.end());
- goto skip_append;
- }
- }
-
- // Append the element
- normal.append_separator_if_needed();
- normal.m_pathname.append(pathname + start_pos, size);
- }
-
- skip_append:
- if (i == pathname_size)
- break;
-
- // Skip directory separators, including duplicates
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
- if (i == pathname_size)
- {
- // If a path ends with a separator, add a trailing dot element
- goto append_trailing_dot;
- }
- }
-
- if (normal.empty() || last_element_was_dot)
- {
- append_trailing_dot:
- normal.append_separator_if_needed();
- normal.m_pathname.push_back(dot);
- }
- }
-
- return normal;
+BOOST_FILESYSTEM_DECL path path::generic_path() const
+{
+ path tmp(*this);
+ std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
+ return tmp;
}
-BOOST_FILESYSTEM_DECL path path::lexically_normal_v4() const
+BOOST_FILESYSTEM_DECL path& path::make_preferred()
{
- const value_type* const pathname = m_pathname.c_str();
- const size_type pathname_size = m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
- path normal(pathname, pathname + root_name_size);
-
-#if defined(BOOST_WINDOWS_API)
- for (size_type i = 0; i < root_name_size; ++i)
- {
- if (normal.m_pathname[i] == path::separator)
- normal.m_pathname[i] = path::preferred_separator;
- }
-#endif
-
- size_type root_path_size = root_name_size;
- if (root_dir_pos < pathname_size)
- {
- root_path_size = root_dir_pos + 1;
- normal.m_pathname.push_back(preferred_separator);
- }
-
- size_type i = root_path_size;
-
- // Skip redundant directory separators after the root directory
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i < pathname_size)
- {
- while (true)
- {
- bool last_element_was_dot = false;
- {
- const size_type start_pos = i;
-
- // Find next separator
- i += find_separator(pathname + i, pathname_size - i);
-
- const size_type size = i - start_pos;
-
- // Skip dot elements
- if (size == 1u && pathname[start_pos] == dot)
- {
- last_element_was_dot = true;
- goto skip_append;
- }
-
- // Process dot dot elements
- if (size == 2u && pathname[start_pos] == dot && pathname[start_pos + 1] == dot && normal.m_pathname.size() > root_path_size)
- {
- // Don't remove previous dot dot elements
- const size_type normal_size = normal.m_pathname.size();
- size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
- size_type pos = normal_size - filename_size;
- if (filename_size != 2u || normal.m_pathname[pos] != dot || normal.m_pathname[pos + 1] != dot)
- {
- if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
- --pos;
- normal.m_pathname.erase(normal.m_pathname.begin() + pos, normal.m_pathname.end());
- goto skip_append;
- }
- }
-
- // Append the element
- normal.append_separator_if_needed();
- normal.m_pathname.append(pathname + start_pos, size);
- }
-
- skip_append:
- if (i == pathname_size)
- {
- // If a path ends with a trailing dot after a directory element, add a trailing separator
- if (last_element_was_dot && !normal.empty() && !normal.filename_is_dot_dot())
- normal.append_separator_if_needed();
-
- break;
- }
-
- // Skip directory separators, including duplicates
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i == pathname_size)
- {
- // If a path ends with a separator, add a trailing separator
- if (!normal.empty() && !normal.filename_is_dot_dot())
- normal.append_separator_if_needed();
- break;
- }
- }
-
- // If the original path was not empty and normalized ended up being empty, make it a dot
- if (normal.empty())
- normal.m_pathname.push_back(dot);
- }
-
- return normal;
+ std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\');
+ return *this;
}
+#endif // defined(BOOST_WINDOWS_API)
+
} // namespace filesystem
} // namespace boost
@@ -1001,7 +984,13 @@ find_next_separator:
return pos;
}
-// first_element --------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
+// //
+// class path::iterator implementation //
+// //
+//--------------------------------------------------------------------------------------//
+
+// first_element ----------------------------------------------------------------------//
// sets pos and len of first element, excluding extra separators
// if src.empty(), sets pos,len, to 0,0.
@@ -1043,225 +1032,153 @@ namespace boost {
namespace filesystem {
namespace detail {
-BOOST_FILESYSTEM_DECL
-int lex_compare_v3(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2)
-{
- for (; first1 != last1 && first2 != last2;)
- {
- if (first1->native() < first2->native())
- return -1;
- if (first2->native() < first1->native())
- return 1;
- BOOST_ASSERT(first2->native() == first1->native());
- first1.increment_v3();
- first2.increment_v3();
- }
- if (first1 == last1 && first2 == last2)
- return 0;
- return first1 == last1 ? -1 : 1;
-}
-
-BOOST_FILESYSTEM_DECL
-int lex_compare_v4(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2)
-{
- for (; first1 != last1 && first2 != last2;)
- {
- if (first1->native() < first2->native())
- return -1;
- if (first2->native() < first1->native())
- return 1;
- BOOST_ASSERT(first2->native() == first1->native());
- ++first1;
- ++first2;
- }
- if (first1 == last1 && first2 == last2)
- return 0;
- return first1 == last1 ? -1 : 1;
-}
-
-} // namespace detail
-
-//--------------------------------------------------------------------------------------//
-// //
-// class path::iterator implementation //
-// //
-//--------------------------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path::iterator path::begin() const
+BOOST_FILESYSTEM_DECL void path_algorithms::increment_v3(path_detail::path_iterator& it)
{
- iterator itr;
- itr.m_path_ptr = this;
-
- size_type element_size;
- first_element(m_pathname, itr.m_pos, element_size);
-
- if (element_size > 0)
- {
- itr.m_element = m_pathname.substr(itr.m_pos, element_size);
-#ifdef BOOST_WINDOWS_API
- if (itr.m_element.m_pathname.size() == 1u && itr.m_element.m_pathname[0] == preferred_separator)
- itr.m_element.m_pathname[0] = separator;
-#endif
- }
-
- return itr;
-}
-
-BOOST_FILESYSTEM_DECL path::iterator path::end() const
-{
- iterator itr;
- itr.m_path_ptr = this;
- itr.m_pos = m_pathname.size();
- return itr;
-}
-
-BOOST_FILESYSTEM_DECL void path::iterator::increment_v3()
-{
- const size_type size = m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(m_pos < size, "path::iterator increment past end()");
+ const size_type size = it.m_path_ptr->m_pathname.size();
+ BOOST_ASSERT_MSG(it.m_pos < size, "path::iterator increment past end()");
// increment to position past current element; if current element is implicit dot,
// this will cause m_pos to represent the end iterator
- m_pos += m_element.m_pathname.size();
+ it.m_pos += it.m_element.m_pathname.size();
// if the end is reached, we are done
- if (m_pos >= size)
+ if (it.m_pos >= size)
{
- BOOST_ASSERT_MSG(m_pos == size, "path::iterator increment after the referenced path was modified");
- m_element.clear(); // aids debugging
+ BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified");
+ it.m_element.clear(); // aids debugging
return;
}
// process separator (Windows drive spec is only case not a separator)
- if (detail::is_directory_separator(m_path_ptr->m_pathname[m_pos]))
+ if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
{
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_path_ptr->m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
// detect root directory and set iterator value to the separator if it is
- if (m_pos == root_dir_pos && m_element.m_pathname.size() == root_name_size)
+ if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size)
{
- m_element.m_pathname = separator; // generic format; see docs
+ it.m_element.m_pathname = path::separator; // generic format; see docs
return;
}
// skip separators until m_pos points to the start of the next element
- while (m_pos != size && detail::is_directory_separator(m_path_ptr->m_pathname[m_pos]))
+ while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
{
- ++m_pos;
+ ++it.m_pos;
}
// detect trailing separator, and treat it as ".", per POSIX spec
- if (m_pos == size &&
- !is_root_separator(m_path_ptr->m_pathname, root_dir_pos, m_pos - 1))
+ if (it.m_pos == size &&
+ !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
{
- --m_pos;
- m_element = detail::dot_path();
+ --it.m_pos;
+ it.m_element = detail::dot_path();
return;
}
}
// get m_element
- size_type end_pos = m_path_ptr->m_pathname.find_first_of(separators, m_pos);
+ size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos);
if (end_pos == string_type::npos)
end_pos = size;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p + m_pos, p + end_pos);
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
}
-BOOST_FILESYSTEM_DECL void path::iterator::increment_v4()
+BOOST_FILESYSTEM_DECL void path_algorithms::increment_v4(path_detail::path_iterator& it)
{
- const size_type size = m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(m_pos <= size, "path::iterator increment past end()");
+ const size_type size = it.m_path_ptr->m_pathname.size();
+ BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator increment past end()");
- if (m_element.m_pathname.empty() && (m_pos + 1) == size && detail::is_directory_separator(m_path_ptr->m_pathname[m_pos]))
+ if (it.m_element.m_pathname.empty() && (it.m_pos + 1) == size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
{
// The iterator was pointing to the last empty element of the path; set to end.
- m_pos = size;
+ it.m_pos = size;
return;
}
// increment to position past current element; if current element is implicit dot,
// this will cause m_pos to represent the end iterator
- m_pos += m_element.m_pathname.size();
+ it.m_pos += it.m_element.m_pathname.size();
// if the end is reached, we are done
- if (m_pos >= size)
+ if (it.m_pos >= size)
{
- BOOST_ASSERT_MSG(m_pos == size, "path::iterator increment after the referenced path was modified");
- m_element.clear(); // aids debugging
+ BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified");
+ it.m_element.clear(); // aids debugging
return;
}
// process separator (Windows drive spec is only case not a separator)
- if (detail::is_directory_separator(m_path_ptr->m_pathname[m_pos]))
+ if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
{
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_path_ptr->m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
// detect root directory and set iterator value to the separator if it is
- if (m_pos == root_dir_pos && m_element.m_pathname.size() == root_name_size)
+ if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size)
{
- m_element.m_pathname = separator; // generic format; see docs
+ it.m_element.m_pathname = path::separator; // generic format; see docs
return;
}
// skip separators until m_pos points to the start of the next element
- while (m_pos != size && detail::is_directory_separator(m_path_ptr->m_pathname[m_pos]))
+ while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
{
- ++m_pos;
+ ++it.m_pos;
}
// detect trailing separator
- if (m_pos == size &&
- !is_root_separator(m_path_ptr->m_pathname, root_dir_pos, m_pos - 1))
+ if (it.m_pos == size &&
+ !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
{
- --m_pos;
- m_element.m_pathname.clear();
+ --it.m_pos;
+ it.m_element.m_pathname.clear();
return;
}
}
// get m_element
- size_type end_pos = m_path_ptr->m_pathname.find_first_of(separators, m_pos);
+ size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos);
if (end_pos == string_type::npos)
end_pos = size;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p + m_pos, p + end_pos);
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
}
-BOOST_FILESYSTEM_DECL void path::iterator::decrement_v3()
+BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v3(path_detail::path_iterator& it)
{
- const size_type size = m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(m_pos > 0, "path::iterator decrement past begin()");
- BOOST_ASSERT_MSG(m_pos <= size, "path::iterator decrement after the referenced path was modified");
+ const size_type size = it.m_path_ptr->m_pathname.size();
+ BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()");
+ BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified");
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_path_ptr->m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
- if (root_dir_pos < size && m_pos == root_dir_pos)
+ if (root_dir_pos < size && it.m_pos == root_dir_pos)
{
// Was pointing at root directory, decrement to root name
set_to_root_name:
- m_pos = 0u;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p, p + root_name_size);
+ it.m_pos = 0u;
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p, p + root_name_size);
return;
}
// if at end and there was a trailing non-root '/', return "."
- if (m_pos == size &&
+ if (it.m_pos == size &&
size > 1 &&
- detail::is_directory_separator(m_path_ptr->m_pathname[m_pos - 1]) &&
- !is_root_separator(m_path_ptr->m_pathname, root_dir_pos, m_pos - 1))
+ detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) &&
+ !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
{
- --m_pos;
- m_element = detail::dot_path();
+ --it.m_pos;
+ it.m_element = detail::dot_path();
return;
}
// skip separators unless root directory
- size_type end_pos = m_pos;
+ size_type end_pos = it.m_pos;
while (end_pos > root_name_size)
{
--end_pos;
@@ -1269,12 +1186,12 @@ BOOST_FILESYSTEM_DECL void path::iterator::decrement_v3()
if (end_pos == root_dir_pos)
{
// Decremented to the root directory
- m_pos = end_pos;
- m_element.m_pathname = separator; // generic format; see docs
+ it.m_pos = end_pos;
+ it.m_element.m_pathname = path::separator; // generic format; see docs
return;
}
- if (!detail::is_directory_separator(m_path_ptr->m_pathname[end_pos]))
+ if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos]))
{
++end_pos;
break;
@@ -1284,44 +1201,44 @@ BOOST_FILESYSTEM_DECL void path::iterator::decrement_v3()
if (end_pos <= root_name_size)
goto set_to_root_name;
- size_type filename_size = find_filename_size(m_path_ptr->m_pathname, root_name_size, end_pos);
- m_pos = end_pos - filename_size;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p + m_pos, p + end_pos);
+ size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos);
+ it.m_pos = end_pos - filename_size;
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
}
-BOOST_FILESYSTEM_DECL void path::iterator::decrement_v4()
+BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v4(path_detail::path_iterator& it)
{
- const size_type size = m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(m_pos > 0, "path::iterator decrement past begin()");
- BOOST_ASSERT_MSG(m_pos <= size, "path::iterator decrement after the referenced path was modified");
+ const size_type size = it.m_path_ptr->m_pathname.size();
+ BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()");
+ BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified");
size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(m_path_ptr->m_pathname.c_str(), size, root_name_size);
+ size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
- if (root_dir_pos < size && m_pos == root_dir_pos)
+ if (root_dir_pos < size && it.m_pos == root_dir_pos)
{
// Was pointing at root directory, decrement to root name
set_to_root_name:
- m_pos = 0u;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p, p + root_name_size);
+ it.m_pos = 0u;
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p, p + root_name_size);
return;
}
// if at end and there was a trailing '/', return ""
- if (m_pos == size &&
+ if (it.m_pos == size &&
size > 1 &&
- detail::is_directory_separator(m_path_ptr->m_pathname[m_pos - 1]) &&
- !is_root_separator(m_path_ptr->m_pathname, root_dir_pos, m_pos - 1))
+ detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) &&
+ !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
{
- --m_pos;
- m_element.m_pathname.clear();
+ --it.m_pos;
+ it.m_element.m_pathname.clear();
return;
}
// skip separators unless root directory
- size_type end_pos = m_pos;
+ size_type end_pos = it.m_pos;
while (end_pos > root_name_size)
{
--end_pos;
@@ -1329,12 +1246,12 @@ BOOST_FILESYSTEM_DECL void path::iterator::decrement_v4()
if (end_pos == root_dir_pos)
{
// Decremented to the root directory
- m_pos = end_pos;
- m_element.m_pathname = separator; // generic format; see docs
+ it.m_pos = end_pos;
+ it.m_element.m_pathname = path::separator; // generic format; see docs
return;
}
- if (!detail::is_directory_separator(m_path_ptr->m_pathname[end_pos]))
+ if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos]))
{
++end_pos;
break;
@@ -1344,10 +1261,42 @@ BOOST_FILESYSTEM_DECL void path::iterator::decrement_v4()
if (end_pos <= root_name_size)
goto set_to_root_name;
- size_type filename_size = find_filename_size(m_path_ptr->m_pathname, root_name_size, end_pos);
- m_pos = end_pos - filename_size;
- const path::value_type* p = m_path_ptr->m_pathname.c_str();
- m_element.m_pathname.assign(p + m_pos, p + end_pos);
+ size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos);
+ it.m_pos = end_pos - filename_size;
+ const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
+ it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
+}
+
+} // namespace detail
+
+// path iterators ------------------------------------------------------------------//
+
+BOOST_FILESYSTEM_DECL path::iterator path::begin() const
+{
+ iterator itr;
+ itr.m_path_ptr = this;
+
+ size_type element_size;
+ first_element(m_pathname, itr.m_pos, element_size);
+
+ if (element_size > 0)
+ {
+ itr.m_element = m_pathname.substr(itr.m_pos, element_size);
+#ifdef BOOST_WINDOWS_API
+ if (itr.m_element.m_pathname.size() == 1u && itr.m_element.m_pathname[0] == path::preferred_separator)
+ itr.m_element.m_pathname[0] = path::separator;
+#endif
+ }
+
+ return itr;
+}
+
+BOOST_FILESYSTEM_DECL path::iterator path::end() const
+{
+ iterator itr;
+ itr.m_path_ptr = this;
+ itr.m_pos = m_pathname.size();
+ return itr;
}
} // namespace filesystem
diff --git a/contrib/restricted/boost/filesystem/src/path_traits.cpp b/contrib/restricted/boost/filesystem/src/path_traits.cpp
index aa4b8815f7..baed387b4d 100644
--- a/contrib/restricted/boost/filesystem/src/path_traits.cpp
+++ b/contrib/restricted/boost/filesystem/src/path_traits.cpp
@@ -12,19 +12,19 @@
#include "platform_config.hpp"
#include <boost/filesystem/config.hpp>
-#include <boost/filesystem/path_traits.hpp>
+#include <boost/filesystem/detail/path_traits.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/system/system_error.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <boost/assert.hpp>
#include <string>
#include <locale> // for codecvt_base::result
-#include <cstring> // for strlen
-#include <cwchar> // for wcslen
+#include <cwchar> // for mbstate_t
#include <cstddef>
#include <boost/filesystem/detail/header.hpp> // must be the last #include
-namespace pt = boost::filesystem::path_traits;
+namespace pt = boost::filesystem::detail::path_traits;
namespace fs = boost::filesystem;
namespace bs = boost::system;
@@ -51,12 +51,7 @@ BOOST_CONSTEXPR_OR_CONST std::size_t default_codecvt_buf_size = BOOST_FILESYSTEM
// convert_aux const char* to wstring //
//--------------------------------------------------------------------------------------//
-void convert_aux(
- const char* from,
- const char* from_end,
- wchar_t* to, wchar_t* to_end,
- std::wstring& target,
- pt::codecvt_type const& cvt)
+void convert_aux(const char* from, const char* from_end, wchar_t* to, wchar_t* to_end, std::wstring& target, pt::codecvt_type const& cvt)
{
//std::cout << std::hex
// << " from=" << std::size_t(from)
@@ -83,12 +78,7 @@ void convert_aux(
// convert_aux const wchar_t* to string //
//--------------------------------------------------------------------------------------//
-void convert_aux(
- const wchar_t* from,
- const wchar_t* from_end,
- char* to, char* to_end,
- std::string& target,
- pt::codecvt_type const& cvt)
+void convert_aux(const wchar_t* from, const wchar_t* from_end, char* to, char* to_end, std::string& target, pt::codecvt_type const& cvt)
{
//std::cout << std::hex
// << " from=" << std::size_t(from)
@@ -119,6 +109,7 @@ void convert_aux(
namespace boost {
namespace filesystem {
+namespace detail {
namespace path_traits {
//--------------------------------------------------------------------------------------//
@@ -126,32 +117,29 @@ namespace path_traits {
//--------------------------------------------------------------------------------------//
BOOST_FILESYSTEM_DECL
-void convert(const char* from,
- const char* from_end, // 0 for null terminated MBCS
- std::wstring& to, codecvt_type const& cvt)
+void convert(const char* from, const char* from_end, std::wstring& to, const codecvt_type* cvt)
{
- BOOST_ASSERT(from);
-
- if (!from_end) // null terminated
- {
- from_end = from + std::strlen(from);
- }
-
if (from == from_end)
return;
+ BOOST_ASSERT(from != NULL);
+ BOOST_ASSERT(from_end != NULL);
+
+ if (!cvt)
+ cvt = &fs::path::codecvt();
+
std::size_t buf_size = (from_end - from) * 3; // perhaps too large, but that's OK
// dynamically allocate a buffer only if source is unusually large
if (buf_size > default_codecvt_buf_size)
{
boost::scoped_array< wchar_t > buf(new wchar_t[buf_size]);
- convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, cvt);
+ convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, *cvt);
}
else
{
wchar_t buf[default_codecvt_buf_size];
- convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, cvt);
+ convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, *cvt);
}
}
@@ -160,20 +148,17 @@ void convert(const char* from,
//--------------------------------------------------------------------------------------//
BOOST_FILESYSTEM_DECL
-void convert(const wchar_t* from,
- const wchar_t* from_end, // 0 for null terminated MBCS
- std::string& to, codecvt_type const& cvt)
+void convert(const wchar_t* from, const wchar_t* from_end, std::string& to, const codecvt_type* cvt)
{
- BOOST_ASSERT(from);
-
- if (!from_end) // null terminated
- {
- from_end = from + std::wcslen(from);
- }
-
if (from == from_end)
return;
+ BOOST_ASSERT(from != NULL);
+ BOOST_ASSERT(from_end != NULL);
+
+ if (!cvt)
+ cvt = &fs::path::codecvt();
+
// The codecvt length functions may not be implemented, and I don't really
// understand them either. Thus this code is just a guess; if it turns
// out the buffer is too small then an error will be reported and the code
@@ -185,16 +170,17 @@ void convert(const wchar_t* from,
if (buf_size > default_codecvt_buf_size)
{
boost::scoped_array< char > buf(new char[buf_size]);
- convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, cvt);
+ convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, *cvt);
}
else
{
char buf[default_codecvt_buf_size];
- convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, cvt);
+ convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, *cvt);
}
}
} // namespace path_traits
+} // namespace detail
} // namespace filesystem
} // namespace boost
diff --git a/contrib/restricted/boost/filesystem/src/windows_tools.hpp b/contrib/restricted/boost/filesystem/src/windows_tools.hpp
index 8a2de7f0c9..ca62bfbf7e 100644
--- a/contrib/restricted/boost/filesystem/src/windows_tools.hpp
+++ b/contrib/restricted/boost/filesystem/src/windows_tools.hpp
@@ -1,7 +1,8 @@
// windows_tools.hpp -----------------------------------------------------------------//
-// Copyright 2002-2009, 2014 Beman Dawes
// Copyright 2001 Dietmar Kuehl
+// Copyright 2002-2009, 2014 Beman Dawes
+// Copyright 2021-2022 Andrey Semashev
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -23,6 +24,10 @@
#include <boost/filesystem/detail/header.hpp> // must be the last #include
+#ifndef IO_REPARSE_TAG_DEDUP
+#define IO_REPARSE_TAG_DEDUP (0x80000013L)
+#endif
+
#ifndef IO_REPARSE_TAG_MOUNT_POINT
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
#endif
@@ -57,14 +62,14 @@ inline boost::filesystem::perms make_permissions(boost::filesystem::path const&
boost::filesystem::perms prms = boost::filesystem::owner_read | boost::filesystem::group_read | boost::filesystem::others_read;
if ((attr & FILE_ATTRIBUTE_READONLY) == 0u)
prms |= boost::filesystem::owner_write | boost::filesystem::group_write | boost::filesystem::others_write;
- boost::filesystem::path ext = p.extension();
+ boost::filesystem::path ext = detail::path_algorithms::extension_v4(p);
wchar_t const* q = ext.c_str();
if (equal_extension(q, L".exe", L".EXE") || equal_extension(q, L".com", L".COM") || equal_extension(q, L".bat", L".BAT") || equal_extension(q, L".cmd", L".CMD"))
prms |= boost::filesystem::owner_exe | boost::filesystem::group_exe | boost::filesystem::others_exe;
return prms;
}
-bool is_reparse_point_a_symlink_ioctl(HANDLE h);
+ULONG get_reparse_point_tag_ioctl(HANDLE h, boost::filesystem::path const& p, boost::system::error_code* ec);
inline bool is_reparse_point_tag_a_symlink(ULONG reparse_point_tag)
{
@@ -156,6 +161,9 @@ struct object_attributes
#ifndef FILE_DIRECTORY_FILE
#define FILE_DIRECTORY_FILE 0x00000001
#endif
+#ifndef FILE_SYNCHRONOUS_IO_NONALERT
+#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
+#endif
#ifndef FILE_OPEN_FOR_BACKUP_INTENT
#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
#endif
diff --git a/contrib/restricted/boost/filesystem/ya.make b/contrib/restricted/boost/filesystem/ya.make
index fb19913ed1..bd15cb93a5 100644
--- a/contrib/restricted/boost/filesystem/ya.make
+++ b/contrib/restricted/boost/filesystem/ya.make
@@ -1,4 +1,4 @@
-# Generated by devtools/yamaker from nixpkgs 22.05.
+# Generated by devtools/yamaker from nixpkgs 22.11.
LIBRARY()
@@ -6,9 +6,9 @@ LICENSE(BSL-1.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(1.80.0)
+VERSION(1.83.0)
-ORIGINAL_SOURCE(https://github.com/boostorg/filesystem/archive/boost-1.80.0.tar.gz)
+ORIGINAL_SOURCE(https://github.com/boostorg/filesystem/archive/boost-1.83.0.tar.gz)
PEERDIR(
contrib/restricted/boost/assert