Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:29:16

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