Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:05:29

0001 //  filesystem path.hpp  ---------------------------------------------------------------//
0002 
0003 //  Copyright Vladimir Prus 2002
0004 //  Copyright Beman Dawes 2002-2005, 2009
0005 //  Copyright Andrey Semashev 2021-2023
0006 
0007 //  Distributed under the Boost Software License, Version 1.0.
0008 //  See http://www.boost.org/LICENSE_1_0.txt
0009 
0010 //  Library home page: http://www.boost.org/libs/filesystem
0011 
0012 //  path::stem(), extension(), and replace_extension() are based on
0013 //  basename(), extension(), and change_extension() from the original
0014 //  filesystem/convenience.hpp header by Vladimir Prus.
0015 
0016 #ifndef BOOST_FILESYSTEM_PATH_HPP
0017 #define BOOST_FILESYSTEM_PATH_HPP
0018 
0019 #include <boost/assert.hpp>
0020 #include <boost/filesystem/config.hpp>
0021 #include <boost/filesystem/detail/path_traits.hpp>
0022 #include <boost/iterator/iterator_facade.hpp>
0023 #include <boost/iterator/iterator_categories.hpp>
0024 #include <boost/core/enable_if.hpp>
0025 #include <boost/io/quoted.hpp>
0026 #include <boost/functional/hash_fwd.hpp>
0027 #include <boost/type_traits/negation.hpp>
0028 #include <boost/type_traits/conjunction.hpp>
0029 #include <boost/type_traits/disjunction.hpp>
0030 #include <boost/type_traits/is_same.hpp>
0031 #include <boost/type_traits/remove_cv.hpp>
0032 #include <cstddef>
0033 #include <iosfwd>
0034 #include <locale>
0035 #include <string>
0036 #include <iterator>
0037 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0038 #include <string_view>
0039 #endif
0040 
0041 #include <boost/filesystem/detail/header.hpp> // must be the last #include
0042 
0043 namespace boost {
0044 namespace filesystem {
0045 
0046 class path;
0047 
0048 namespace path_detail { // intentionally don't use filesystem::detail to not bring internal Boost.Filesystem functions into ADL via path_constants
0049 
0050 template< typename Char, Char Separator, Char PreferredSeparator, Char Dot >
0051 struct path_constants
0052 {
0053     typedef path_constants< Char, Separator, PreferredSeparator, Dot > path_constants_base;
0054     typedef Char value_type;
0055     static BOOST_CONSTEXPR_OR_CONST value_type separator = Separator;
0056     static BOOST_CONSTEXPR_OR_CONST value_type preferred_separator = PreferredSeparator;
0057     static BOOST_CONSTEXPR_OR_CONST value_type dot = Dot;
0058 };
0059 
0060 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0061 template< typename Char, Char Separator, Char PreferredSeparator, Char Dot >
0062 BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type
0063 path_constants< Char, Separator, PreferredSeparator, Dot >::separator;
0064 template< typename Char, Char Separator, Char PreferredSeparator, Char Dot >
0065 BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type
0066 path_constants< Char, Separator, PreferredSeparator, Dot >::preferred_separator;
0067 template< typename Char, Char Separator, Char PreferredSeparator, Char Dot >
0068 BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type
0069 path_constants< Char, Separator, PreferredSeparator, Dot >::dot;
0070 #endif
0071 
0072 class path_iterator;
0073 class path_reverse_iterator;
0074 
0075 } // namespace path_detail
0076 
0077 namespace detail {
0078 
0079 struct path_algorithms
0080 {
0081     // A struct that denotes a contiguous range of characters in a string. A lightweight alternative to string_view.
0082     struct substring
0083     {
0084         std::size_t pos;
0085         std::size_t size;
0086     };
0087 
0088     typedef path_traits::path_native_char_type value_type;
0089     typedef std::basic_string< value_type > string_type;
0090 
0091     static bool has_filename_v3(path const& p);
0092     static bool has_filename_v4(path const& p);
0093     BOOST_FILESYSTEM_DECL static path filename_v3(path const& p);
0094     static path filename_v4(path const& p);
0095 
0096     BOOST_FILESYSTEM_DECL static path stem_v3(path const& p);
0097     BOOST_FILESYSTEM_DECL static path stem_v4(path const& p);
0098     BOOST_FILESYSTEM_DECL static path extension_v3(path const& p);
0099     static path extension_v4(path const& p);
0100 
0101     BOOST_FILESYSTEM_DECL static void remove_filename_v3(path& p);
0102     BOOST_FILESYSTEM_DECL static void remove_filename_v4(path& p);
0103 
0104     BOOST_FILESYSTEM_DECL static void replace_extension_v3(path& p, path const& new_extension);
0105     BOOST_FILESYSTEM_DECL static void replace_extension_v4(path& p, path const& new_extension);
0106 
0107     BOOST_FILESYSTEM_DECL static path lexically_normal_v3(path const& p);
0108     BOOST_FILESYSTEM_DECL static path lexically_normal_v4(path const& p);
0109 
0110     BOOST_FILESYSTEM_DECL static int compare_v3(path const& left, path const& right);
0111     BOOST_FILESYSTEM_DECL static int compare_v4(path const& left, path const& right);
0112 
0113     BOOST_FILESYSTEM_DECL static void append_v3(path& p, const value_type* b, const value_type* e);
0114     BOOST_FILESYSTEM_DECL static void append_v4(path& p, const value_type* b, const value_type* e);
0115     static void append_v4(path& left, path const& right);
0116 
0117     //  Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0.
0118     //  Note: An append is never performed if size()==0, so a returned 0 is unambiguous.
0119     BOOST_FILESYSTEM_DECL static string_type::size_type append_separator_if_needed(path& p);
0120     BOOST_FILESYSTEM_DECL static void erase_redundant_separator(path& p, string_type::size_type sep_pos);
0121 
0122     BOOST_FILESYSTEM_DECL static string_type::size_type find_root_name_size(path const& p);
0123     BOOST_FILESYSTEM_DECL static string_type::size_type find_root_path_size(path const& p);
0124     BOOST_FILESYSTEM_DECL static substring find_root_directory(path const& p);
0125     BOOST_FILESYSTEM_DECL static substring find_relative_path(path const& p);
0126     BOOST_FILESYSTEM_DECL static string_type::size_type find_parent_path_size(path const& p);
0127     BOOST_FILESYSTEM_DECL static string_type::size_type find_filename_v4_size(path const& p);
0128     BOOST_FILESYSTEM_DECL static string_type::size_type find_extension_v4_size(path const& p);
0129 
0130     BOOST_FILESYSTEM_DECL static int lex_compare_v3
0131     (
0132         path_detail::path_iterator first1, path_detail::path_iterator const& last1,
0133         path_detail::path_iterator first2, path_detail::path_iterator const& last2
0134     );
0135     BOOST_FILESYSTEM_DECL static int lex_compare_v4
0136     (
0137         path_detail::path_iterator first1, path_detail::path_iterator const& last1,
0138         path_detail::path_iterator first2, path_detail::path_iterator const& last2
0139     );
0140 
0141     BOOST_FILESYSTEM_DECL static void increment_v3(path_detail::path_iterator& it);
0142     BOOST_FILESYSTEM_DECL static void increment_v4(path_detail::path_iterator& it);
0143     BOOST_FILESYSTEM_DECL static void decrement_v3(path_detail::path_iterator& it);
0144     BOOST_FILESYSTEM_DECL static void decrement_v4(path_detail::path_iterator& it);
0145 };
0146 
0147 } // namespace detail
0148 
0149 //------------------------------------------------------------------------------------//
0150 //                                                                                    //
0151 //                                    class path                                      //
0152 //                                                                                    //
0153 //------------------------------------------------------------------------------------//
0154 
0155 class path :
0156     public filesystem::path_detail::path_constants<
0157 #ifdef BOOST_WINDOWS_API
0158         detail::path_traits::path_native_char_type, L'/', L'\\', L'.'
0159 #else
0160         detail::path_traits::path_native_char_type, '/', '/', '.'
0161 #endif
0162     >
0163 {
0164     friend class path_detail::path_iterator;
0165     friend class path_detail::path_reverse_iterator;
0166     friend struct detail::path_algorithms;
0167 
0168 public:
0169     //  value_type is the character type used by the operating system API to
0170     //  represent paths.
0171 
0172     typedef detail::path_algorithms::value_type value_type;
0173     typedef detail::path_algorithms::string_type string_type;
0174     typedef detail::path_traits::codecvt_type codecvt_type;
0175 
0176     //  ----- character encoding conversions -----
0177 
0178     //  Following the principle of least astonishment, path input arguments
0179     //  passed to or obtained from the operating system via objects of
0180     //  class path behave as if they were directly passed to or
0181     //  obtained from the O/S API, unless conversion is explicitly requested.
0182     //
0183     //  POSIX specfies that path strings are passed unchanged to and from the
0184     //  API. Note that this is different from the POSIX command line utilities,
0185     //  which convert according to a locale.
0186     //
0187     //  Thus for POSIX, char strings do not undergo conversion.  wchar_t strings
0188     //  are converted to/from char using the path locale or, if a conversion
0189     //  argument is given, using a conversion object modeled on
0190     //  std::wstring_convert.
0191     //
0192     //  The path locale, which is global to the thread, can be changed by the
0193     //  imbue() function. It is initialized to an implementation defined locale.
0194     //
0195     //  For Windows, wchar_t strings do not undergo conversion. char strings
0196     //  are converted using the "ANSI" or "OEM" code pages, as determined by
0197     //  the AreFileApisANSI() function, or, if a conversion argument is given,
0198     //  using a conversion object modeled on std::wstring_convert.
0199     //
0200     //  See m_pathname comments for further important rationale.
0201 
0202     //  TODO: rules needed for operating systems that use / or .
0203     //  differently, or format directory paths differently from file paths.
0204     //
0205     //  **********************************************************************************
0206     //
0207     //  More work needed: How to handle an operating system that may have
0208     //  slash characters or dot characters in valid filenames, either because
0209     //  it doesn't follow the POSIX standard, or because it allows MBCS
0210     //  filename encodings that may contain slash or dot characters. For
0211     //  example, ISO/IEC 2022 (JIS) encoding which allows switching to
0212     //  JIS x0208-1983 encoding. A valid filename in this set of encodings is
0213     //  0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU]
0214     //                                             ^^^^
0215     //  Note that 0x2F is the ASCII slash character
0216     //
0217     //  **********************************************************************************
0218 
0219     //  Supported source arguments: half-open iterator range, container, c-array,
0220     //  and single pointer to null terminated string.
0221 
0222     //  All source arguments except pointers to null terminated byte strings support
0223     //  multi-byte character strings which may have embedded nulls. Embedded null
0224     //  support is required for some Asian languages on Windows.
0225 
0226     //  "const codecvt_type& cvt=codecvt()" default arguments are not used because this
0227     //  limits the impact of locale("") initialization failures on POSIX systems to programs
0228     //  that actually depend on locale(""). It further ensures that exceptions thrown
0229     //  as a result of such failues occur after main() has started, so can be caught.
0230 
0231 private:
0232     //! Assignment operation
0233     class assign_op
0234     {
0235     private:
0236         path& m_self;
0237 
0238     public:
0239         typedef void result_type;
0240 
0241         explicit assign_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
0242 
0243         result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
0244         {
0245             m_self.m_pathname.assign(source, source_end);
0246         }
0247 
0248         template< typename OtherChar >
0249         result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
0250         {
0251             m_self.m_pathname.clear();
0252             detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt);
0253         }
0254     };
0255 
0256     //! Concatenation operation
0257     class concat_op
0258     {
0259     private:
0260         path& m_self;
0261 
0262     public:
0263         typedef void result_type;
0264 
0265         explicit concat_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
0266 
0267         result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
0268         {
0269             m_self.m_pathname.append(source, source_end);
0270         }
0271 
0272         template< typename OtherChar >
0273         result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
0274         {
0275             detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt);
0276         }
0277     };
0278 
0279     //! Path appending operation
0280     class append_op
0281     {
0282     private:
0283         path& m_self;
0284 
0285     public:
0286         typedef void result_type;
0287 
0288         explicit append_op(path& self) BOOST_NOEXCEPT : m_self(self) {}
0289 
0290         BOOST_FORCEINLINE result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const
0291         {
0292             m_self.append(source, source_end);
0293         }
0294 
0295         template< typename OtherChar >
0296         BOOST_FORCEINLINE result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const
0297         {
0298             string_type src;
0299             detail::path_traits::convert(source, source_end, src, cvt);
0300             m_self.append(src.data(), src.data() + src.size());
0301         }
0302     };
0303 
0304     //! Path comparison operation
0305     class compare_op
0306     {
0307     private:
0308         path const& m_self;
0309 
0310     public:
0311         typedef int result_type;
0312 
0313         explicit compare_op(path const& self) BOOST_NOEXCEPT : m_self(self) {}
0314 
0315         result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const;
0316 
0317         template< typename OtherChar >
0318         result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const;
0319     };
0320 
0321 public:
0322     typedef path_detail::path_iterator iterator;
0323     typedef iterator const_iterator;
0324     typedef path_detail::path_reverse_iterator reverse_iterator;
0325     typedef reverse_iterator const_reverse_iterator;
0326 
0327 public:
0328     //  -----  constructors  -----
0329 
0330     path() BOOST_NOEXCEPT {}
0331     path(path const& p) : m_pathname(p.m_pathname) {}
0332     path(path const& p, codecvt_type const&) : m_pathname(p.m_pathname) {}
0333 
0334     path(const value_type* s) : m_pathname(s) {}
0335     path(const value_type* s, codecvt_type const&) : m_pathname(s) {}
0336     path(string_type const& s) : m_pathname(s) {}
0337     path(string_type const& s, codecvt_type const&) : m_pathname(s) {}
0338 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0339     path(std::basic_string_view< value_type > const& s) : m_pathname(s) {}
0340     path(std::basic_string_view< value_type > const& s, codecvt_type const&) : m_pathname(s) {}
0341 #endif
0342 
0343 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0344     template<
0345         typename Source,
0346         typename = typename boost::enable_if_c<
0347             boost::conjunction<
0348                 detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
0349                 boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
0350             >::value
0351         >::type
0352     >
0353     path(Source const& source)
0354 #else
0355     template< typename Source >
0356     path(Source const& source, typename boost::enable_if_c<
0357         boost::conjunction<
0358             detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
0359             boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
0360         >::value
0361     >::type* = NULL)
0362 #endif
0363     {
0364         assign(source);
0365     }
0366 
0367 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0368     template<
0369         typename Source,
0370         typename = typename boost::enable_if_c<
0371             boost::conjunction<
0372                 detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
0373                 boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
0374             >::value
0375         >::type
0376     >
0377     explicit path(Source const& source, codecvt_type const& cvt)
0378 #else
0379     template< typename Source >
0380     explicit path(Source const& source, codecvt_type const& cvt, typename boost::enable_if_c<
0381         boost::conjunction<
0382             detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
0383             boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > >
0384         >::value
0385     >::type* = NULL)
0386 #endif
0387     {
0388         assign(source, cvt);
0389     }
0390 
0391     //  As of October 2015 the interaction between noexcept and =default is so troublesome
0392     //  for VC++, GCC, and probably other compilers, that =default is not used with noexcept
0393     //  functions. GCC is not even consistent for the same release on different platforms.
0394 
0395 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0396     path(path&& p) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname))
0397     {
0398     }
0399     path(path&& p, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname))
0400     {
0401     }
0402     path& operator=(path&& p) BOOST_NOEXCEPT
0403     {
0404         m_pathname = static_cast< string_type&& >(p.m_pathname);
0405         return *this;
0406     }
0407     path& assign(path&& p) BOOST_NOEXCEPT
0408     {
0409         m_pathname = static_cast< string_type&& >(p.m_pathname);
0410         return *this;
0411     }
0412     path& assign(path&& p, codecvt_type const&) BOOST_NOEXCEPT
0413     {
0414         m_pathname = static_cast< string_type&& >(p.m_pathname);
0415         return *this;
0416     }
0417 
0418     path(string_type&& s) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s))
0419     {
0420     }
0421     path(string_type&& s, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s))
0422     {
0423     }
0424     path& operator=(string_type&& p) BOOST_NOEXCEPT
0425     {
0426         m_pathname = static_cast< string_type&& >(p);
0427         return *this;
0428     }
0429     path& assign(string_type&& p) BOOST_NOEXCEPT
0430     {
0431         m_pathname = static_cast< string_type&& >(p);
0432         return *this;
0433     }
0434     path& assign(string_type&& p, codecvt_type const&) BOOST_NOEXCEPT
0435     {
0436         m_pathname = static_cast< string_type&& >(p);
0437         return *this;
0438     }
0439 #endif
0440 
0441     path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {}
0442     path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {}
0443 
0444 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0445     template<
0446         typename InputIterator,
0447         typename = typename boost::enable_if_c<
0448             boost::conjunction<
0449                 detail::path_traits::is_path_source_iterator< InputIterator >,
0450                 boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0451             >::value
0452         >::type
0453     >
0454     path(InputIterator begin, InputIterator end)
0455 #else
0456     template< typename InputIterator >
0457     path(InputIterator begin, InputIterator end, typename boost::enable_if_c<
0458         boost::conjunction<
0459             detail::path_traits::is_path_source_iterator< InputIterator >,
0460             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0461         >::value
0462     >::type* = NULL)
0463 #endif
0464     {
0465         if (begin != end)
0466         {
0467             typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
0468             source_t source(begin, end);
0469 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0470             assign(static_cast< source_t&& >(source));
0471 #else
0472             assign(source);
0473 #endif
0474         }
0475     }
0476 
0477 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0478     template<
0479         typename InputIterator,
0480         typename = typename boost::enable_if_c<
0481             boost::conjunction<
0482                 detail::path_traits::is_path_source_iterator< InputIterator >,
0483                 boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0484             >::value
0485         >::type
0486     >
0487     path(InputIterator begin, InputIterator end, codecvt_type const& cvt)
0488 #else
0489     template< typename InputIterator >
0490     path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::enable_if_c<
0491         boost::conjunction<
0492             detail::path_traits::is_path_source_iterator< InputIterator >,
0493             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0494         >::value
0495     >::type* = NULL)
0496 #endif
0497     {
0498         if (begin != end)
0499         {
0500             typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
0501             source_t source(begin, end);
0502 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0503             assign(static_cast< source_t&& >(source), cvt);
0504 #else
0505             assign(source, cvt);
0506 #endif
0507         }
0508     }
0509 
0510 #if !defined(BOOST_NO_CXX11_NULLPTR)
0511     BOOST_DELETED_FUNCTION(path(std::nullptr_t))
0512     BOOST_DELETED_FUNCTION(path& operator= (std::nullptr_t))
0513 #endif
0514 
0515 public:
0516     //  -----  assignments  -----
0517 
0518     // We need to explicitly define copy assignment as otherwise it will be implicitly defined as deleted because there is move assignment
0519     path& operator=(path const& p);
0520 
0521     template< typename Source >
0522     typename boost::enable_if_c<
0523         boost::disjunction<
0524             detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >,
0525             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
0526         >::value,
0527         path&
0528     >::type operator=(Source const& source)
0529     {
0530         return assign(source);
0531     }
0532 
0533     path& assign(path const& p)
0534     {
0535         m_pathname = p.m_pathname;
0536         return *this;
0537     }
0538 
0539     template< typename Source >
0540     typename boost::enable_if_c<
0541         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0542         path&
0543     >::type assign(Source const& source)
0544     {
0545         detail::path_traits::dispatch(source, assign_op(*this));
0546         return *this;
0547     }
0548 
0549     template< typename Source >
0550     typename boost::enable_if_c<
0551         boost::conjunction<
0552             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0553             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0554         >::value,
0555         path&
0556     >::type assign(Source const& source)
0557     {
0558         detail::path_traits::dispatch_convertible(source, assign_op(*this));
0559         return *this;
0560     }
0561 
0562     path& assign(path const& p, codecvt_type const&)
0563     {
0564         m_pathname = p.m_pathname;
0565         return *this;
0566     }
0567 
0568     template< typename Source >
0569     typename boost::enable_if_c<
0570         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0571         path&
0572     >::type assign(Source const& source, codecvt_type const& cvt)
0573     {
0574         detail::path_traits::dispatch(source, assign_op(*this), &cvt);
0575         return *this;
0576     }
0577 
0578     template< typename Source >
0579     typename boost::enable_if_c<
0580         boost::conjunction<
0581             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0582             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0583         >::value,
0584         path&
0585     >::type assign(Source const& source, codecvt_type const& cvt)
0586     {
0587         detail::path_traits::dispatch_convertible(source, assign_op(*this), &cvt);
0588         return *this;
0589     }
0590 
0591     path& assign(const value_type* begin, const value_type* end)
0592     {
0593         m_pathname.assign(begin, end);
0594         return *this;
0595     }
0596 
0597     template< typename InputIterator >
0598     typename boost::enable_if_c<
0599         boost::conjunction<
0600             detail::path_traits::is_path_source_iterator< InputIterator >,
0601             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0602         >::value,
0603         path&
0604     >::type assign(InputIterator begin, InputIterator end)
0605     {
0606         m_pathname.clear();
0607         if (begin != end)
0608         {
0609             typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
0610             source_t source(begin, end);
0611 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0612             assign(static_cast< source_t&& >(source));
0613 #else
0614             assign(source);
0615 #endif
0616         }
0617         return *this;
0618     }
0619 
0620     path& assign(const value_type* begin, const value_type* end, codecvt_type const&)
0621     {
0622         m_pathname.assign(begin, end);
0623         return *this;
0624     }
0625 
0626     template< typename InputIterator >
0627     typename boost::enable_if_c<
0628         boost::conjunction<
0629             detail::path_traits::is_path_source_iterator< InputIterator >,
0630             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0631         >::value,
0632         path&
0633     >::type assign(InputIterator begin, InputIterator end, codecvt_type const& cvt)
0634     {
0635         m_pathname.clear();
0636         if (begin != end)
0637         {
0638             typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t;
0639             source_t source(begin, end);
0640 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0641             assign(static_cast< source_t&& >(source), cvt);
0642 #else
0643             assign(source, cvt);
0644 #endif
0645         }
0646         return *this;
0647     }
0648 
0649     //  -----  concatenation  -----
0650 
0651     path& operator+=(path const& p);
0652 
0653     template< typename Source >
0654     typename boost::enable_if_c<
0655         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
0656         path&
0657     >::type operator+=(Source const& source)
0658     {
0659         return concat(source);
0660     }
0661 
0662     path& operator+=(value_type c)
0663     {
0664         m_pathname.push_back(c);
0665         return *this;
0666     }
0667 
0668     template< typename CharT >
0669     typename boost::enable_if_c<
0670         detail::path_traits::is_path_char_type< CharT >::value,
0671         path&
0672     >::type operator+=(CharT c)
0673     {
0674         CharT tmp[2];
0675         tmp[0] = c;
0676         tmp[1] = static_cast< CharT >(0);
0677         concat_op(*this)(tmp, tmp + 1);
0678         return *this;
0679     }
0680 
0681     path& concat(path const& p)
0682     {
0683         m_pathname.append(p.m_pathname);
0684         return *this;
0685     }
0686 
0687     template< typename Source >
0688     typename boost::enable_if_c<
0689         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0690         path&
0691     >::type concat(Source const& source)
0692     {
0693         detail::path_traits::dispatch(source, concat_op(*this));
0694         return *this;
0695     }
0696 
0697     template< typename Source >
0698     typename boost::enable_if_c<
0699         boost::conjunction<
0700             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0701             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0702         >::value,
0703         path&
0704     >::type concat(Source const& source)
0705     {
0706         detail::path_traits::dispatch_convertible(source, concat_op(*this));
0707         return *this;
0708     }
0709 
0710     path& concat(path const& p, codecvt_type const&)
0711     {
0712         m_pathname.append(p.m_pathname);
0713         return *this;
0714     }
0715 
0716     template< typename Source >
0717     typename boost::enable_if_c<
0718         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0719         path&
0720     >::type concat(Source const& source, codecvt_type const& cvt)
0721     {
0722         detail::path_traits::dispatch(source, concat_op(*this), &cvt);
0723         return *this;
0724     }
0725 
0726     template< typename Source >
0727     typename boost::enable_if_c<
0728         boost::conjunction<
0729             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0730             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0731         >::value,
0732         path&
0733     >::type concat(Source const& source, codecvt_type const& cvt)
0734     {
0735         detail::path_traits::dispatch_convertible(source, concat_op(*this), &cvt);
0736         return *this;
0737     }
0738 
0739     path& concat(const value_type* begin, const value_type* end)
0740     {
0741         m_pathname.append(begin, end);
0742         return *this;
0743     }
0744 
0745     template< typename InputIterator >
0746     typename boost::enable_if_c<
0747         boost::conjunction<
0748             detail::path_traits::is_path_source_iterator< InputIterator >,
0749             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0750         >::value,
0751         path&
0752     >::type concat(InputIterator begin, InputIterator end)
0753     {
0754         if (begin != end)
0755         {
0756             std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
0757             detail::path_traits::dispatch(source, concat_op(*this));
0758         }
0759         return *this;
0760     }
0761 
0762     path& concat(const value_type* begin, const value_type* end, codecvt_type const&)
0763     {
0764         m_pathname.append(begin, end);
0765         return *this;
0766     }
0767 
0768     template< typename InputIterator >
0769     typename boost::enable_if_c<
0770         boost::conjunction<
0771             detail::path_traits::is_path_source_iterator< InputIterator >,
0772             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0773         >::value,
0774         path&
0775     >::type concat(InputIterator begin, InputIterator end, codecvt_type const& cvt)
0776     {
0777         if (begin != end)
0778         {
0779             std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
0780             detail::path_traits::dispatch(source, concat_op(*this), &cvt);
0781         }
0782         return *this;
0783     }
0784 
0785     //  -----  appends  -----
0786 
0787     //  if a separator is added, it is the preferred separator for the platform;
0788     //  slash for POSIX, backslash for Windows
0789 
0790     path& operator/=(path const& p);
0791 
0792     template< typename Source >
0793     BOOST_FORCEINLINE typename boost::enable_if_c<
0794         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
0795         path&
0796     >::type operator/=(Source const& source)
0797     {
0798         return append(source);
0799     }
0800 
0801     path& append(path const& p);
0802 
0803     template< typename Source >
0804     BOOST_FORCEINLINE typename boost::enable_if_c<
0805         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0806         path&
0807     >::type append(Source const& source)
0808     {
0809         detail::path_traits::dispatch(source, append_op(*this));
0810         return *this;
0811     }
0812 
0813     template< typename Source >
0814     BOOST_FORCEINLINE typename boost::enable_if_c<
0815         boost::conjunction<
0816             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0817             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0818         >::value,
0819         path&
0820     >::type append(Source const& source)
0821     {
0822         detail::path_traits::dispatch_convertible(source, append_op(*this));
0823         return *this;
0824     }
0825 
0826     path& append(path const& p, codecvt_type const&);
0827 
0828     template< typename Source >
0829     BOOST_FORCEINLINE typename boost::enable_if_c<
0830         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
0831         path&
0832     >::type append(Source const& source, codecvt_type const& cvt)
0833     {
0834         detail::path_traits::dispatch(source, append_op(*this), &cvt);
0835         return *this;
0836     }
0837 
0838     template< typename Source >
0839     BOOST_FORCEINLINE typename boost::enable_if_c<
0840         boost::conjunction<
0841             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
0842             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
0843         >::value,
0844         path&
0845     >::type append(Source const& source, codecvt_type const& cvt)
0846     {
0847         detail::path_traits::dispatch_convertible(source, append_op(*this), &cvt);
0848         return *this;
0849     }
0850 
0851     path& append(const value_type* begin, const value_type* end);
0852 
0853     template< typename InputIterator >
0854     BOOST_FORCEINLINE typename boost::enable_if_c<
0855         boost::conjunction<
0856             detail::path_traits::is_path_source_iterator< InputIterator >,
0857             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0858         >::value,
0859         path&
0860     >::type append(InputIterator begin, InputIterator end)
0861     {
0862         std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
0863         detail::path_traits::dispatch(source, append_op(*this));
0864         return *this;
0865     }
0866 
0867     path& append(const value_type* begin, const value_type* end, codecvt_type const&);
0868 
0869     template< typename InputIterator >
0870     BOOST_FORCEINLINE typename boost::enable_if_c<
0871         boost::conjunction<
0872             detail::path_traits::is_path_source_iterator< InputIterator >,
0873             boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > >
0874         >::value,
0875         path&
0876     >::type append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
0877     {
0878         std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end);
0879         detail::path_traits::dispatch(source, append_op(*this), &cvt);
0880         return *this;
0881     }
0882 
0883     //  -----  modifiers  -----
0884 
0885     void clear() BOOST_NOEXCEPT { m_pathname.clear(); }
0886 #ifdef BOOST_POSIX_API
0887     path& make_preferred()
0888     {
0889         // No effect on POSIX
0890         return *this;
0891     }
0892 #else // BOOST_WINDOWS_API
0893     BOOST_FILESYSTEM_DECL path& make_preferred(); // change slashes to backslashes
0894 #endif
0895     path& remove_filename();
0896     BOOST_FILESYSTEM_DECL path& remove_filename_and_trailing_separators();
0897     BOOST_FILESYSTEM_DECL path& remove_trailing_separator();
0898     BOOST_FILESYSTEM_DECL path& replace_filename(path const& replacement);
0899     path& replace_extension(path const& new_extension = path());
0900 
0901     void swap(path& rhs) BOOST_NOEXCEPT { m_pathname.swap(rhs.m_pathname); }
0902 
0903     //  -----  observers  -----
0904 
0905     //  For operating systems that format file paths differently than directory
0906     //  paths, return values from observers are formatted as file names unless there
0907     //  is a trailing separator, in which case returns are formatted as directory
0908     //  paths. POSIX and Windows make no such distinction.
0909 
0910     //  Implementations are permitted to return const values or const references.
0911 
0912     //  The string or path returned by an observer are specified as being formatted
0913     //  as "native" or "generic".
0914     //
0915     //  For POSIX, these are all the same format; slashes and backslashes are as input and
0916     //  are not modified.
0917     //
0918     //  For Windows,   native:    as input; slashes and backslashes are not modified;
0919     //                            this is the format of the internally stored string.
0920     //                 generic:   backslashes are converted to slashes
0921 
0922     //  -----  native format observers  -----
0923 
0924     string_type const& native() const BOOST_NOEXCEPT { return m_pathname; }
0925     const value_type* c_str() const BOOST_NOEXCEPT { return m_pathname.c_str(); }
0926     string_type::size_type size() const BOOST_NOEXCEPT { return m_pathname.size(); }
0927 
0928     template< typename String >
0929     String string() const;
0930 
0931     template< typename String >
0932     String string(codecvt_type const& cvt) const;
0933 
0934 #ifdef BOOST_WINDOWS_API
0935     std::string string() const
0936     {
0937         std::string tmp;
0938         if (!m_pathname.empty())
0939             detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp);
0940         return tmp;
0941     }
0942     std::string string(codecvt_type const& cvt) const
0943     {
0944         std::string tmp;
0945         if (!m_pathname.empty())
0946             detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt);
0947         return tmp;
0948     }
0949 
0950     //  string_type is std::wstring, so there is no conversion
0951     std::wstring const& wstring() const { return m_pathname; }
0952     std::wstring const& wstring(codecvt_type const&) const { return m_pathname; }
0953 #else // BOOST_POSIX_API
0954     //  string_type is std::string, so there is no conversion
0955     std::string const& string() const { return m_pathname; }
0956     std::string const& string(codecvt_type const&) const { return m_pathname; }
0957 
0958     std::wstring wstring() const
0959     {
0960         std::wstring tmp;
0961         if (!m_pathname.empty())
0962             detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp);
0963         return tmp;
0964     }
0965     std::wstring wstring(codecvt_type const& cvt) const
0966     {
0967         std::wstring tmp;
0968         if (!m_pathname.empty())
0969             detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt);
0970         return tmp;
0971     }
0972 #endif
0973 
0974     //  -----  generic format observers  -----
0975 
0976     //  Experimental generic function returning generic formatted path (i.e. separators
0977     //  are forward slashes). Motivation: simpler than a family of generic_*string
0978     //  functions.
0979 #ifdef BOOST_WINDOWS_API
0980     BOOST_FILESYSTEM_DECL path generic_path() const;
0981 #else
0982     path generic_path() const;
0983 #endif
0984 
0985     template< typename String >
0986     String generic_string() const;
0987 
0988     template< typename String >
0989     String generic_string(codecvt_type const& cvt) const;
0990 
0991 #ifdef BOOST_WINDOWS_API
0992     std::string generic_string() const { return generic_path().string(); }
0993     std::string generic_string(codecvt_type const& cvt) const { return generic_path().string(cvt); }
0994     std::wstring generic_wstring() const { return generic_path().wstring(); }
0995     std::wstring generic_wstring(codecvt_type const&) const { return generic_wstring(); }
0996 #else // BOOST_POSIX_API
0997     //  On POSIX-like systems, the generic format is the same as the native format
0998     std::string const& generic_string() const { return m_pathname; }
0999     std::string const& generic_string(codecvt_type const&) const { return m_pathname; }
1000     std::wstring generic_wstring() const { return this->wstring(); }
1001     std::wstring generic_wstring(codecvt_type const& cvt) const { return this->wstring(cvt); }
1002 #endif
1003 
1004     //  -----  compare  -----
1005 
1006     int compare(path const& p) const; // generic, lexicographical
1007 
1008     template< typename Source >
1009     BOOST_FORCEINLINE typename boost::enable_if_c<
1010         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
1011         int
1012     >::type compare(Source const& source) const
1013     {
1014         return detail::path_traits::dispatch(source, compare_op(*this));
1015     }
1016 
1017     template< typename Source >
1018     BOOST_FORCEINLINE typename boost::enable_if_c<
1019         boost::conjunction<
1020             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
1021             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
1022         >::value,
1023         int
1024     >::type compare(Source const& source) const
1025     {
1026         return detail::path_traits::dispatch_convertible(source, compare_op(*this));
1027     }
1028 
1029     template< typename Source >
1030     BOOST_FORCEINLINE typename boost::enable_if_c<
1031         detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value,
1032         int
1033     >::type compare(Source const& source, codecvt_type const& cvt) const
1034     {
1035         return detail::path_traits::dispatch(source, compare_op(*this), &cvt);
1036     }
1037 
1038     template< typename Source >
1039     BOOST_FORCEINLINE typename boost::enable_if_c<
1040         boost::conjunction<
1041             detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >,
1042             boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > >
1043         >::value,
1044         int
1045     >::type compare(Source const& source, codecvt_type const& cvt) const
1046     {
1047         return detail::path_traits::dispatch_convertible(source, compare_op(*this), &cvt);
1048     }
1049 
1050     //  -----  decomposition  -----
1051 
1052     path root_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_path_size(*this)); }
1053     // returns 0 or 1 element path even on POSIX, root_name() is non-empty() for network paths
1054     path root_name() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_name_size(*this)); }
1055 
1056     // returns 0 or 1 element path
1057     path root_directory() const
1058     {
1059         detail::path_algorithms::substring root_dir = detail::path_algorithms::find_root_directory(*this);
1060         const value_type* p = m_pathname.c_str() + root_dir.pos;
1061         return path(p, p + root_dir.size);
1062     }
1063 
1064     path relative_path() const
1065     {
1066         detail::path_algorithms::substring rel_path = detail::path_algorithms::find_relative_path(*this);
1067         const value_type* p = m_pathname.c_str() + rel_path.pos;
1068         return path(p, p + rel_path.size);
1069     }
1070 
1071     path parent_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_parent_path_size(*this)); }
1072 
1073     path filename() const;  // returns 0 or 1 element path
1074     path stem() const;      // returns 0 or 1 element path
1075     path extension() const; // returns 0 or 1 element path
1076 
1077     //  -----  query  -----
1078 
1079     bool empty() const BOOST_NOEXCEPT { return m_pathname.empty(); }
1080     bool filename_is_dot() const;
1081     bool filename_is_dot_dot() const;
1082     bool has_root_path() const { return detail::path_algorithms::find_root_path_size(*this) > 0; }
1083     bool has_root_name() const { return detail::path_algorithms::find_root_name_size(*this) > 0; }
1084     bool has_root_directory() const { return detail::path_algorithms::find_root_directory(*this).size > 0; }
1085     bool has_relative_path() const { return detail::path_algorithms::find_relative_path(*this).size > 0; }
1086     bool has_parent_path() const { return detail::path_algorithms::find_parent_path_size(*this) > 0; }
1087     bool has_filename() const;
1088     bool has_stem() const { return !stem().empty(); }
1089     bool has_extension() const { return !extension().empty(); }
1090     bool is_relative() const { return !is_absolute(); }
1091     bool is_absolute() const
1092     {
1093 #if defined(BOOST_WINDOWS_API)
1094         return has_root_name() && has_root_directory();
1095 #else
1096         return has_root_directory();
1097 #endif
1098     }
1099 
1100     //  -----  lexical operations  -----
1101 
1102     path lexically_normal() const;
1103     BOOST_FILESYSTEM_DECL path lexically_relative(path const& base) const;
1104     path lexically_proximate(path const& base) const;
1105 
1106     //  -----  iterators  -----
1107 
1108     BOOST_FILESYSTEM_DECL iterator begin() const;
1109     BOOST_FILESYSTEM_DECL iterator end() const;
1110     reverse_iterator rbegin() const;
1111     reverse_iterator rend() const;
1112 
1113     //  -----  static member functions  -----
1114 
1115     static BOOST_FILESYSTEM_DECL std::locale imbue(std::locale const& loc);
1116     static BOOST_FILESYSTEM_DECL codecvt_type const& codecvt();
1117 
1118     //  -----  deprecated functions  -----
1119 
1120 #if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
1121     //  recently deprecated functions supplied by default
1122     path& normalize();
1123     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::remove_filename() instead")
1124     path& remove_leaf() { return remove_filename(); }
1125     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::filename() instead")
1126     path leaf() const { return filename(); }
1127     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::parent_path() instead")
1128     path branch_path() const { return parent_path(); }
1129     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::generic_path() instead")
1130     path generic() const { return generic_path(); }
1131     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use !path::empty() instead")
1132     bool has_leaf() const { return !m_pathname.empty(); }
1133     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::has_parent_path() instead")
1134     bool has_branch_path() const { return has_parent_path(); }
1135     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::is_absolute() instead")
1136     bool is_complete() const { return is_absolute(); }
1137 #endif
1138 
1139 #if defined(BOOST_FILESYSTEM_DEPRECATED)
1140     //  deprecated functions with enough signature or semantic changes that they are
1141     //  not supplied by default
1142     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
1143     std::string file_string() const { return string(); }
1144     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
1145     std::string directory_string() const { return string(); }
1146     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
1147     std::string native_file_string() const { return string(); }
1148     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead")
1149     std::string native_directory_string() const { return string(); }
1150     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead")
1151     string_type external_file_string() const { return native(); }
1152     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead")
1153     string_type external_directory_string() const { return native(); }
1154 #endif
1155 
1156     //--------------------------------------------------------------------------------------//
1157     //                            class path private members                                //
1158     //--------------------------------------------------------------------------------------//
1159 private:
1160     /*
1161      * m_pathname has the type, encoding, and format required by the native
1162      * operating system. Thus for POSIX and Windows there is no conversion for
1163      * passing m_pathname.c_str() to the O/S API or when obtaining a path from the
1164      * O/S API. POSIX encoding is unspecified other than for dot and slash
1165      * characters; POSIX just treats paths as a sequence of bytes. Windows
1166      * encoding is UCS-2 or UTF-16 depending on the version.
1167      */
1168     string_type m_pathname;     // Windows: as input; backslashes NOT converted to slashes,
1169                                 // slashes NOT converted to backslashes
1170 };
1171 
1172 namespace detail {
1173 BOOST_FILESYSTEM_DECL path const& dot_path();
1174 BOOST_FILESYSTEM_DECL path const& dot_dot_path();
1175 } // namespace detail
1176 
1177 #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
1178 typedef path wpath;
1179 #endif
1180 
1181 namespace path_detail {
1182 
1183 //------------------------------------------------------------------------------------//
1184 //                             class path::iterator                                   //
1185 //------------------------------------------------------------------------------------//
1186 
1187 class path_iterator :
1188     public boost::iterator_facade<
1189         path_iterator,
1190         const path,
1191         boost::bidirectional_traversal_tag
1192     >
1193 {
1194 private:
1195     friend class boost::iterator_core_access;
1196     friend class boost::filesystem::path;
1197     friend class path_reverse_iterator;
1198     friend struct boost::filesystem::detail::path_algorithms;
1199 
1200     path const& dereference() const { return m_element; }
1201 
1202     bool equal(path_iterator const& rhs) const BOOST_NOEXCEPT
1203     {
1204         return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos;
1205     }
1206 
1207     void increment();
1208     void decrement();
1209 
1210 private:
1211     // current element
1212     path m_element;
1213     // path being iterated over
1214     const path* m_path_ptr;
1215     // position of m_element in m_path_ptr->m_pathname.
1216     // if m_element is implicit dot, m_pos is the
1217     // position of the last separator in the path.
1218     // end() iterator is indicated by
1219     // m_pos == m_path_ptr->m_pathname.size()
1220     path::string_type::size_type m_pos;
1221 };
1222 
1223 //------------------------------------------------------------------------------------//
1224 //                         class path::reverse_iterator                               //
1225 //------------------------------------------------------------------------------------//
1226 
1227 class path_reverse_iterator :
1228     public boost::iterator_facade<
1229         path_reverse_iterator,
1230         const path,
1231         boost::bidirectional_traversal_tag
1232     >
1233 {
1234 public:
1235     explicit path_reverse_iterator(path_iterator itr) :
1236         m_itr(itr)
1237     {
1238         if (itr != itr.m_path_ptr->begin())
1239             m_element = *--itr;
1240     }
1241 
1242 private:
1243     friend class boost::iterator_core_access;
1244     friend class boost::filesystem::path;
1245 
1246     path const& dereference() const { return m_element; }
1247     bool equal(path_reverse_iterator const& rhs) const BOOST_NOEXCEPT { return m_itr == rhs.m_itr; }
1248 
1249     void increment()
1250     {
1251         --m_itr;
1252         if (m_itr != m_itr.m_path_ptr->begin())
1253         {
1254             path_iterator tmp = m_itr;
1255             m_element = *--tmp;
1256         }
1257     }
1258 
1259     void decrement()
1260     {
1261         m_element = *m_itr;
1262         ++m_itr;
1263     }
1264 
1265 private:
1266     path_iterator m_itr;
1267     path m_element;
1268 };
1269 
1270 //  std::lexicographical_compare would infinitely recurse because path iterators
1271 //  yield paths, so provide a path aware version
1272 bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2);
1273 
1274 } // namespace path_detail
1275 
1276 using path_detail::lexicographical_compare;
1277 
1278 //------------------------------------------------------------------------------------//
1279 //                                                                                    //
1280 //                              non-member functions                                  //
1281 //                                                                                    //
1282 //------------------------------------------------------------------------------------//
1283 
1284 BOOST_FORCEINLINE bool operator==(path const& lhs, path const& rhs)
1285 {
1286     return lhs.compare(rhs) == 0;
1287 }
1288 
1289 template< typename Path, typename Source >
1290 BOOST_FORCEINLINE typename boost::enable_if_c<
1291     boost::conjunction<
1292         boost::is_same< Path, path >,
1293         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1294     >::value,
1295     bool
1296 >::type operator==(Path const& lhs, Source const& rhs)
1297 {
1298     return lhs.compare(rhs) == 0;
1299 }
1300 
1301 template< typename Source, typename Path >
1302 BOOST_FORCEINLINE typename boost::enable_if_c<
1303     boost::conjunction<
1304         boost::is_same< Path, path >,
1305         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1306     >::value,
1307     bool
1308 >::type operator==(Source const& lhs, Path const& rhs)
1309 {
1310     return rhs.compare(lhs) == 0;
1311 }
1312 
1313 BOOST_FORCEINLINE bool operator!=(path const& lhs, path const& rhs)
1314 {
1315     return lhs.compare(rhs) != 0;
1316 }
1317 
1318 template< typename Path, typename Source >
1319 BOOST_FORCEINLINE typename boost::enable_if_c<
1320     boost::conjunction<
1321         boost::is_same< Path, path >,
1322         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1323     >::value,
1324     bool
1325 >::type operator!=(Path const& lhs, Source const& rhs)
1326 {
1327     return lhs.compare(rhs) != 0;
1328 }
1329 
1330 template< typename Source, typename Path >
1331 BOOST_FORCEINLINE typename boost::enable_if_c<
1332     boost::conjunction<
1333         boost::is_same< Path, path >,
1334         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1335     >::value,
1336     bool
1337 >::type operator!=(Source const& lhs, Path const& rhs)
1338 {
1339     return rhs.compare(lhs) != 0;
1340 }
1341 
1342 BOOST_FORCEINLINE bool operator<(path const& lhs, path const& rhs)
1343 {
1344     return lhs.compare(rhs) < 0;
1345 }
1346 
1347 template< typename Path, typename Source >
1348 BOOST_FORCEINLINE typename boost::enable_if_c<
1349     boost::conjunction<
1350         boost::is_same< Path, path >,
1351         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1352     >::value,
1353     bool
1354 >::type operator<(Path const& lhs, Source const& rhs)
1355 {
1356     return lhs.compare(rhs) < 0;
1357 }
1358 
1359 template< typename Source, typename Path >
1360 BOOST_FORCEINLINE typename boost::enable_if_c<
1361     boost::conjunction<
1362         boost::is_same< Path, path >,
1363         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1364     >::value,
1365     bool
1366 >::type operator<(Source const& lhs, Path const& rhs)
1367 {
1368     return rhs.compare(lhs) > 0;
1369 }
1370 
1371 BOOST_FORCEINLINE bool operator<=(path const& lhs, path const& rhs)
1372 {
1373     return lhs.compare(rhs) <= 0;
1374 }
1375 
1376 template< typename Path, typename Source >
1377 BOOST_FORCEINLINE typename boost::enable_if_c<
1378     boost::conjunction<
1379         boost::is_same< Path, path >,
1380         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1381     >::value,
1382     bool
1383 >::type operator<=(Path const& lhs, Source const& rhs)
1384 {
1385     return lhs.compare(rhs) <= 0;
1386 }
1387 
1388 template< typename Source, typename Path >
1389 BOOST_FORCEINLINE typename boost::enable_if_c<
1390     boost::conjunction<
1391         boost::is_same< Path, path >,
1392         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1393     >::value,
1394     bool
1395 >::type operator<=(Source const& lhs, Path const& rhs)
1396 {
1397     return rhs.compare(lhs) >= 0;
1398 }
1399 
1400 BOOST_FORCEINLINE bool operator>(path const& lhs, path const& rhs)
1401 {
1402     return lhs.compare(rhs) > 0;
1403 }
1404 
1405 template< typename Path, typename Source >
1406 BOOST_FORCEINLINE typename boost::enable_if_c<
1407     boost::conjunction<
1408         boost::is_same< Path, path >,
1409         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1410     >::value,
1411     bool
1412 >::type operator>(Path const& lhs, Source const& rhs)
1413 {
1414     return lhs.compare(rhs) > 0;
1415 }
1416 
1417 template< typename Source, typename Path >
1418 BOOST_FORCEINLINE typename boost::enable_if_c<
1419     boost::conjunction<
1420         boost::is_same< Path, path >,
1421         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1422     >::value,
1423     bool
1424 >::type operator>(Source const& lhs, Path const& rhs)
1425 {
1426     return rhs.compare(lhs) < 0;
1427 }
1428 
1429 BOOST_FORCEINLINE bool operator>=(path const& lhs, path const& rhs)
1430 {
1431     return lhs.compare(rhs) >= 0;
1432 }
1433 
1434 template< typename Path, typename Source >
1435 BOOST_FORCEINLINE typename boost::enable_if_c<
1436     boost::conjunction<
1437         boost::is_same< Path, path >,
1438         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1439     >::value,
1440     bool
1441 >::type operator>=(Path const& lhs, Source const& rhs)
1442 {
1443     return lhs.compare(rhs) >= 0;
1444 }
1445 
1446 template< typename Source, typename Path >
1447 BOOST_FORCEINLINE typename boost::enable_if_c<
1448     boost::conjunction<
1449         boost::is_same< Path, path >,
1450         detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
1451     >::value,
1452     bool
1453 >::type operator>=(Source const& lhs, Path const& rhs)
1454 {
1455     return rhs.compare(lhs) <= 0;
1456 }
1457 
1458 
1459 // Note: Declared as a template to delay binding to Boost.ContainerHash functions and make the dependency optional
1460 template< typename Path >
1461 inline typename boost::enable_if_c<
1462     boost::is_same< Path, path >::value,
1463     std::size_t
1464 >::type hash_value(Path const& p) BOOST_NOEXCEPT
1465 {
1466 #ifdef BOOST_WINDOWS_API
1467     std::size_t seed = 0u;
1468     for (typename Path::value_type const* it = p.c_str(); *it; ++it)
1469         hash_combine(seed, *it == L'/' ? L'\\' : *it);
1470     return seed;
1471 #else // BOOST_POSIX_API
1472     return hash_range(p.native().begin(), p.native().end());
1473 #endif
1474 }
1475 
1476 inline void swap(path& lhs, path& rhs) BOOST_NOEXCEPT
1477 {
1478     lhs.swap(rhs);
1479 }
1480 
1481 BOOST_FORCEINLINE path operator/(path lhs, path const& rhs)
1482 {
1483     lhs.append(rhs);
1484     return lhs;
1485 }
1486 
1487 template< typename Source >
1488 BOOST_FORCEINLINE typename boost::enable_if_c<
1489     detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
1490     path
1491 >::type operator/(path lhs, Source const& rhs)
1492 {
1493     lhs.append(rhs);
1494     return lhs;
1495 }
1496 
1497 //  inserters and extractors
1498 //    use boost::io::quoted() to handle spaces in paths
1499 //    use '&' as escape character to ease use for Windows paths
1500 
1501 template< typename Char, typename Traits >
1502 inline std::basic_ostream< Char, Traits >&
1503 operator<<(std::basic_ostream< Char, Traits >& os, path const& p)
1504 {
1505     return os << boost::io::quoted(p.template string< std::basic_string< Char > >(), static_cast< Char >('&'));
1506 }
1507 
1508 template< typename Char, typename Traits >
1509 inline std::basic_istream< Char, Traits >&
1510 operator>>(std::basic_istream< Char, Traits >& is, path& p)
1511 {
1512     std::basic_string< Char > str;
1513     is >> boost::io::quoted(str, static_cast< Char >('&'));
1514     p = str;
1515     return is;
1516 }
1517 
1518 //  name_checks
1519 
1520 //  These functions are holdovers from version 1. It isn't clear they have much
1521 //  usefulness, or how to generalize them for later versions.
1522 
1523 BOOST_FILESYSTEM_DECL bool portable_posix_name(std::string const& name);
1524 BOOST_FILESYSTEM_DECL bool windows_name(std::string const& name);
1525 BOOST_FILESYSTEM_DECL bool portable_name(std::string const& name);
1526 BOOST_FILESYSTEM_DECL bool portable_directory_name(std::string const& name);
1527 BOOST_FILESYSTEM_DECL bool portable_file_name(std::string const& name);
1528 BOOST_FILESYSTEM_DECL bool native(std::string const& name);
1529 
1530 namespace detail {
1531 
1532 //  For POSIX, is_directory_separator() and is_element_separator() are identical since
1533 //  a forward slash is the only valid directory separator and also the only valid
1534 //  element separator. For Windows, forward slash and back slash are the possible
1535 //  directory separators, but colon (example: "c:foo") is also an element separator.
1536 inline bool is_directory_separator(path::value_type c) BOOST_NOEXCEPT
1537 {
1538     return c == path::separator
1539 #ifdef BOOST_WINDOWS_API
1540         || c == path::preferred_separator
1541 #endif
1542         ;
1543 }
1544 
1545 inline bool is_element_separator(path::value_type c) BOOST_NOEXCEPT
1546 {
1547     return c == path::separator
1548 #ifdef BOOST_WINDOWS_API
1549         || c == path::preferred_separator || c == L':'
1550 #endif
1551         ;
1552 }
1553 
1554 } // namespace detail
1555 
1556 //------------------------------------------------------------------------------------//
1557 //                  class path miscellaneous function implementations                 //
1558 //------------------------------------------------------------------------------------//
1559 
1560 namespace detail {
1561 
1562 inline bool path_algorithms::has_filename_v3(path const& p)
1563 {
1564     return !p.m_pathname.empty();
1565 }
1566 
1567 inline bool path_algorithms::has_filename_v4(path const& p)
1568 {
1569     return path_algorithms::find_filename_v4_size(p) > 0;
1570 }
1571 
1572 inline path path_algorithms::filename_v4(path const& p)
1573 {
1574     string_type::size_type filename_size = path_algorithms::find_filename_v4_size(p);
1575     string_type::size_type pos = p.m_pathname.size() - filename_size;
1576     const value_type* ptr = p.m_pathname.c_str() + pos;
1577     return path(ptr, ptr + filename_size);
1578 }
1579 
1580 inline path path_algorithms::extension_v4(path const& p)
1581 {
1582     string_type::size_type extension_size = path_algorithms::find_extension_v4_size(p);
1583     string_type::size_type pos = p.m_pathname.size() - extension_size;
1584     const value_type* ptr = p.m_pathname.c_str() + pos;
1585     return path(ptr, ptr + extension_size);
1586 }
1587 
1588 inline void path_algorithms::append_v4(path& left, path const& right)
1589 {
1590     path_algorithms::append_v4(left, right.m_pathname.c_str(), right.m_pathname.c_str() + right.m_pathname.size());
1591 }
1592 
1593 } // namespace detail
1594 
1595 // Note: Because of the range constructor in C++23 std::string_view that involves a check for contiguous_range concept,
1596 //       any non-template function call that requires a check whether the source argument (which may be fs::path)
1597 //       is convertible to std::string_view must be made after fs::path::iterator is defined. This includes overload
1598 //       resolution and SFINAE checks. Otherwise, the concept check result formally changes between fs::path::iterator
1599 //       is not defined and defined, which causes compilation errors with gcc 11 and later.
1600 //       https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106808
1601 
1602 BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const value_type* source, const value_type* source_end, const codecvt_type*) const
1603 {
1604     path src;
1605     src.m_pathname.assign(source, source_end);
1606     return m_self.compare(src);
1607 }
1608 
1609 template< typename OtherChar >
1610 BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt) const
1611 {
1612     path src;
1613     detail::path_traits::convert(source, source_end, src.m_pathname, cvt);
1614     return m_self.compare(src);
1615 }
1616 
1617 inline path& path::operator=(path const& p)
1618 {
1619     return assign(p);
1620 }
1621 
1622 inline path& path::operator+=(path const& p)
1623 {
1624     return concat(p);
1625 }
1626 
1627 BOOST_FORCEINLINE path& path::operator/=(path const& p)
1628 {
1629     return append(p);
1630 }
1631 
1632 #if !defined(BOOST_WINDOWS_API)
1633 inline path path::generic_path() const
1634 {
1635     return path(*this);
1636 }
1637 #endif
1638 
1639 inline path path::lexically_proximate(path const& base) const
1640 {
1641     path tmp(lexically_relative(base));
1642     return tmp.empty() ? *this : tmp;
1643 }
1644 
1645 inline path::reverse_iterator path::rbegin() const
1646 {
1647     return reverse_iterator(end());
1648 }
1649 
1650 inline path::reverse_iterator path::rend() const
1651 {
1652     return reverse_iterator(begin());
1653 }
1654 
1655 inline bool path::filename_is_dot() const
1656 {
1657     // implicit dot is tricky, so actually call filename(); see path::filename() example
1658     // in reference.html
1659     path p(filename());
1660     return p.size() == 1 && *p.c_str() == dot;
1661 }
1662 
1663 inline bool path::filename_is_dot_dot() const
1664 {
1665     return size() >= 2 && m_pathname[size() - 1] == dot && m_pathname[size() - 2] == dot && (m_pathname.size() == 2 || detail::is_element_separator(m_pathname[size() - 3]));
1666     // use detail::is_element_separator() rather than detail::is_directory_separator
1667     // to deal with "c:.." edge case on Windows when ':' acts as a separator
1668 }
1669 
1670 #if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
1671 
1672 BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::lexically_normal() instead")
1673 BOOST_FORCEINLINE path& path::normalize()
1674 {
1675     path tmp(lexically_normal());
1676     m_pathname.swap(tmp.m_pathname);
1677     return *this;
1678 }
1679 
1680 #endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
1681 
1682 // The following functions are defined differently, depending on Boost.Filesystem version in use.
1683 // To avoid ODR violation, these functions are not defined when the library itself is built.
1684 // This makes sure they are not compiled when the library is built, and the only version there is
1685 // is the one in user's code. Users are supposed to consistently use the same Boost.Filesystem version
1686 // in all their translation units.
1687 #if !defined(BOOST_FILESYSTEM_SOURCE)
1688 
1689 BOOST_FORCEINLINE path& path::append(path const& p)
1690 {
1691     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size());
1692     return *this;
1693 }
1694 
1695 BOOST_FORCEINLINE path& path::append(path const& p, codecvt_type const&)
1696 {
1697     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size());
1698     return *this;
1699 }
1700 
1701 BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end)
1702 {
1703     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end);
1704     return *this;
1705 }
1706 
1707 BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end, codecvt_type const&)
1708 {
1709     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end);
1710     return *this;
1711 }
1712 
1713 BOOST_FORCEINLINE path& path::remove_filename()
1714 {
1715     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::remove_filename)(*this);
1716     return *this;
1717 }
1718 
1719 BOOST_FORCEINLINE path& path::replace_extension(path const& new_extension)
1720 {
1721     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::replace_extension)(*this, new_extension);
1722     return *this;
1723 }
1724 
1725 BOOST_FORCEINLINE int path::compare(path const& p) const
1726 {
1727     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::compare)(*this, p);
1728 }
1729 
1730 BOOST_FORCEINLINE path path::filename() const
1731 {
1732     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::filename)(*this);
1733 }
1734 
1735 BOOST_FORCEINLINE path path::stem() const
1736 {
1737     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::stem)(*this);
1738 }
1739 
1740 BOOST_FORCEINLINE path path::extension() const
1741 {
1742     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::extension)(*this);
1743 }
1744 
1745 BOOST_FORCEINLINE bool path::has_filename() const
1746 {
1747     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::has_filename)(*this);
1748 }
1749 
1750 BOOST_FORCEINLINE path path::lexically_normal() const
1751 {
1752     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lexically_normal)(*this);
1753 }
1754 
1755 namespace path_detail {
1756 
1757 BOOST_FORCEINLINE void path_iterator::increment()
1758 {
1759     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::increment)(*this);
1760 }
1761 
1762 BOOST_FORCEINLINE void path_iterator::decrement()
1763 {
1764     BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::decrement)(*this);
1765 }
1766 
1767 BOOST_FORCEINLINE bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2)
1768 {
1769     return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lex_compare)(first1, last1, first2, last2) < 0;
1770 }
1771 
1772 } // namespace path_detail
1773 
1774 #endif // !defined(BOOST_FILESYSTEM_SOURCE)
1775 
1776 //--------------------------------------------------------------------------------------//
1777 //                     class path member template specializations                       //
1778 //--------------------------------------------------------------------------------------//
1779 
1780 template< >
1781 inline std::string path::string< std::string >() const
1782 {
1783     return string();
1784 }
1785 
1786 template< >
1787 inline std::wstring path::string< std::wstring >() const
1788 {
1789     return wstring();
1790 }
1791 
1792 template< >
1793 inline std::string path::string< std::string >(codecvt_type const& cvt) const
1794 {
1795     return string(cvt);
1796 }
1797 
1798 template< >
1799 inline std::wstring path::string< std::wstring >(codecvt_type const& cvt) const
1800 {
1801     return wstring(cvt);
1802 }
1803 
1804 template< >
1805 inline std::string path::generic_string< std::string >() const
1806 {
1807     return generic_string();
1808 }
1809 
1810 template< >
1811 inline std::wstring path::generic_string< std::wstring >() const
1812 {
1813     return generic_wstring();
1814 }
1815 
1816 template< >
1817 inline std::string path::generic_string< std::string >(codecvt_type const& cvt) const
1818 {
1819     return generic_string(cvt);
1820 }
1821 
1822 template< >
1823 inline std::wstring path::generic_string< std::wstring >(codecvt_type const& cvt) const
1824 {
1825     return generic_wstring(cvt);
1826 }
1827 
1828 } // namespace filesystem
1829 } // namespace boost
1830 
1831 //----------------------------------------------------------------------------//
1832 
1833 #include <boost/filesystem/detail/footer.hpp>
1834 
1835 #endif // BOOST_FILESYSTEM_PATH_HPP