10eae32dcSDimitry Andric // -*- C++ -*-
20eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
30eae32dcSDimitry Andric //
40eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
60eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70eae32dcSDimitry Andric //
80eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
90eae32dcSDimitry Andric 
100eae32dcSDimitry Andric #ifndef _LIBCPP___FILESYSTEM_PATH_H
110eae32dcSDimitry Andric #define _LIBCPP___FILESYSTEM_PATH_H
120eae32dcSDimitry Andric 
1381ad6265SDimitry Andric #include <__algorithm/replace.h>
1481ad6265SDimitry Andric #include <__algorithm/replace_copy.h>
150eae32dcSDimitry Andric #include <__availability>
160eae32dcSDimitry Andric #include <__config>
1706c3fb27SDimitry Andric #include <__functional/hash.h>
1806c3fb27SDimitry Andric #include <__functional/unary_function.h>
1906c3fb27SDimitry Andric #include <__fwd/hash.h>
200eae32dcSDimitry Andric #include <__iterator/back_insert_iterator.h>
210eae32dcSDimitry Andric #include <__iterator/iterator_traits.h>
2206c3fb27SDimitry Andric #include <__type_traits/decay.h>
2306c3fb27SDimitry Andric #include <__type_traits/is_pointer.h>
2406c3fb27SDimitry Andric #include <__type_traits/remove_const.h>
2506c3fb27SDimitry Andric #include <__type_traits/remove_pointer.h>
260eae32dcSDimitry Andric #include <cstddef>
2704eeddc0SDimitry Andric #include <string>
280eae32dcSDimitry Andric #include <string_view>
290eae32dcSDimitry Andric 
300eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
310eae32dcSDimitry Andric #  include <iomanip> // for quoted
3204eeddc0SDimitry Andric #  include <locale>
330eae32dcSDimitry Andric #endif
340eae32dcSDimitry Andric 
3581ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3681ad6265SDimitry Andric #  pragma GCC system_header
3781ad6265SDimitry Andric #endif
3881ad6265SDimitry Andric 
39*b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
40*b3edf446SDimitry Andric #include <__undef_macros>
41*b3edf446SDimitry Andric 
425f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 17
430eae32dcSDimitry Andric 
440eae32dcSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
450eae32dcSDimitry Andric 
4606c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
470eae32dcSDimitry Andric 
480eae32dcSDimitry Andric template <class _Tp>
490eae32dcSDimitry Andric struct __can_convert_char {
500eae32dcSDimitry Andric   static const bool value = false;
510eae32dcSDimitry Andric };
520eae32dcSDimitry Andric template <class _Tp>
530eae32dcSDimitry Andric struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
540eae32dcSDimitry Andric template <>
550eae32dcSDimitry Andric struct __can_convert_char<char> {
560eae32dcSDimitry Andric   static const bool value = true;
570eae32dcSDimitry Andric   using __char_type       = char;
580eae32dcSDimitry Andric };
590eae32dcSDimitry Andric template <>
600eae32dcSDimitry Andric struct __can_convert_char<wchar_t> {
610eae32dcSDimitry Andric   static const bool value = true;
620eae32dcSDimitry Andric   using __char_type       = wchar_t;
630eae32dcSDimitry Andric };
640eae32dcSDimitry Andric #  ifndef _LIBCPP_HAS_NO_CHAR8_T
650eae32dcSDimitry Andric template <>
660eae32dcSDimitry Andric struct __can_convert_char<char8_t> {
670eae32dcSDimitry Andric   static const bool value = true;
680eae32dcSDimitry Andric   using __char_type       = char8_t;
690eae32dcSDimitry Andric };
700eae32dcSDimitry Andric #  endif
710eae32dcSDimitry Andric template <>
720eae32dcSDimitry Andric struct __can_convert_char<char16_t> {
730eae32dcSDimitry Andric   static const bool value = true;
740eae32dcSDimitry Andric   using __char_type       = char16_t;
750eae32dcSDimitry Andric };
760eae32dcSDimitry Andric template <>
770eae32dcSDimitry Andric struct __can_convert_char<char32_t> {
780eae32dcSDimitry Andric   static const bool value = true;
790eae32dcSDimitry Andric   using __char_type       = char32_t;
800eae32dcSDimitry Andric };
810eae32dcSDimitry Andric 
825f757f3fSDimitry Andric template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
83cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {
840eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
850eae32dcSDimitry Andric   return __e == _ECharT('/') || __e == _ECharT('\\');
860eae32dcSDimitry Andric #  else
870eae32dcSDimitry Andric   return __e == _ECharT('/');
880eae32dcSDimitry Andric #  endif
890eae32dcSDimitry Andric }
900eae32dcSDimitry Andric 
910eae32dcSDimitry Andric #  ifndef _LIBCPP_HAS_NO_CHAR8_T
920eae32dcSDimitry Andric typedef u8string __u8_string;
930eae32dcSDimitry Andric #  else
940eae32dcSDimitry Andric typedef string __u8_string;
950eae32dcSDimitry Andric #  endif
960eae32dcSDimitry Andric 
970eae32dcSDimitry Andric struct _NullSentinel {};
980eae32dcSDimitry Andric 
990eae32dcSDimitry Andric template <class _Tp>
1000eae32dcSDimitry Andric using _Void = void;
1010eae32dcSDimitry Andric 
1020eae32dcSDimitry Andric template <class _Tp, class = void>
1030eae32dcSDimitry Andric struct __is_pathable_string : public false_type {};
1040eae32dcSDimitry Andric 
1050eae32dcSDimitry Andric template <class _ECharT, class _Traits, class _Alloc>
106cb14a3feSDimitry Andric struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>,
1070eae32dcSDimitry Andric                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
1080eae32dcSDimitry Andric     : public __can_convert_char<_ECharT> {
1090eae32dcSDimitry Andric   using _Str = basic_string<_ECharT, _Traits, _Alloc>;
11081ad6265SDimitry Andric 
111cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
11281ad6265SDimitry Andric 
113cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
11481ad6265SDimitry Andric 
115cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
1160eae32dcSDimitry Andric };
1170eae32dcSDimitry Andric 
1180eae32dcSDimitry Andric template <class _ECharT, class _Traits>
119cb14a3feSDimitry Andric struct __is_pathable_string< basic_string_view<_ECharT, _Traits>,
1200eae32dcSDimitry Andric                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
1210eae32dcSDimitry Andric     : public __can_convert_char<_ECharT> {
1220eae32dcSDimitry Andric   using _Str = basic_string_view<_ECharT, _Traits>;
12381ad6265SDimitry Andric 
124cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
12581ad6265SDimitry Andric 
126cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
12781ad6265SDimitry Andric 
128cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
1290eae32dcSDimitry Andric };
1300eae32dcSDimitry Andric 
131cb14a3feSDimitry Andric template <class _Source,
132cb14a3feSDimitry Andric           class _DS            = __decay_t<_Source>,
133cb14a3feSDimitry Andric           class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
134cb14a3feSDimitry Andric           bool _IsCharPtr      = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
1350eae32dcSDimitry Andric struct __is_pathable_char_array : false_type {};
1360eae32dcSDimitry Andric 
1370eae32dcSDimitry Andric template <class _Source, class _ECharT, class _UPtr>
138cb14a3feSDimitry Andric struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> : __can_convert_char<__remove_const_t<_ECharT> > {
139cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
14081ad6265SDimitry Andric 
141cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {
1420eae32dcSDimitry Andric     using _Iter              = const _ECharT*;
1430eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
1440eae32dcSDimitry Andric     _Iter __e                = __b;
1450eae32dcSDimitry Andric     for (; *__e != __sentinel; ++__e)
1460eae32dcSDimitry Andric       ;
1470eae32dcSDimitry Andric     return __e;
1480eae32dcSDimitry Andric   }
1490eae32dcSDimitry Andric 
150cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
1510eae32dcSDimitry Andric };
1520eae32dcSDimitry Andric 
153cb14a3feSDimitry Andric template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
1540eae32dcSDimitry Andric struct __is_pathable_iter : false_type {};
1550eae32dcSDimitry Andric 
1560eae32dcSDimitry Andric template <class _Iter>
1570eae32dcSDimitry Andric struct __is_pathable_iter<
158cb14a3feSDimitry Andric     _Iter,
159cb14a3feSDimitry Andric     true,
160cb14a3feSDimitry Andric     _Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >
1610eae32dcSDimitry Andric     : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
1620eae32dcSDimitry Andric   using _ECharT = typename iterator_traits<_Iter>::value_type;
1630eae32dcSDimitry Andric 
164cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }
16581ad6265SDimitry Andric 
166cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
1670eae32dcSDimitry Andric 
168cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }
1690eae32dcSDimitry Andric };
1700eae32dcSDimitry Andric 
171cb14a3feSDimitry Andric template <class _Tp,
172cb14a3feSDimitry Andric           bool _IsStringT   = __is_pathable_string<_Tp>::value,
1730eae32dcSDimitry Andric           bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
1740eae32dcSDimitry Andric           bool _IsIterT     = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
1750eae32dcSDimitry Andric struct __is_pathable : false_type {
1760eae32dcSDimitry Andric   static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
1770eae32dcSDimitry Andric };
1780eae32dcSDimitry Andric 
1790eae32dcSDimitry Andric template <class _Tp>
1800eae32dcSDimitry Andric struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
1810eae32dcSDimitry Andric 
1820eae32dcSDimitry Andric template <class _Tp>
183cb14a3feSDimitry Andric struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
1840eae32dcSDimitry Andric 
1850eae32dcSDimitry Andric template <class _Tp>
1860eae32dcSDimitry Andric struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
1870eae32dcSDimitry Andric 
1880eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
1890eae32dcSDimitry Andric typedef wstring __path_string;
1900eae32dcSDimitry Andric typedef wchar_t __path_value;
1910eae32dcSDimitry Andric #  else
1920eae32dcSDimitry Andric typedef string __path_string;
1930eae32dcSDimitry Andric typedef char __path_value;
1940eae32dcSDimitry Andric #  endif
1950eae32dcSDimitry Andric 
1960eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
19706c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
19806c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
1990eae32dcSDimitry Andric #  endif
2000eae32dcSDimitry Andric 
2010eae32dcSDimitry Andric template <class _ECharT>
2020eae32dcSDimitry Andric struct _PathCVT;
2030eae32dcSDimitry Andric 
2040eae32dcSDimitry Andric #  if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
2050eae32dcSDimitry Andric template <class _ECharT>
2060eae32dcSDimitry Andric struct _PathCVT {
207cb14a3feSDimitry Andric   static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
2080eae32dcSDimitry Andric 
2090eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
2100eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2110eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
2120eae32dcSDimitry Andric #    endif
2130eae32dcSDimitry Andric 
214cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {
2150eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2160eae32dcSDimitry Andric     string __utf8;
2170eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __b, __e);
2180eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2190eae32dcSDimitry Andric #    else
2200eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __b, __e);
2210eae32dcSDimitry Andric #    endif
2220eae32dcSDimitry Andric   }
2230eae32dcSDimitry Andric 
2240eae32dcSDimitry Andric   template <class _Iter>
225cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2260eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2270eae32dcSDimitry Andric     if (__b == __e)
2280eae32dcSDimitry Andric       return;
2290eae32dcSDimitry Andric     basic_string<_ECharT> __tmp(__b, __e);
2300eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2310eae32dcSDimitry Andric     string __utf8;
232cb14a3feSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
2330eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2340eae32dcSDimitry Andric #    else
235cb14a3feSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
2360eae32dcSDimitry Andric #    endif
2370eae32dcSDimitry Andric   }
2380eae32dcSDimitry Andric 
2390eae32dcSDimitry Andric   template <class _Iter>
240cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
2410eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2420eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
2430eae32dcSDimitry Andric     if (*__b == __sentinel)
2440eae32dcSDimitry Andric       return;
2450eae32dcSDimitry Andric     basic_string<_ECharT> __tmp;
2460eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
2470eae32dcSDimitry Andric       __tmp.push_back(*__b);
2480eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2490eae32dcSDimitry Andric     string __utf8;
250cb14a3feSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
2510eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2520eae32dcSDimitry Andric #    else
253cb14a3feSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
2540eae32dcSDimitry Andric #    endif
2550eae32dcSDimitry Andric   }
2560eae32dcSDimitry Andric 
2570eae32dcSDimitry Andric   template <class _Source>
258cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
2590eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
260cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
2610eae32dcSDimitry Andric   }
2620eae32dcSDimitry Andric };
2630eae32dcSDimitry Andric #  endif // !_LIBCPP_HAS_NO_LOCALIZATION
2640eae32dcSDimitry Andric 
2650eae32dcSDimitry Andric template <>
2660eae32dcSDimitry Andric struct _PathCVT<__path_value> {
2675f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
268cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2690eae32dcSDimitry Andric     for (; __b != __e; ++__b)
2700eae32dcSDimitry Andric       __dest.push_back(*__b);
2710eae32dcSDimitry Andric   }
2720eae32dcSDimitry Andric 
2735f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
274cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2750eae32dcSDimitry Andric     __dest.append(__b, __e);
2760eae32dcSDimitry Andric   }
2770eae32dcSDimitry Andric 
2780eae32dcSDimitry Andric   template <class _Iter>
279cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
2800eae32dcSDimitry Andric     const char __sentinel = char{};
2810eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
2820eae32dcSDimitry Andric       __dest.push_back(*__b);
2830eae32dcSDimitry Andric   }
2840eae32dcSDimitry Andric 
2850eae32dcSDimitry Andric   template <class _Source>
286cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
2870eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
288cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
2890eae32dcSDimitry Andric   }
2900eae32dcSDimitry Andric };
2910eae32dcSDimitry Andric 
2920eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
2930eae32dcSDimitry Andric template <>
2940eae32dcSDimitry Andric struct _PathCVT<char> {
295cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
2960eae32dcSDimitry Andric     size_t __size = __char_to_wide(__str, nullptr, 0);
2970eae32dcSDimitry Andric     size_t __pos  = __dest.size();
2980eae32dcSDimitry Andric     __dest.resize(__pos + __size);
2990eae32dcSDimitry Andric     __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
3000eae32dcSDimitry Andric   }
3010eae32dcSDimitry Andric 
3025f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
303cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3040eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3050eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3060eae32dcSDimitry Andric   }
3070eae32dcSDimitry Andric 
3085f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
309cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3100eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3110eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3120eae32dcSDimitry Andric   }
3130eae32dcSDimitry Andric 
3140eae32dcSDimitry Andric   template <class _Iter>
315cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
3160eae32dcSDimitry Andric     const char __sentinel = char{};
3170eae32dcSDimitry Andric     basic_string<char> __tmp;
3180eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
3190eae32dcSDimitry Andric       __tmp.push_back(*__b);
3200eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3210eae32dcSDimitry Andric   }
3220eae32dcSDimitry Andric 
3230eae32dcSDimitry Andric   template <class _Source>
324cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
3250eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
326cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
3270eae32dcSDimitry Andric   }
3280eae32dcSDimitry Andric };
3290eae32dcSDimitry Andric 
3300eae32dcSDimitry Andric template <class _ECharT>
3310eae32dcSDimitry Andric struct _PathExport {
3320eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
3330eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
3340eae32dcSDimitry Andric 
3350eae32dcSDimitry Andric   template <class _Str>
336cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3370eae32dcSDimitry Andric     string __utf8;
3380eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
3390eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
3400eae32dcSDimitry Andric   }
3410eae32dcSDimitry Andric };
3420eae32dcSDimitry Andric 
3430eae32dcSDimitry Andric template <>
3440eae32dcSDimitry Andric struct _PathExport<char> {
3450eae32dcSDimitry Andric   template <class _Str>
346cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3470eae32dcSDimitry Andric     size_t __size = __wide_to_char(__src, nullptr, 0);
3480eae32dcSDimitry Andric     size_t __pos  = __dest.size();
3490eae32dcSDimitry Andric     __dest.resize(__size);
3500eae32dcSDimitry Andric     __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
3510eae32dcSDimitry Andric   }
3520eae32dcSDimitry Andric };
3530eae32dcSDimitry Andric 
3540eae32dcSDimitry Andric template <>
3550eae32dcSDimitry Andric struct _PathExport<wchar_t> {
3560eae32dcSDimitry Andric   template <class _Str>
357cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3580eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
3590eae32dcSDimitry Andric   }
3600eae32dcSDimitry Andric };
3610eae32dcSDimitry Andric 
3620eae32dcSDimitry Andric template <>
3630eae32dcSDimitry Andric struct _PathExport<char16_t> {
3640eae32dcSDimitry Andric   template <class _Str>
365cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3660eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
3670eae32dcSDimitry Andric   }
3680eae32dcSDimitry Andric };
3690eae32dcSDimitry Andric 
3700eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
3710eae32dcSDimitry Andric template <>
3720eae32dcSDimitry Andric struct _PathExport<char8_t> {
3730eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
3740eae32dcSDimitry Andric 
3750eae32dcSDimitry Andric   template <class _Str>
376cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3770eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
3780eae32dcSDimitry Andric   }
3790eae32dcSDimitry Andric };
3800eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_CHAR8_T */
3810eae32dcSDimitry Andric #  endif   /* _LIBCPP_WIN32API */
3820eae32dcSDimitry Andric 
38306c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI path {
3840eae32dcSDimitry Andric   template <class _SourceOrIter, class _Tp = path&>
3855f757f3fSDimitry Andric   using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;
3860eae32dcSDimitry Andric 
3870eae32dcSDimitry Andric   template <class _Tp>
3880eae32dcSDimitry Andric   using _SourceChar = typename __is_pathable<_Tp>::__char_type;
3890eae32dcSDimitry Andric 
3900eae32dcSDimitry Andric   template <class _Tp>
3910eae32dcSDimitry Andric   using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
3920eae32dcSDimitry Andric 
3930eae32dcSDimitry Andric public:
3940eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
3950eae32dcSDimitry Andric   typedef wchar_t value_type;
3960eae32dcSDimitry Andric   static constexpr value_type preferred_separator = L'\\';
3970eae32dcSDimitry Andric #  else
3980eae32dcSDimitry Andric   typedef char value_type;
3990eae32dcSDimitry Andric   static constexpr value_type preferred_separator = '/';
4000eae32dcSDimitry Andric #  endif
4010eae32dcSDimitry Andric   typedef basic_string<value_type> string_type;
4020eae32dcSDimitry Andric   typedef basic_string_view<value_type> __string_view;
4030eae32dcSDimitry Andric 
404cb14a3feSDimitry Andric   enum format : unsigned char { auto_format, native_format, generic_format };
4050eae32dcSDimitry Andric 
4060eae32dcSDimitry Andric   // constructors and destructor
40781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path() noexcept {}
40881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
409cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}
4100eae32dcSDimitry Andric 
411cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}
4120eae32dcSDimitry Andric 
4130eae32dcSDimitry Andric   template <class _Source, class = _EnableIfPathable<_Source, void> >
414cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {
4150eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
4160eae32dcSDimitry Andric   }
4170eae32dcSDimitry Andric 
4180eae32dcSDimitry Andric   template <class _InputIt>
419cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {
4200eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
4210eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
4220eae32dcSDimitry Andric   }
4230eae32dcSDimitry Andric 
4240eae32dcSDimitry Andric   /*
4250eae32dcSDimitry Andric   #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
4260eae32dcSDimitry Andric     // TODO Implement locale conversions.
4270eae32dcSDimitry Andric     template <class _Source, class = _EnableIfPathable<_Source, void> >
4280eae32dcSDimitry Andric     path(const _Source& __src, const locale& __loc, format = format::auto_format);
4290eae32dcSDimitry Andric     template <class _InputIt>
4300eae32dcSDimitry Andric     path(_InputIt __first, _InputIt _last, const locale& __loc,
4310eae32dcSDimitry Andric          format = format::auto_format);
4320eae32dcSDimitry Andric   #endif
4330eae32dcSDimitry Andric   */
4340eae32dcSDimitry Andric 
435cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI ~path() = default;
4360eae32dcSDimitry Andric 
4370eae32dcSDimitry Andric   // assignments
438cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {
4390eae32dcSDimitry Andric     __pn_ = __p.__pn_;
4400eae32dcSDimitry Andric     return *this;
4410eae32dcSDimitry Andric   }
4420eae32dcSDimitry Andric 
443cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {
4445f757f3fSDimitry Andric     __pn_ = std::move(__p.__pn_);
4450eae32dcSDimitry Andric     return *this;
4460eae32dcSDimitry Andric   }
4470eae32dcSDimitry Andric 
448cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {
4495f757f3fSDimitry Andric     __pn_ = std::move(__s);
4500eae32dcSDimitry Andric     return *this;
4510eae32dcSDimitry Andric   }
4520eae32dcSDimitry Andric 
453cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {
4545f757f3fSDimitry Andric     __pn_ = std::move(__s);
4550eae32dcSDimitry Andric     return *this;
4560eae32dcSDimitry Andric   }
4570eae32dcSDimitry Andric 
4580eae32dcSDimitry Andric   template <class _Source>
459cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {
4600eae32dcSDimitry Andric     return this->assign(__src);
4610eae32dcSDimitry Andric   }
4620eae32dcSDimitry Andric 
4630eae32dcSDimitry Andric   template <class _Source>
464cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {
4650eae32dcSDimitry Andric     __pn_.clear();
4660eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
4670eae32dcSDimitry Andric     return *this;
4680eae32dcSDimitry Andric   }
4690eae32dcSDimitry Andric 
4700eae32dcSDimitry Andric   template <class _InputIt>
471cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {
4720eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
4730eae32dcSDimitry Andric     __pn_.clear();
4740eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
4750eae32dcSDimitry Andric     return *this;
4760eae32dcSDimitry Andric   }
4770eae32dcSDimitry Andric 
4780eae32dcSDimitry Andric public:
4790eae32dcSDimitry Andric   // appends
4800eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
481cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
4820eae32dcSDimitry Andric     auto __p_root_name      = __p.__root_name();
4830eae32dcSDimitry Andric     auto __p_root_name_size = __p_root_name.size();
484cb14a3feSDimitry Andric     if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
4850eae32dcSDimitry Andric       __pn_ = __p.__pn_;
4860eae32dcSDimitry Andric       return *this;
4870eae32dcSDimitry Andric     }
4880eae32dcSDimitry Andric     if (__p.has_root_directory()) {
4890eae32dcSDimitry Andric       path __root_name_str = root_name();
4900eae32dcSDimitry Andric       __pn_                = __root_name_str.native();
4910eae32dcSDimitry Andric       __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
4920eae32dcSDimitry Andric       return *this;
4930eae32dcSDimitry Andric     }
4940eae32dcSDimitry Andric     if (has_filename() || (!has_root_directory() && is_absolute()))
4950eae32dcSDimitry Andric       __pn_ += preferred_separator;
4960eae32dcSDimitry Andric     __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
4970eae32dcSDimitry Andric     return *this;
4980eae32dcSDimitry Andric   }
4990eae32dcSDimitry Andric   template <class _Source>
500cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
5010eae32dcSDimitry Andric     return operator/=(path(__src));
5020eae32dcSDimitry Andric   }
5030eae32dcSDimitry Andric 
5040eae32dcSDimitry Andric   template <class _Source>
505cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
5060eae32dcSDimitry Andric     return operator/=(path(__src));
5070eae32dcSDimitry Andric   }
5080eae32dcSDimitry Andric 
5090eae32dcSDimitry Andric   template <class _InputIt>
510cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
5110eae32dcSDimitry Andric     return operator/=(path(__first, __last));
5120eae32dcSDimitry Andric   }
5130eae32dcSDimitry Andric #  else
514cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
5150eae32dcSDimitry Andric     if (__p.is_absolute()) {
5160eae32dcSDimitry Andric       __pn_ = __p.__pn_;
5170eae32dcSDimitry Andric       return *this;
5180eae32dcSDimitry Andric     }
5190eae32dcSDimitry Andric     if (has_filename())
5200eae32dcSDimitry Andric       __pn_ += preferred_separator;
5210eae32dcSDimitry Andric     __pn_ += __p.native();
5220eae32dcSDimitry Andric     return *this;
5230eae32dcSDimitry Andric   }
5240eae32dcSDimitry Andric 
5250eae32dcSDimitry Andric   // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
5260eae32dcSDimitry Andric   // is known at compile time to be "/' since the user almost certainly intended
5270eae32dcSDimitry Andric   // to append a separator instead of overwriting the path with "/"
5280eae32dcSDimitry Andric   template <class _Source>
529cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
5300eae32dcSDimitry Andric     return this->append(__src);
5310eae32dcSDimitry Andric   }
5320eae32dcSDimitry Andric 
5330eae32dcSDimitry Andric   template <class _Source>
534cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
5350eae32dcSDimitry Andric     using _Traits             = __is_pathable<_Source>;
5360eae32dcSDimitry Andric     using _CVT                = _PathCVT<_SourceChar<_Source> >;
5375f757f3fSDimitry Andric     bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));
5380eae32dcSDimitry Andric     if (__source_is_absolute)
5390eae32dcSDimitry Andric       __pn_.clear();
5400eae32dcSDimitry Andric     else if (has_filename())
5410eae32dcSDimitry Andric       __pn_ += preferred_separator;
5420eae32dcSDimitry Andric     _CVT::__append_source(__pn_, __src);
5430eae32dcSDimitry Andric     return *this;
5440eae32dcSDimitry Andric   }
5450eae32dcSDimitry Andric 
5460eae32dcSDimitry Andric   template <class _InputIt>
547cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
5480eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
5490eae32dcSDimitry Andric     static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
5500eae32dcSDimitry Andric     using _CVT = _PathCVT<_ItVal>;
5515f757f3fSDimitry Andric     if (__first != __last && filesystem::__is_separator(*__first))
5520eae32dcSDimitry Andric       __pn_.clear();
5530eae32dcSDimitry Andric     else if (has_filename())
5540eae32dcSDimitry Andric       __pn_ += preferred_separator;
5550eae32dcSDimitry Andric     _CVT::__append_range(__pn_, __first, __last);
5560eae32dcSDimitry Andric     return *this;
5570eae32dcSDimitry Andric   }
5580eae32dcSDimitry Andric #  endif
5590eae32dcSDimitry Andric 
5600eae32dcSDimitry Andric   // concatenation
561cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {
5620eae32dcSDimitry Andric     __pn_ += __x.__pn_;
5630eae32dcSDimitry Andric     return *this;
5640eae32dcSDimitry Andric   }
5650eae32dcSDimitry Andric 
566cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {
5670eae32dcSDimitry Andric     __pn_ += __x;
5680eae32dcSDimitry Andric     return *this;
5690eae32dcSDimitry Andric   }
5700eae32dcSDimitry Andric 
571cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {
5720eae32dcSDimitry Andric     __pn_ += __x;
5730eae32dcSDimitry Andric     return *this;
5740eae32dcSDimitry Andric   }
5750eae32dcSDimitry Andric 
576cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {
5770eae32dcSDimitry Andric     __pn_ += __x;
5780eae32dcSDimitry Andric     return *this;
5790eae32dcSDimitry Andric   }
5800eae32dcSDimitry Andric 
581cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {
5820eae32dcSDimitry Andric     __pn_ += __x;
5830eae32dcSDimitry Andric     return *this;
5840eae32dcSDimitry Andric   }
5850eae32dcSDimitry Andric 
5865f757f3fSDimitry Andric   template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
587cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
588cb14a3feSDimitry Andric     _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
5890eae32dcSDimitry Andric     return *this;
5900eae32dcSDimitry Andric   }
5910eae32dcSDimitry Andric 
5920eae32dcSDimitry Andric   template <class _Source>
593cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {
5940eae32dcSDimitry Andric     return this->concat(__x);
5950eae32dcSDimitry Andric   }
5960eae32dcSDimitry Andric 
5970eae32dcSDimitry Andric   template <class _Source>
598cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {
5990eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __x);
6000eae32dcSDimitry Andric     return *this;
6010eae32dcSDimitry Andric   }
6020eae32dcSDimitry Andric 
6030eae32dcSDimitry Andric   template <class _InputIt>
604cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {
6050eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
6060eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
6070eae32dcSDimitry Andric     return *this;
6080eae32dcSDimitry Andric   }
6090eae32dcSDimitry Andric 
6100eae32dcSDimitry Andric   // modifiers
611cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }
6120eae32dcSDimitry Andric 
613cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& make_preferred() {
6140eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
6155f757f3fSDimitry Andric     std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
6160eae32dcSDimitry Andric #  endif
6170eae32dcSDimitry Andric     return *this;
6180eae32dcSDimitry Andric   }
6190eae32dcSDimitry Andric 
620cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& remove_filename() {
6210eae32dcSDimitry Andric     auto __fname = __filename();
6220eae32dcSDimitry Andric     if (!__fname.empty())
6230eae32dcSDimitry Andric       __pn_.erase(__fname.data() - __pn_.data());
6240eae32dcSDimitry Andric     return *this;
6250eae32dcSDimitry Andric   }
6260eae32dcSDimitry Andric 
627cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {
6280eae32dcSDimitry Andric     remove_filename();
6290eae32dcSDimitry Andric     return (*this /= __replacement);
6300eae32dcSDimitry Andric   }
6310eae32dcSDimitry Andric 
6320eae32dcSDimitry Andric   path& replace_extension(const path& __replacement = path());
6330eae32dcSDimitry Andric 
634bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
635bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) == 0;
636bdd1243dSDimitry Andric   }
637bdd1243dSDimitry Andric #  if _LIBCPP_STD_VER <= 17
638bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
639bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) != 0;
640bdd1243dSDimitry Andric   }
641bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {
642bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) < 0;
643bdd1243dSDimitry Andric   }
644bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {
645bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) <= 0;
646bdd1243dSDimitry Andric   }
647bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {
648bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) > 0;
649bdd1243dSDimitry Andric   }
650bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {
651bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) >= 0;
652bdd1243dSDimitry Andric   }
653bdd1243dSDimitry Andric #  else  // _LIBCPP_STD_VER <= 17
654bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
655bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) <=> 0;
656bdd1243dSDimitry Andric   }
657bdd1243dSDimitry Andric #  endif // _LIBCPP_STD_VER <= 17
658bdd1243dSDimitry Andric 
659bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
660bdd1243dSDimitry Andric     path __result(__lhs);
661bdd1243dSDimitry Andric     __result /= __rhs;
662bdd1243dSDimitry Andric     return __result;
663bdd1243dSDimitry Andric   }
664bdd1243dSDimitry Andric 
665cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
6660eae32dcSDimitry Andric 
6670eae32dcSDimitry Andric   // private helper to allow reserving memory in the path
668cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }
6690eae32dcSDimitry Andric 
6700eae32dcSDimitry Andric   // native format observers
671cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }
6720eae32dcSDimitry Andric 
673cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }
6740eae32dcSDimitry Andric 
67581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
6760eae32dcSDimitry Andric 
6770eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
6785f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }
6790eae32dcSDimitry Andric 
680cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {
6815f757f3fSDimitry Andric     std::wstring __s;
6820eae32dcSDimitry Andric     __s.resize(__pn_.size());
6835f757f3fSDimitry Andric     std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
6840eae32dcSDimitry Andric     return __s;
6850eae32dcSDimitry Andric   }
6860eae32dcSDimitry Andric 
6870eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
688cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
689cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
6900eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
6910eae32dcSDimitry Andric     _Str __s(__a);
6920eae32dcSDimitry Andric     __s.reserve(__pn_.size());
6930eae32dcSDimitry Andric     _PathExport<_ECharT>::__append(__s, __pn_);
6940eae32dcSDimitry Andric     return __s;
6950eae32dcSDimitry Andric   }
6960eae32dcSDimitry Andric 
697cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }
69881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
6990eae32dcSDimitry Andric     using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
7000eae32dcSDimitry Andric     __u8_string __s;
7010eae32dcSDimitry Andric     __s.reserve(__pn_.size());
7020eae32dcSDimitry Andric     _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
7030eae32dcSDimitry Andric     return __s;
7040eae32dcSDimitry Andric   }
7050eae32dcSDimitry Andric 
706cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
707cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
7080eae32dcSDimitry Andric 
7090eae32dcSDimitry Andric   // generic format observers
710cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
711cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
7120eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
7130eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
7140eae32dcSDimitry Andric     _Str __s   = string<_ECharT, _Traits, _Allocator>(__a);
7150eae32dcSDimitry Andric     // Note: This (and generic_u8string below) is slightly suboptimal as
7160eae32dcSDimitry Andric     // it iterates twice over the string; once to convert it to the right
7170eae32dcSDimitry Andric     // character type, and once to replace path delimiters.
718cb14a3feSDimitry Andric     std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
7190eae32dcSDimitry Andric     return __s;
7200eae32dcSDimitry Andric   }
7210eae32dcSDimitry Andric 
7225f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }
7235f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }
7245f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }
725cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {
7260eae32dcSDimitry Andric     __u8_string __s = u8string();
7275f757f3fSDimitry Andric     std::replace(__s.begin(), __s.end(), '\\', '/');
7280eae32dcSDimitry Andric     return __s;
7290eae32dcSDimitry Andric   }
7300eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7310eae32dcSDimitry Andric #  else    /* _LIBCPP_WIN32API */
7320eae32dcSDimitry Andric 
7335f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }
7340eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
7355f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
7360eae32dcSDimitry Andric #    else
7375f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }
7380eae32dcSDimitry Andric #    endif
7390eae32dcSDimitry Andric 
7400eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
741cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
742cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
7430eae32dcSDimitry Andric     using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
7440eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
7450eae32dcSDimitry Andric     _Str __s(__a);
7460eae32dcSDimitry Andric     __s.reserve(__pn_.size());
747bdd1243dSDimitry Andric     _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
7480eae32dcSDimitry Andric     return __s;
7490eae32dcSDimitry Andric   }
7500eae32dcSDimitry Andric 
7510eae32dcSDimitry Andric #      ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
752cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }
7530eae32dcSDimitry Andric #      endif
754cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
755cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
7560eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7570eae32dcSDimitry Andric 
7580eae32dcSDimitry Andric   // generic format observers
7595f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }
7600eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
7615f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
7620eae32dcSDimitry Andric #    else
7635f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }
7640eae32dcSDimitry Andric #    endif
7650eae32dcSDimitry Andric 
7660eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
767cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
768cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
7690eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
7700eae32dcSDimitry Andric     return string<_ECharT, _Traits, _Allocator>(__a);
7710eae32dcSDimitry Andric   }
7720eae32dcSDimitry Andric 
7730eae32dcSDimitry Andric #      ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
7745f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }
7750eae32dcSDimitry Andric #      endif
7765f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }
7775f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }
7780eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7790eae32dcSDimitry Andric #  endif   /* !_LIBCPP_WIN32API */
7800eae32dcSDimitry Andric 
7810eae32dcSDimitry Andric private:
7820eae32dcSDimitry Andric   int __compare(__string_view) const;
7830eae32dcSDimitry Andric   __string_view __root_name() const;
7840eae32dcSDimitry Andric   __string_view __root_directory() const;
7850eae32dcSDimitry Andric   __string_view __root_path_raw() const;
7860eae32dcSDimitry Andric   __string_view __relative_path() const;
7870eae32dcSDimitry Andric   __string_view __parent_path() const;
7880eae32dcSDimitry Andric   __string_view __filename() const;
7890eae32dcSDimitry Andric   __string_view __stem() const;
7900eae32dcSDimitry Andric   __string_view __extension() const;
7910eae32dcSDimitry Andric 
7920eae32dcSDimitry Andric public:
7930eae32dcSDimitry Andric   // compare
794cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }
795cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }
796cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }
797cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }
7980eae32dcSDimitry Andric 
7990eae32dcSDimitry Andric   // decomposition
800cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }
801cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }
80281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_path() const {
8030eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
8040eae32dcSDimitry Andric     return string_type(__root_path_raw());
8050eae32dcSDimitry Andric #  else
8060eae32dcSDimitry Andric     return root_name().append(string_type(__root_directory()));
8070eae32dcSDimitry Andric #  endif
8080eae32dcSDimitry Andric   }
809cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }
810cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }
811cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }
81281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
813cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }
8140eae32dcSDimitry Andric 
8150eae32dcSDimitry Andric   // query
816cb14a3feSDimitry Andric   _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }
8170eae32dcSDimitry Andric 
818cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }
819cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }
820cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }
821cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }
822cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }
823cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }
82481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
825cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }
8260eae32dcSDimitry Andric 
82781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
8280eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
8290eae32dcSDimitry Andric     __string_view __root_name_str = __root_name();
8300eae32dcSDimitry Andric     __string_view __root_dir      = __root_directory();
8310eae32dcSDimitry Andric     if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
8320eae32dcSDimitry Andric       // A drive letter with no root directory is relative, e.g. x:example.
8330eae32dcSDimitry Andric       return !__root_dir.empty();
8340eae32dcSDimitry Andric     }
8350eae32dcSDimitry Andric     // If no root name, it's relative, e.g. \example is relative to the current drive
8360eae32dcSDimitry Andric     if (__root_name_str.empty())
8370eae32dcSDimitry Andric       return false;
8380eae32dcSDimitry Andric     if (__root_name_str.size() < 3)
8390eae32dcSDimitry Andric       return false;
8400eae32dcSDimitry Andric     // A server root name, like \\server, is always absolute
8410eae32dcSDimitry Andric     if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
8420eae32dcSDimitry Andric       return false;
8430eae32dcSDimitry Andric     if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
8440eae32dcSDimitry Andric       return false;
8450eae32dcSDimitry Andric     // Seems to be a server root name
8460eae32dcSDimitry Andric     return true;
8470eae32dcSDimitry Andric #  else
8480eae32dcSDimitry Andric     return has_root_directory();
8490eae32dcSDimitry Andric #  endif
8500eae32dcSDimitry Andric   }
85181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
8520eae32dcSDimitry Andric 
8530eae32dcSDimitry Andric   // relative paths
8540eae32dcSDimitry Andric   path lexically_normal() const;
8550eae32dcSDimitry Andric   path lexically_relative(const path& __base) const;
8560eae32dcSDimitry Andric 
85781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
8580eae32dcSDimitry Andric     path __result = this->lexically_relative(__base);
8590eae32dcSDimitry Andric     if (__result.native().empty())
8600eae32dcSDimitry Andric       return *this;
8610eae32dcSDimitry Andric     return __result;
8620eae32dcSDimitry Andric   }
8630eae32dcSDimitry Andric 
8640eae32dcSDimitry Andric   // iterators
86506c3fb27SDimitry Andric   class _LIBCPP_EXPORTED_FROM_ABI iterator;
8660eae32dcSDimitry Andric   typedef iterator const_iterator;
8670eae32dcSDimitry Andric 
8680eae32dcSDimitry Andric   iterator begin() const;
8690eae32dcSDimitry Andric   iterator end() const;
8700eae32dcSDimitry Andric 
8710eae32dcSDimitry Andric #  if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
872cb14a3feSDimitry Andric   template <
873cb14a3feSDimitry Andric       class _CharT,
874cb14a3feSDimitry Andric       class _Traits,
875cb14a3feSDimitry Andric       __enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>
876cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
8770eae32dcSDimitry Andric   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
8785f757f3fSDimitry Andric     __os << std::__quoted(__p.native());
8790eae32dcSDimitry Andric     return __os;
8800eae32dcSDimitry Andric   }
8810eae32dcSDimitry Andric 
882cb14a3feSDimitry Andric   template <
883cb14a3feSDimitry Andric       class _CharT,
884cb14a3feSDimitry Andric       class _Traits,
885cb14a3feSDimitry Andric       __enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>
886cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
8870eae32dcSDimitry Andric   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
8885f757f3fSDimitry Andric     __os << std::__quoted(__p.string<_CharT, _Traits>());
8890eae32dcSDimitry Andric     return __os;
8900eae32dcSDimitry Andric   }
8910eae32dcSDimitry Andric 
8920eae32dcSDimitry Andric   template <class _CharT, class _Traits>
89381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
8940eae32dcSDimitry Andric   operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
8950eae32dcSDimitry Andric     basic_string<_CharT, _Traits> __tmp;
8965f757f3fSDimitry Andric     __is >> std::__quoted(__tmp);
8970eae32dcSDimitry Andric     __p = __tmp;
8980eae32dcSDimitry Andric     return __is;
8990eae32dcSDimitry Andric   }
9000eae32dcSDimitry Andric #  endif // !_LIBCPP_HAS_NO_LOCALIZATION
9010eae32dcSDimitry Andric 
9020eae32dcSDimitry Andric private:
9035f757f3fSDimitry Andric   inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {
9040eae32dcSDimitry Andric     __pn_ = string_type(__s);
9050eae32dcSDimitry Andric     return *this;
9060eae32dcSDimitry Andric   }
9070eae32dcSDimitry Andric   string_type __pn_;
9080eae32dcSDimitry Andric };
9090eae32dcSDimitry Andric 
910cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
9110eae32dcSDimitry Andric 
91206c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
9130eae32dcSDimitry Andric 
91406c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
9150eae32dcSDimitry Andric 
9160eae32dcSDimitry Andric _LIBCPP_END_NAMESPACE_FILESYSTEM
9170eae32dcSDimitry Andric 
91806c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
91906c3fb27SDimitry Andric 
92006c3fb27SDimitry Andric template <>
9215f757f3fSDimitry Andric struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {
9225f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {
9235f757f3fSDimitry Andric     return filesystem::hash_value(__p);
92406c3fb27SDimitry Andric   }
92506c3fb27SDimitry Andric };
92606c3fb27SDimitry Andric 
92706c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
92806c3fb27SDimitry Andric 
9295f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 17
9300eae32dcSDimitry Andric 
931*b3edf446SDimitry Andric _LIBCPP_POP_MACROS
932*b3edf446SDimitry Andric 
9330eae32dcSDimitry Andric #endif // _LIBCPP___FILESYSTEM_PATH_H
934