Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:47

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___FILESYSTEM_PATH_H
0011 #define _LIBCPP___FILESYSTEM_PATH_H
0012 
0013 #include <__algorithm/replace.h>
0014 #include <__algorithm/replace_copy.h>
0015 #include <__config>
0016 #include <__functional/unary_function.h>
0017 #include <__fwd/functional.h>
0018 #include <__iterator/back_insert_iterator.h>
0019 #include <__iterator/iterator_traits.h>
0020 #include <__type_traits/decay.h>
0021 #include <__type_traits/is_pointer.h>
0022 #include <__type_traits/remove_const.h>
0023 #include <__type_traits/remove_pointer.h>
0024 #include <__utility/move.h>
0025 #include <string>
0026 #include <string_view>
0027 
0028 #if _LIBCPP_HAS_LOCALIZATION
0029 #  include <iomanip> // for quoted
0030 #  include <locale>
0031 #endif
0032 
0033 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0034 #  pragma GCC system_header
0035 #endif
0036 
0037 _LIBCPP_PUSH_MACROS
0038 #include <__undef_macros>
0039 
0040 #if _LIBCPP_STD_VER >= 17
0041 
0042 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
0043 
0044 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
0045 
0046 template <class _Tp>
0047 struct __can_convert_char {
0048   static const bool value = false;
0049 };
0050 template <class _Tp>
0051 struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
0052 template <>
0053 struct __can_convert_char<char> {
0054   static const bool value           = true;
0055   using __char_type _LIBCPP_NODEBUG = char;
0056 };
0057 template <>
0058 struct __can_convert_char<wchar_t> {
0059   static const bool value           = true;
0060   using __char_type _LIBCPP_NODEBUG = wchar_t;
0061 };
0062 #  if _LIBCPP_HAS_CHAR8_T
0063 template <>
0064 struct __can_convert_char<char8_t> {
0065   static const bool value           = true;
0066   using __char_type _LIBCPP_NODEBUG = char8_t;
0067 };
0068 #  endif
0069 template <>
0070 struct __can_convert_char<char16_t> {
0071   static const bool value           = true;
0072   using __char_type _LIBCPP_NODEBUG = char16_t;
0073 };
0074 template <>
0075 struct __can_convert_char<char32_t> {
0076   static const bool value           = true;
0077   using __char_type _LIBCPP_NODEBUG = char32_t;
0078 };
0079 
0080 template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
0081 _LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {
0082 #  if defined(_LIBCPP_WIN32API)
0083   return __e == _ECharT('/') || __e == _ECharT('\\');
0084 #  else
0085   return __e == _ECharT('/');
0086 #  endif
0087 }
0088 
0089 #  if _LIBCPP_HAS_CHAR8_T
0090 typedef u8string __u8_string;
0091 #  else
0092 typedef string __u8_string;
0093 #  endif
0094 
0095 struct _NullSentinel {};
0096 
0097 template <class _Tp>
0098 using _Void _LIBCPP_NODEBUG = void;
0099 
0100 template <class _Tp, class = void>
0101 struct __is_pathable_string : public false_type {};
0102 
0103 template <class _ECharT, class _Traits, class _Alloc>
0104 struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>,
0105                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
0106     : public __can_convert_char<_ECharT> {
0107   using _Str _LIBCPP_NODEBUG = basic_string<_ECharT, _Traits, _Alloc>;
0108 
0109   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
0110 
0111   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
0112 
0113   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
0114 };
0115 
0116 template <class _ECharT, class _Traits>
0117 struct __is_pathable_string< basic_string_view<_ECharT, _Traits>,
0118                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
0119     : public __can_convert_char<_ECharT> {
0120   using _Str _LIBCPP_NODEBUG = basic_string_view<_ECharT, _Traits>;
0121 
0122   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
0123 
0124   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
0125 
0126   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
0127 };
0128 
0129 template <class _Source,
0130           class _DS            = __decay_t<_Source>,
0131           class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
0132           bool _IsCharPtr      = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
0133 struct __is_pathable_char_array : false_type {};
0134 
0135 template <class _Source, class _ECharT, class _UPtr>
0136 struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> : __can_convert_char<__remove_const_t<_ECharT> > {
0137   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
0138 
0139   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {
0140     using _Iter              = const _ECharT*;
0141     const _ECharT __sentinel = _ECharT{};
0142     _Iter __e                = __b;
0143     for (; *__e != __sentinel; ++__e)
0144       ;
0145     return __e;
0146   }
0147 
0148   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
0149 };
0150 
0151 template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
0152 struct __is_pathable_iter : false_type {};
0153 
0154 template <class _Iter>
0155 struct __is_pathable_iter<
0156     _Iter,
0157     true,
0158     _Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >
0159     : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
0160   using _ECharT _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type;
0161 
0162   _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }
0163 
0164   _LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
0165 
0166   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }
0167 };
0168 
0169 template <class _Tp,
0170           bool _IsStringT   = __is_pathable_string<_Tp>::value,
0171           bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
0172           bool _IsIterT     = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
0173 struct __is_pathable : false_type {
0174   static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
0175 };
0176 
0177 template <class _Tp>
0178 struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
0179 
0180 template <class _Tp>
0181 struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
0182 
0183 template <class _Tp>
0184 struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
0185 
0186 #  if defined(_LIBCPP_WIN32API)
0187 typedef wstring __path_string;
0188 typedef wchar_t __path_value;
0189 #  else
0190 typedef string __path_string;
0191 typedef char __path_value;
0192 #  endif
0193 
0194 #  if defined(_LIBCPP_WIN32API)
0195 _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
0196 _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
0197 #  endif
0198 
0199 template <class _ECharT>
0200 struct _PathCVT;
0201 
0202 #  if _LIBCPP_HAS_LOCALIZATION
0203 template <class _ECharT>
0204 struct _PathCVT {
0205   static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
0206 
0207   typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
0208 #    if defined(_LIBCPP_WIN32API)
0209   typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
0210 #    endif
0211 
0212   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {
0213 #    if defined(_LIBCPP_WIN32API)
0214     string __utf8;
0215     _Narrower()(back_inserter(__utf8), __b, __e);
0216     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
0217 #    else
0218     _Narrower()(back_inserter(__dest), __b, __e);
0219 #    endif
0220   }
0221 
0222   template <class _Iter>
0223   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
0224     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
0225     if (__b == __e)
0226       return;
0227     basic_string<_ECharT> __tmp(__b, __e);
0228 #    if defined(_LIBCPP_WIN32API)
0229     string __utf8;
0230     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
0231     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
0232 #    else
0233     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
0234 #    endif
0235   }
0236 
0237   template <class _Iter>
0238   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
0239     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
0240     const _ECharT __sentinel = _ECharT{};
0241     if (*__b == __sentinel)
0242       return;
0243     basic_string<_ECharT> __tmp;
0244     for (; *__b != __sentinel; ++__b)
0245       __tmp.push_back(*__b);
0246 #    if defined(_LIBCPP_WIN32API)
0247     string __utf8;
0248     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
0249     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
0250 #    else
0251     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
0252 #    endif
0253   }
0254 
0255   template <class _Source>
0256   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
0257     using _Traits = __is_pathable<_Source>;
0258     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
0259   }
0260 };
0261 #  endif // _LIBCPP_HAS_LOCALIZATION
0262 
0263 template <>
0264 struct _PathCVT<__path_value> {
0265   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
0266   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
0267     for (; __b != __e; ++__b)
0268       __dest.push_back(*__b);
0269   }
0270 
0271   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
0272   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
0273     __dest.append(__b, __e);
0274   }
0275 
0276   template <class _Iter>
0277   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
0278     const char __sentinel = char{};
0279     for (; *__b != __sentinel; ++__b)
0280       __dest.push_back(*__b);
0281   }
0282 
0283   template <class _Source>
0284   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
0285     using _Traits = __is_pathable<_Source>;
0286     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
0287   }
0288 };
0289 
0290 #  if defined(_LIBCPP_WIN32API)
0291 template <>
0292 struct _PathCVT<char> {
0293   _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
0294     size_t __size = __char_to_wide(__str, nullptr, 0);
0295     size_t __pos  = __dest.size();
0296     __dest.resize(__pos + __size);
0297     __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
0298   }
0299 
0300   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
0301   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
0302     basic_string<char> __tmp(__b, __e);
0303     __append_string(__dest, __tmp);
0304   }
0305 
0306   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
0307   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
0308     basic_string<char> __tmp(__b, __e);
0309     __append_string(__dest, __tmp);
0310   }
0311 
0312   template <class _Iter>
0313   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
0314     const char __sentinel = char{};
0315     basic_string<char> __tmp;
0316     for (; *__b != __sentinel; ++__b)
0317       __tmp.push_back(*__b);
0318     __append_string(__dest, __tmp);
0319   }
0320 
0321   template <class _Source>
0322   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
0323     using _Traits = __is_pathable<_Source>;
0324     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
0325   }
0326 };
0327 
0328 template <class _ECharT>
0329 struct _PathExport {
0330   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
0331   typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
0332 
0333   template <class _Str>
0334   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
0335     string __utf8;
0336     _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
0337     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
0338   }
0339 };
0340 
0341 template <>
0342 struct _PathExport<char> {
0343   template <class _Str>
0344   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
0345     size_t __size = __wide_to_char(__src, nullptr, 0);
0346     size_t __pos  = __dest.size();
0347     __dest.resize(__size);
0348     __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
0349   }
0350 };
0351 
0352 template <>
0353 struct _PathExport<wchar_t> {
0354   template <class _Str>
0355   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
0356     __dest.append(__src.begin(), __src.end());
0357   }
0358 };
0359 
0360 template <>
0361 struct _PathExport<char16_t> {
0362   template <class _Str>
0363   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
0364     __dest.append(__src.begin(), __src.end());
0365   }
0366 };
0367 
0368 #    if _LIBCPP_HAS_CHAR8_T
0369 template <>
0370 struct _PathExport<char8_t> {
0371   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
0372 
0373   template <class _Str>
0374   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
0375     _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
0376   }
0377 };
0378 #    endif // _LIBCPP_HAS_CHAR8_T
0379 #  endif   /* _LIBCPP_WIN32API */
0380 
0381 class _LIBCPP_EXPORTED_FROM_ABI path {
0382   template <class _SourceOrIter, class _Tp = path&>
0383   using _EnableIfPathable _LIBCPP_NODEBUG = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;
0384 
0385   template <class _Tp>
0386   using _SourceChar _LIBCPP_NODEBUG = typename __is_pathable<_Tp>::__char_type;
0387 
0388   template <class _Tp>
0389   using _SourceCVT _LIBCPP_NODEBUG = _PathCVT<_SourceChar<_Tp> >;
0390 
0391 public:
0392 #  if defined(_LIBCPP_WIN32API)
0393   typedef wchar_t value_type;
0394   static constexpr value_type preferred_separator = L'\\';
0395 #  else
0396   typedef char value_type;
0397   static constexpr value_type preferred_separator = '/';
0398 #  endif
0399   typedef basic_string<value_type> string_type;
0400   typedef basic_string_view<value_type> __string_view;
0401 
0402   enum format : unsigned char { auto_format, native_format, generic_format };
0403 
0404   // constructors and destructor
0405   _LIBCPP_HIDE_FROM_ABI path() noexcept {}
0406   _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
0407   _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}
0408 
0409   _LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}
0410 
0411   template <class _Source, class = _EnableIfPathable<_Source, void> >
0412   _LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {
0413     _SourceCVT<_Source>::__append_source(__pn_, __src);
0414   }
0415 
0416   template <class _InputIt>
0417   _LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {
0418     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
0419     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
0420   }
0421 
0422   /*
0423   #if _LIBCPP_HAS_LOCALIZATION
0424     // TODO Implement locale conversions.
0425     template <class _Source, class = _EnableIfPathable<_Source, void> >
0426     path(const _Source& __src, const locale& __loc, format = format::auto_format);
0427     template <class _InputIt>
0428     path(_InputIt __first, _InputIt _last, const locale& __loc,
0429          format = format::auto_format);
0430   #endif
0431   */
0432 
0433   _LIBCPP_HIDE_FROM_ABI ~path() = default;
0434 
0435   // assignments
0436   _LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {
0437     __pn_ = __p.__pn_;
0438     return *this;
0439   }
0440 
0441   _LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {
0442     __pn_ = std::move(__p.__pn_);
0443     return *this;
0444   }
0445 
0446   _LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {
0447     __pn_ = std::move(__s);
0448     return *this;
0449   }
0450 
0451   _LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {
0452     __pn_ = std::move(__s);
0453     return *this;
0454   }
0455 
0456   template <class _Source>
0457   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {
0458     return this->assign(__src);
0459   }
0460 
0461   template <class _Source>
0462   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {
0463     __pn_.clear();
0464     _SourceCVT<_Source>::__append_source(__pn_, __src);
0465     return *this;
0466   }
0467 
0468   template <class _InputIt>
0469   _LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {
0470     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
0471     __pn_.clear();
0472     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
0473     return *this;
0474   }
0475 
0476 public:
0477   // appends
0478 #  if defined(_LIBCPP_WIN32API)
0479   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
0480     auto __p_root_name      = __p.__root_name();
0481     auto __p_root_name_size = __p_root_name.size();
0482     if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
0483       __pn_ = __p.__pn_;
0484       return *this;
0485     }
0486     if (__p.has_root_directory()) {
0487       path __root_name_str = root_name();
0488       __pn_                = __root_name_str.native();
0489       __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
0490       return *this;
0491     }
0492     if (has_filename() || (!has_root_directory() && is_absolute()))
0493       __pn_ += preferred_separator;
0494     __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
0495     return *this;
0496   }
0497   template <class _Source>
0498   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
0499     return operator/=(path(__src));
0500   }
0501 
0502   template <class _Source>
0503   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
0504     return operator/=(path(__src));
0505   }
0506 
0507   template <class _InputIt>
0508   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
0509     return operator/=(path(__first, __last));
0510   }
0511 #  else
0512   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
0513     if (__p.is_absolute()) {
0514       __pn_ = __p.__pn_;
0515       return *this;
0516     }
0517     if (has_filename())
0518       __pn_ += preferred_separator;
0519     __pn_ += __p.native();
0520     return *this;
0521   }
0522 
0523   // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
0524   // is known at compile time to be "/' since the user almost certainly intended
0525   // to append a separator instead of overwriting the path with "/"
0526   template <class _Source>
0527   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
0528     return this->append(__src);
0529   }
0530 
0531   template <class _Source>
0532   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
0533     using _Traits             = __is_pathable<_Source>;
0534     using _CVT                = _PathCVT<_SourceChar<_Source> >;
0535     bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));
0536     if (__source_is_absolute)
0537       __pn_.clear();
0538     else if (has_filename())
0539       __pn_ += preferred_separator;
0540     _CVT::__append_source(__pn_, __src);
0541     return *this;
0542   }
0543 
0544   template <class _InputIt>
0545   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
0546     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
0547     static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
0548     using _CVT = _PathCVT<_ItVal>;
0549     if (__first != __last && filesystem::__is_separator(*__first))
0550       __pn_.clear();
0551     else if (has_filename())
0552       __pn_ += preferred_separator;
0553     _CVT::__append_range(__pn_, __first, __last);
0554     return *this;
0555   }
0556 #  endif
0557 
0558   // concatenation
0559   _LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {
0560     __pn_ += __x.__pn_;
0561     return *this;
0562   }
0563 
0564   _LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {
0565     __pn_ += __x;
0566     return *this;
0567   }
0568 
0569   _LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {
0570     __pn_ += __x;
0571     return *this;
0572   }
0573 
0574   _LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {
0575     __pn_ += __x;
0576     return *this;
0577   }
0578 
0579   _LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {
0580     __pn_ += __x;
0581     return *this;
0582   }
0583 
0584   template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
0585   _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
0586     _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
0587     return *this;
0588   }
0589 
0590   template <class _Source>
0591   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {
0592     return this->concat(__x);
0593   }
0594 
0595   template <class _Source>
0596   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {
0597     _SourceCVT<_Source>::__append_source(__pn_, __x);
0598     return *this;
0599   }
0600 
0601   template <class _InputIt>
0602   _LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {
0603     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
0604     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
0605     return *this;
0606   }
0607 
0608   // modifiers
0609   _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }
0610 
0611   _LIBCPP_HIDE_FROM_ABI path& make_preferred() {
0612 #  if defined(_LIBCPP_WIN32API)
0613     std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
0614 #  endif
0615     return *this;
0616   }
0617 
0618   _LIBCPP_HIDE_FROM_ABI path& remove_filename() {
0619     auto __fname = __filename();
0620     if (!__fname.empty())
0621       __pn_.erase(__fname.data() - __pn_.data());
0622     return *this;
0623   }
0624 
0625   _LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {
0626     remove_filename();
0627     return (*this /= __replacement);
0628   }
0629 
0630   path& replace_extension(const path& __replacement = path());
0631 
0632   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
0633     return __lhs.__compare(__rhs.__pn_) == 0;
0634   }
0635 #  if _LIBCPP_STD_VER <= 17
0636   friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
0637     return __lhs.__compare(__rhs.__pn_) != 0;
0638   }
0639   friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {
0640     return __lhs.__compare(__rhs.__pn_) < 0;
0641   }
0642   friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {
0643     return __lhs.__compare(__rhs.__pn_) <= 0;
0644   }
0645   friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {
0646     return __lhs.__compare(__rhs.__pn_) > 0;
0647   }
0648   friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {
0649     return __lhs.__compare(__rhs.__pn_) >= 0;
0650   }
0651 #  else  // _LIBCPP_STD_VER <= 17
0652   friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
0653     return __lhs.__compare(__rhs.__pn_) <=> 0;
0654   }
0655 #  endif // _LIBCPP_STD_VER <= 17
0656 
0657   friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
0658     path __result(__lhs);
0659     __result /= __rhs;
0660     return __result;
0661   }
0662 
0663   _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
0664 
0665   // private helper to allow reserving memory in the path
0666   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }
0667 
0668   // native format observers
0669   _LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }
0670 
0671   _LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }
0672 
0673   _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
0674 
0675 #  if defined(_LIBCPP_WIN32API)
0676   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }
0677 
0678   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {
0679     std::wstring __s;
0680     __s.resize(__pn_.size());
0681     std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
0682     return __s;
0683   }
0684 
0685 #    if _LIBCPP_HAS_LOCALIZATION
0686   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
0687   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
0688     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
0689     _Str __s(__a);
0690     __s.reserve(__pn_.size());
0691     _PathExport<_ECharT>::__append(__s, __pn_);
0692     return __s;
0693   }
0694 
0695   _LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }
0696   _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
0697     using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
0698     __u8_string __s;
0699     __s.reserve(__pn_.size());
0700     _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
0701     return __s;
0702   }
0703 
0704   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
0705   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
0706 
0707   // generic format observers
0708   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
0709   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
0710   generic_string(const _Allocator& __a = _Allocator()) const {
0711     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
0712     _Str __s   = string<_ECharT, _Traits, _Allocator>(__a);
0713     // Note: This (and generic_u8string below) is slightly suboptimal as
0714     // it iterates twice over the string; once to convert it to the right
0715     // character type, and once to replace path delimiters.
0716     std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
0717     return __s;
0718   }
0719 
0720   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }
0721   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }
0722   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }
0723   _LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {
0724     __u8_string __s = u8string();
0725     std::replace(__s.begin(), __s.end(), '\\', '/');
0726     return __s;
0727   }
0728 #    endif // _LIBCPP_HAS_LOCALIZATION
0729 #  else    /* _LIBCPP_WIN32API */
0730 
0731   _LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }
0732 #    if _LIBCPP_HAS_CHAR8_T
0733   _LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
0734 #    else
0735   _LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }
0736 #    endif
0737 
0738 #    if _LIBCPP_HAS_LOCALIZATION
0739   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
0740   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
0741     using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
0742     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
0743     _Str __s(__a);
0744     __s.reserve(__pn_.size());
0745     _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
0746     return __s;
0747   }
0748 
0749 #      if _LIBCPP_HAS_WIDE_CHARACTERS
0750   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }
0751 #      endif
0752   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
0753   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
0754 #    endif // _LIBCPP_HAS_LOCALIZATION
0755 
0756   // generic format observers
0757   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }
0758 #    if _LIBCPP_HAS_CHAR8_T
0759   _LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
0760 #    else
0761   _LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }
0762 #    endif
0763 
0764 #    if _LIBCPP_HAS_LOCALIZATION
0765   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
0766   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
0767   generic_string(const _Allocator& __a = _Allocator()) const {
0768     return string<_ECharT, _Traits, _Allocator>(__a);
0769   }
0770 
0771 #      if _LIBCPP_HAS_WIDE_CHARACTERS
0772   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }
0773 #      endif
0774   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }
0775   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }
0776 #    endif // _LIBCPP_HAS_LOCALIZATION
0777 #  endif   /* !_LIBCPP_WIN32API */
0778 
0779 private:
0780   int __compare(__string_view) const;
0781   __string_view __root_name() const;
0782   __string_view __root_directory() const;
0783   __string_view __root_path_raw() const;
0784   __string_view __relative_path() const;
0785   __string_view __parent_path() const;
0786   __string_view __filename() const;
0787   __string_view __stem() const;
0788   __string_view __extension() const;
0789 
0790 public:
0791   // compare
0792   _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }
0793   _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }
0794   _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }
0795   _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }
0796 
0797   // decomposition
0798   _LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }
0799   _LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }
0800   _LIBCPP_HIDE_FROM_ABI path root_path() const {
0801 #  if defined(_LIBCPP_WIN32API)
0802     return string_type(__root_path_raw());
0803 #  else
0804     return root_name().append(string_type(__root_directory()));
0805 #  endif
0806   }
0807   _LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }
0808   _LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }
0809   _LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }
0810   _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
0811   _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }
0812 
0813   // query
0814   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }
0815 
0816   _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }
0817   _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }
0818   _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }
0819   _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }
0820   _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }
0821   _LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }
0822   _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
0823   _LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }
0824 
0825   _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
0826 #  if defined(_LIBCPP_WIN32API)
0827     __string_view __root_name_str = __root_name();
0828     __string_view __root_dir      = __root_directory();
0829     if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
0830       // A drive letter with no root directory is relative, e.g. x:example.
0831       return !__root_dir.empty();
0832     }
0833     // If no root name, it's relative, e.g. \example is relative to the current drive
0834     if (__root_name_str.empty())
0835       return false;
0836     if (__root_name_str.size() < 3)
0837       return false;
0838     // A server root name, like \\server, is always absolute
0839     if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
0840       return false;
0841     if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
0842       return false;
0843     // Seems to be a server root name
0844     return true;
0845 #  else
0846     return has_root_directory();
0847 #  endif
0848   }
0849   _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
0850 
0851   // relative paths
0852   path lexically_normal() const;
0853   path lexically_relative(const path& __base) const;
0854 
0855   _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
0856     path __result = this->lexically_relative(__base);
0857     if (__result.native().empty())
0858       return *this;
0859     return __result;
0860   }
0861 
0862   // iterators
0863   class _LIBCPP_EXPORTED_FROM_ABI iterator;
0864   typedef iterator const_iterator;
0865 
0866   iterator begin() const;
0867   iterator end() const;
0868 
0869 #  if _LIBCPP_HAS_LOCALIZATION
0870   template <
0871       class _CharT,
0872       class _Traits,
0873       __enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>
0874   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
0875   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
0876     __os << std::__quoted(__p.native());
0877     return __os;
0878   }
0879 
0880   template <
0881       class _CharT,
0882       class _Traits,
0883       __enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>
0884   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
0885   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
0886     __os << std::__quoted(__p.string<_CharT, _Traits>());
0887     return __os;
0888   }
0889 
0890   template <class _CharT, class _Traits>
0891   _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
0892   operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
0893     basic_string<_CharT, _Traits> __tmp;
0894     __is >> std::__quoted(__tmp);
0895     __p = __tmp;
0896     return __is;
0897   }
0898 #  endif // _LIBCPP_HAS_LOCALIZATION
0899 
0900 private:
0901   inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {
0902     __pn_ = string_type(__s);
0903     return *this;
0904   }
0905   string_type __pn_;
0906 };
0907 
0908 inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
0909 
0910 _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
0911 
0912 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
0913 
0914 _LIBCPP_END_NAMESPACE_FILESYSTEM
0915 
0916 _LIBCPP_BEGIN_NAMESPACE_STD
0917 
0918 template <>
0919 struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {
0920   _LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {
0921     return filesystem::hash_value(__p);
0922   }
0923 };
0924 
0925 _LIBCPP_END_NAMESPACE_STD
0926 
0927 #endif // _LIBCPP_STD_VER >= 17
0928 
0929 _LIBCPP_POP_MACROS
0930 
0931 #endif // _LIBCPP___FILESYSTEM_PATH_H