xref: /freebsd-src/contrib/llvm-project/libcxx/include/__filesystem/path.h (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
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 
395f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 17
400eae32dcSDimitry Andric 
410eae32dcSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
420eae32dcSDimitry Andric 
4306c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric template <class _Tp>
460eae32dcSDimitry Andric struct __can_convert_char {
470eae32dcSDimitry Andric   static const bool value = false;
480eae32dcSDimitry Andric };
490eae32dcSDimitry Andric template <class _Tp>
500eae32dcSDimitry Andric struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
510eae32dcSDimitry Andric template <>
520eae32dcSDimitry Andric struct __can_convert_char<char> {
530eae32dcSDimitry Andric   static const bool value = true;
540eae32dcSDimitry Andric   using __char_type       = char;
550eae32dcSDimitry Andric };
560eae32dcSDimitry Andric template <>
570eae32dcSDimitry Andric struct __can_convert_char<wchar_t> {
580eae32dcSDimitry Andric   static const bool value = true;
590eae32dcSDimitry Andric   using __char_type       = wchar_t;
600eae32dcSDimitry Andric };
610eae32dcSDimitry Andric #  ifndef _LIBCPP_HAS_NO_CHAR8_T
620eae32dcSDimitry Andric template <>
630eae32dcSDimitry Andric struct __can_convert_char<char8_t> {
640eae32dcSDimitry Andric   static const bool value = true;
650eae32dcSDimitry Andric   using __char_type       = char8_t;
660eae32dcSDimitry Andric };
670eae32dcSDimitry Andric #  endif
680eae32dcSDimitry Andric template <>
690eae32dcSDimitry Andric struct __can_convert_char<char16_t> {
700eae32dcSDimitry Andric   static const bool value = true;
710eae32dcSDimitry Andric   using __char_type       = char16_t;
720eae32dcSDimitry Andric };
730eae32dcSDimitry Andric template <>
740eae32dcSDimitry Andric struct __can_convert_char<char32_t> {
750eae32dcSDimitry Andric   static const bool value = true;
760eae32dcSDimitry Andric   using __char_type       = char32_t;
770eae32dcSDimitry Andric };
780eae32dcSDimitry Andric 
795f757f3fSDimitry Andric template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
80*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {
810eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
820eae32dcSDimitry Andric   return __e == _ECharT('/') || __e == _ECharT('\\');
830eae32dcSDimitry Andric #  else
840eae32dcSDimitry Andric   return __e == _ECharT('/');
850eae32dcSDimitry Andric #  endif
860eae32dcSDimitry Andric }
870eae32dcSDimitry Andric 
880eae32dcSDimitry Andric #  ifndef _LIBCPP_HAS_NO_CHAR8_T
890eae32dcSDimitry Andric typedef u8string __u8_string;
900eae32dcSDimitry Andric #  else
910eae32dcSDimitry Andric typedef string __u8_string;
920eae32dcSDimitry Andric #  endif
930eae32dcSDimitry Andric 
940eae32dcSDimitry Andric struct _NullSentinel {};
950eae32dcSDimitry Andric 
960eae32dcSDimitry Andric template <class _Tp>
970eae32dcSDimitry Andric using _Void = void;
980eae32dcSDimitry Andric 
990eae32dcSDimitry Andric template <class _Tp, class = void>
1000eae32dcSDimitry Andric struct __is_pathable_string : public false_type {};
1010eae32dcSDimitry Andric 
1020eae32dcSDimitry Andric template <class _ECharT, class _Traits, class _Alloc>
103*cb14a3feSDimitry Andric struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>,
1040eae32dcSDimitry Andric                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
1050eae32dcSDimitry Andric     : public __can_convert_char<_ECharT> {
1060eae32dcSDimitry Andric   using _Str = basic_string<_ECharT, _Traits, _Alloc>;
10781ad6265SDimitry Andric 
108*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
10981ad6265SDimitry Andric 
110*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
11181ad6265SDimitry Andric 
112*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
1130eae32dcSDimitry Andric };
1140eae32dcSDimitry Andric 
1150eae32dcSDimitry Andric template <class _ECharT, class _Traits>
116*cb14a3feSDimitry Andric struct __is_pathable_string< basic_string_view<_ECharT, _Traits>,
1170eae32dcSDimitry Andric                              _Void<typename __can_convert_char<_ECharT>::__char_type> >
1180eae32dcSDimitry Andric     : public __can_convert_char<_ECharT> {
1190eae32dcSDimitry Andric   using _Str = basic_string_view<_ECharT, _Traits>;
12081ad6265SDimitry Andric 
121*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
12281ad6265SDimitry Andric 
123*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
12481ad6265SDimitry Andric 
125*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
1260eae32dcSDimitry Andric };
1270eae32dcSDimitry Andric 
128*cb14a3feSDimitry Andric template <class _Source,
129*cb14a3feSDimitry Andric           class _DS            = __decay_t<_Source>,
130*cb14a3feSDimitry Andric           class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
131*cb14a3feSDimitry Andric           bool _IsCharPtr      = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
1320eae32dcSDimitry Andric struct __is_pathable_char_array : false_type {};
1330eae32dcSDimitry Andric 
1340eae32dcSDimitry Andric template <class _Source, class _ECharT, class _UPtr>
135*cb14a3feSDimitry Andric struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> : __can_convert_char<__remove_const_t<_ECharT> > {
136*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
13781ad6265SDimitry Andric 
138*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {
1390eae32dcSDimitry Andric     using _Iter              = const _ECharT*;
1400eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
1410eae32dcSDimitry Andric     _Iter __e                = __b;
1420eae32dcSDimitry Andric     for (; *__e != __sentinel; ++__e)
1430eae32dcSDimitry Andric       ;
1440eae32dcSDimitry Andric     return __e;
1450eae32dcSDimitry Andric   }
1460eae32dcSDimitry Andric 
147*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
1480eae32dcSDimitry Andric };
1490eae32dcSDimitry Andric 
150*cb14a3feSDimitry Andric template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
1510eae32dcSDimitry Andric struct __is_pathable_iter : false_type {};
1520eae32dcSDimitry Andric 
1530eae32dcSDimitry Andric template <class _Iter>
1540eae32dcSDimitry Andric struct __is_pathable_iter<
155*cb14a3feSDimitry Andric     _Iter,
156*cb14a3feSDimitry Andric     true,
157*cb14a3feSDimitry Andric     _Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >
1580eae32dcSDimitry Andric     : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
1590eae32dcSDimitry Andric   using _ECharT = typename iterator_traits<_Iter>::value_type;
1600eae32dcSDimitry Andric 
161*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }
16281ad6265SDimitry Andric 
163*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
1640eae32dcSDimitry Andric 
165*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }
1660eae32dcSDimitry Andric };
1670eae32dcSDimitry Andric 
168*cb14a3feSDimitry Andric template <class _Tp,
169*cb14a3feSDimitry Andric           bool _IsStringT   = __is_pathable_string<_Tp>::value,
1700eae32dcSDimitry Andric           bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
1710eae32dcSDimitry Andric           bool _IsIterT     = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
1720eae32dcSDimitry Andric struct __is_pathable : false_type {
1730eae32dcSDimitry Andric   static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
1740eae32dcSDimitry Andric };
1750eae32dcSDimitry Andric 
1760eae32dcSDimitry Andric template <class _Tp>
1770eae32dcSDimitry Andric struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
1780eae32dcSDimitry Andric 
1790eae32dcSDimitry Andric template <class _Tp>
180*cb14a3feSDimitry Andric struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
1810eae32dcSDimitry Andric 
1820eae32dcSDimitry Andric template <class _Tp>
1830eae32dcSDimitry Andric struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
1840eae32dcSDimitry Andric 
1850eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
1860eae32dcSDimitry Andric typedef wstring __path_string;
1870eae32dcSDimitry Andric typedef wchar_t __path_value;
1880eae32dcSDimitry Andric #  else
1890eae32dcSDimitry Andric typedef string __path_string;
1900eae32dcSDimitry Andric typedef char __path_value;
1910eae32dcSDimitry Andric #  endif
1920eae32dcSDimitry Andric 
1930eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
19406c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
19506c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
1960eae32dcSDimitry Andric #  endif
1970eae32dcSDimitry Andric 
1980eae32dcSDimitry Andric template <class _ECharT>
1990eae32dcSDimitry Andric struct _PathCVT;
2000eae32dcSDimitry Andric 
2010eae32dcSDimitry Andric #  if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
2020eae32dcSDimitry Andric template <class _ECharT>
2030eae32dcSDimitry Andric struct _PathCVT {
204*cb14a3feSDimitry Andric   static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
2050eae32dcSDimitry Andric 
2060eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
2070eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2080eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
2090eae32dcSDimitry Andric #    endif
2100eae32dcSDimitry Andric 
211*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {
2120eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2130eae32dcSDimitry Andric     string __utf8;
2140eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __b, __e);
2150eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2160eae32dcSDimitry Andric #    else
2170eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __b, __e);
2180eae32dcSDimitry Andric #    endif
2190eae32dcSDimitry Andric   }
2200eae32dcSDimitry Andric 
2210eae32dcSDimitry Andric   template <class _Iter>
222*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2230eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2240eae32dcSDimitry Andric     if (__b == __e)
2250eae32dcSDimitry Andric       return;
2260eae32dcSDimitry Andric     basic_string<_ECharT> __tmp(__b, __e);
2270eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2280eae32dcSDimitry Andric     string __utf8;
229*cb14a3feSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
2300eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2310eae32dcSDimitry Andric #    else
232*cb14a3feSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
2330eae32dcSDimitry Andric #    endif
2340eae32dcSDimitry Andric   }
2350eae32dcSDimitry Andric 
2360eae32dcSDimitry Andric   template <class _Iter>
237*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
2380eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2390eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
2400eae32dcSDimitry Andric     if (*__b == __sentinel)
2410eae32dcSDimitry Andric       return;
2420eae32dcSDimitry Andric     basic_string<_ECharT> __tmp;
2430eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
2440eae32dcSDimitry Andric       __tmp.push_back(*__b);
2450eae32dcSDimitry Andric #    if defined(_LIBCPP_WIN32API)
2460eae32dcSDimitry Andric     string __utf8;
247*cb14a3feSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
2480eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2490eae32dcSDimitry Andric #    else
250*cb14a3feSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
2510eae32dcSDimitry Andric #    endif
2520eae32dcSDimitry Andric   }
2530eae32dcSDimitry Andric 
2540eae32dcSDimitry Andric   template <class _Source>
255*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
2560eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
257*cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
2580eae32dcSDimitry Andric   }
2590eae32dcSDimitry Andric };
2600eae32dcSDimitry Andric #  endif // !_LIBCPP_HAS_NO_LOCALIZATION
2610eae32dcSDimitry Andric 
2620eae32dcSDimitry Andric template <>
2630eae32dcSDimitry Andric struct _PathCVT<__path_value> {
2645f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
265*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2660eae32dcSDimitry Andric     for (; __b != __e; ++__b)
2670eae32dcSDimitry Andric       __dest.push_back(*__b);
2680eae32dcSDimitry Andric   }
2690eae32dcSDimitry Andric 
2705f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
271*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2720eae32dcSDimitry Andric     __dest.append(__b, __e);
2730eae32dcSDimitry Andric   }
2740eae32dcSDimitry Andric 
2750eae32dcSDimitry Andric   template <class _Iter>
276*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
2770eae32dcSDimitry Andric     const char __sentinel = char{};
2780eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
2790eae32dcSDimitry Andric       __dest.push_back(*__b);
2800eae32dcSDimitry Andric   }
2810eae32dcSDimitry Andric 
2820eae32dcSDimitry Andric   template <class _Source>
283*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
2840eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
285*cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
2860eae32dcSDimitry Andric   }
2870eae32dcSDimitry Andric };
2880eae32dcSDimitry Andric 
2890eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
2900eae32dcSDimitry Andric template <>
2910eae32dcSDimitry Andric struct _PathCVT<char> {
292*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
2930eae32dcSDimitry Andric     size_t __size = __char_to_wide(__str, nullptr, 0);
2940eae32dcSDimitry Andric     size_t __pos  = __dest.size();
2950eae32dcSDimitry Andric     __dest.resize(__pos + __size);
2960eae32dcSDimitry Andric     __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
2970eae32dcSDimitry Andric   }
2980eae32dcSDimitry Andric 
2995f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
300*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3010eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3020eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3030eae32dcSDimitry Andric   }
3040eae32dcSDimitry Andric 
3055f757f3fSDimitry Andric   template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
306*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3070eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3080eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3090eae32dcSDimitry Andric   }
3100eae32dcSDimitry Andric 
3110eae32dcSDimitry Andric   template <class _Iter>
312*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
3130eae32dcSDimitry Andric     const char __sentinel = char{};
3140eae32dcSDimitry Andric     basic_string<char> __tmp;
3150eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
3160eae32dcSDimitry Andric       __tmp.push_back(*__b);
3170eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3180eae32dcSDimitry Andric   }
3190eae32dcSDimitry Andric 
3200eae32dcSDimitry Andric   template <class _Source>
321*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
3220eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
323*cb14a3feSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
3240eae32dcSDimitry Andric   }
3250eae32dcSDimitry Andric };
3260eae32dcSDimitry Andric 
3270eae32dcSDimitry Andric template <class _ECharT>
3280eae32dcSDimitry Andric struct _PathExport {
3290eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
3300eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
3310eae32dcSDimitry Andric 
3320eae32dcSDimitry Andric   template <class _Str>
333*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3340eae32dcSDimitry Andric     string __utf8;
3350eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
3360eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
3370eae32dcSDimitry Andric   }
3380eae32dcSDimitry Andric };
3390eae32dcSDimitry Andric 
3400eae32dcSDimitry Andric template <>
3410eae32dcSDimitry Andric struct _PathExport<char> {
3420eae32dcSDimitry Andric   template <class _Str>
343*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3440eae32dcSDimitry Andric     size_t __size = __wide_to_char(__src, nullptr, 0);
3450eae32dcSDimitry Andric     size_t __pos  = __dest.size();
3460eae32dcSDimitry Andric     __dest.resize(__size);
3470eae32dcSDimitry Andric     __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
3480eae32dcSDimitry Andric   }
3490eae32dcSDimitry Andric };
3500eae32dcSDimitry Andric 
3510eae32dcSDimitry Andric template <>
3520eae32dcSDimitry Andric struct _PathExport<wchar_t> {
3530eae32dcSDimitry Andric   template <class _Str>
354*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3550eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
3560eae32dcSDimitry Andric   }
3570eae32dcSDimitry Andric };
3580eae32dcSDimitry Andric 
3590eae32dcSDimitry Andric template <>
3600eae32dcSDimitry Andric struct _PathExport<char16_t> {
3610eae32dcSDimitry Andric   template <class _Str>
362*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3630eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
3640eae32dcSDimitry Andric   }
3650eae32dcSDimitry Andric };
3660eae32dcSDimitry Andric 
3670eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
3680eae32dcSDimitry Andric template <>
3690eae32dcSDimitry Andric struct _PathExport<char8_t> {
3700eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
3710eae32dcSDimitry Andric 
3720eae32dcSDimitry Andric   template <class _Str>
373*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
3740eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
3750eae32dcSDimitry Andric   }
3760eae32dcSDimitry Andric };
3770eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_CHAR8_T */
3780eae32dcSDimitry Andric #  endif   /* _LIBCPP_WIN32API */
3790eae32dcSDimitry Andric 
38006c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI path {
3810eae32dcSDimitry Andric   template <class _SourceOrIter, class _Tp = path&>
3825f757f3fSDimitry Andric   using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;
3830eae32dcSDimitry Andric 
3840eae32dcSDimitry Andric   template <class _Tp>
3850eae32dcSDimitry Andric   using _SourceChar = typename __is_pathable<_Tp>::__char_type;
3860eae32dcSDimitry Andric 
3870eae32dcSDimitry Andric   template <class _Tp>
3880eae32dcSDimitry Andric   using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
3890eae32dcSDimitry Andric 
3900eae32dcSDimitry Andric public:
3910eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
3920eae32dcSDimitry Andric   typedef wchar_t value_type;
3930eae32dcSDimitry Andric   static constexpr value_type preferred_separator = L'\\';
3940eae32dcSDimitry Andric #  else
3950eae32dcSDimitry Andric   typedef char value_type;
3960eae32dcSDimitry Andric   static constexpr value_type preferred_separator = '/';
3970eae32dcSDimitry Andric #  endif
3980eae32dcSDimitry Andric   typedef basic_string<value_type> string_type;
3990eae32dcSDimitry Andric   typedef basic_string_view<value_type> __string_view;
4000eae32dcSDimitry Andric 
401*cb14a3feSDimitry Andric   enum format : unsigned char { auto_format, native_format, generic_format };
4020eae32dcSDimitry Andric 
4030eae32dcSDimitry Andric   // constructors and destructor
40481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path() noexcept {}
40581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
406*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}
4070eae32dcSDimitry Andric 
408*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}
4090eae32dcSDimitry Andric 
4100eae32dcSDimitry Andric   template <class _Source, class = _EnableIfPathable<_Source, void> >
411*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {
4120eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
4130eae32dcSDimitry Andric   }
4140eae32dcSDimitry Andric 
4150eae32dcSDimitry Andric   template <class _InputIt>
416*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {
4170eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
4180eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
4190eae32dcSDimitry Andric   }
4200eae32dcSDimitry Andric 
4210eae32dcSDimitry Andric   /*
4220eae32dcSDimitry Andric   #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
4230eae32dcSDimitry Andric     // TODO Implement locale conversions.
4240eae32dcSDimitry Andric     template <class _Source, class = _EnableIfPathable<_Source, void> >
4250eae32dcSDimitry Andric     path(const _Source& __src, const locale& __loc, format = format::auto_format);
4260eae32dcSDimitry Andric     template <class _InputIt>
4270eae32dcSDimitry Andric     path(_InputIt __first, _InputIt _last, const locale& __loc,
4280eae32dcSDimitry Andric          format = format::auto_format);
4290eae32dcSDimitry Andric   #endif
4300eae32dcSDimitry Andric   */
4310eae32dcSDimitry Andric 
432*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI ~path() = default;
4330eae32dcSDimitry Andric 
4340eae32dcSDimitry Andric   // assignments
435*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {
4360eae32dcSDimitry Andric     __pn_ = __p.__pn_;
4370eae32dcSDimitry Andric     return *this;
4380eae32dcSDimitry Andric   }
4390eae32dcSDimitry Andric 
440*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {
4415f757f3fSDimitry Andric     __pn_ = std::move(__p.__pn_);
4420eae32dcSDimitry Andric     return *this;
4430eae32dcSDimitry Andric   }
4440eae32dcSDimitry Andric 
445*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {
4465f757f3fSDimitry Andric     __pn_ = std::move(__s);
4470eae32dcSDimitry Andric     return *this;
4480eae32dcSDimitry Andric   }
4490eae32dcSDimitry Andric 
450*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {
4515f757f3fSDimitry Andric     __pn_ = std::move(__s);
4520eae32dcSDimitry Andric     return *this;
4530eae32dcSDimitry Andric   }
4540eae32dcSDimitry Andric 
4550eae32dcSDimitry Andric   template <class _Source>
456*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {
4570eae32dcSDimitry Andric     return this->assign(__src);
4580eae32dcSDimitry Andric   }
4590eae32dcSDimitry Andric 
4600eae32dcSDimitry Andric   template <class _Source>
461*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {
4620eae32dcSDimitry Andric     __pn_.clear();
4630eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
4640eae32dcSDimitry Andric     return *this;
4650eae32dcSDimitry Andric   }
4660eae32dcSDimitry Andric 
4670eae32dcSDimitry Andric   template <class _InputIt>
468*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {
4690eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
4700eae32dcSDimitry Andric     __pn_.clear();
4710eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
4720eae32dcSDimitry Andric     return *this;
4730eae32dcSDimitry Andric   }
4740eae32dcSDimitry Andric 
4750eae32dcSDimitry Andric public:
4760eae32dcSDimitry Andric   // appends
4770eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
478*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
4790eae32dcSDimitry Andric     auto __p_root_name      = __p.__root_name();
4800eae32dcSDimitry Andric     auto __p_root_name_size = __p_root_name.size();
481*cb14a3feSDimitry Andric     if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
4820eae32dcSDimitry Andric       __pn_ = __p.__pn_;
4830eae32dcSDimitry Andric       return *this;
4840eae32dcSDimitry Andric     }
4850eae32dcSDimitry Andric     if (__p.has_root_directory()) {
4860eae32dcSDimitry Andric       path __root_name_str = root_name();
4870eae32dcSDimitry Andric       __pn_                = __root_name_str.native();
4880eae32dcSDimitry Andric       __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
4890eae32dcSDimitry Andric       return *this;
4900eae32dcSDimitry Andric     }
4910eae32dcSDimitry Andric     if (has_filename() || (!has_root_directory() && is_absolute()))
4920eae32dcSDimitry Andric       __pn_ += preferred_separator;
4930eae32dcSDimitry Andric     __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
4940eae32dcSDimitry Andric     return *this;
4950eae32dcSDimitry Andric   }
4960eae32dcSDimitry Andric   template <class _Source>
497*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
4980eae32dcSDimitry Andric     return operator/=(path(__src));
4990eae32dcSDimitry Andric   }
5000eae32dcSDimitry Andric 
5010eae32dcSDimitry Andric   template <class _Source>
502*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
5030eae32dcSDimitry Andric     return operator/=(path(__src));
5040eae32dcSDimitry Andric   }
5050eae32dcSDimitry Andric 
5060eae32dcSDimitry Andric   template <class _InputIt>
507*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
5080eae32dcSDimitry Andric     return operator/=(path(__first, __last));
5090eae32dcSDimitry Andric   }
5100eae32dcSDimitry Andric #  else
511*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
5120eae32dcSDimitry Andric     if (__p.is_absolute()) {
5130eae32dcSDimitry Andric       __pn_ = __p.__pn_;
5140eae32dcSDimitry Andric       return *this;
5150eae32dcSDimitry Andric     }
5160eae32dcSDimitry Andric     if (has_filename())
5170eae32dcSDimitry Andric       __pn_ += preferred_separator;
5180eae32dcSDimitry Andric     __pn_ += __p.native();
5190eae32dcSDimitry Andric     return *this;
5200eae32dcSDimitry Andric   }
5210eae32dcSDimitry Andric 
5220eae32dcSDimitry Andric   // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
5230eae32dcSDimitry Andric   // is known at compile time to be "/' since the user almost certainly intended
5240eae32dcSDimitry Andric   // to append a separator instead of overwriting the path with "/"
5250eae32dcSDimitry Andric   template <class _Source>
526*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
5270eae32dcSDimitry Andric     return this->append(__src);
5280eae32dcSDimitry Andric   }
5290eae32dcSDimitry Andric 
5300eae32dcSDimitry Andric   template <class _Source>
531*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
5320eae32dcSDimitry Andric     using _Traits             = __is_pathable<_Source>;
5330eae32dcSDimitry Andric     using _CVT                = _PathCVT<_SourceChar<_Source> >;
5345f757f3fSDimitry Andric     bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));
5350eae32dcSDimitry Andric     if (__source_is_absolute)
5360eae32dcSDimitry Andric       __pn_.clear();
5370eae32dcSDimitry Andric     else if (has_filename())
5380eae32dcSDimitry Andric       __pn_ += preferred_separator;
5390eae32dcSDimitry Andric     _CVT::__append_source(__pn_, __src);
5400eae32dcSDimitry Andric     return *this;
5410eae32dcSDimitry Andric   }
5420eae32dcSDimitry Andric 
5430eae32dcSDimitry Andric   template <class _InputIt>
544*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
5450eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
5460eae32dcSDimitry Andric     static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
5470eae32dcSDimitry Andric     using _CVT = _PathCVT<_ItVal>;
5485f757f3fSDimitry Andric     if (__first != __last && filesystem::__is_separator(*__first))
5490eae32dcSDimitry Andric       __pn_.clear();
5500eae32dcSDimitry Andric     else if (has_filename())
5510eae32dcSDimitry Andric       __pn_ += preferred_separator;
5520eae32dcSDimitry Andric     _CVT::__append_range(__pn_, __first, __last);
5530eae32dcSDimitry Andric     return *this;
5540eae32dcSDimitry Andric   }
5550eae32dcSDimitry Andric #  endif
5560eae32dcSDimitry Andric 
5570eae32dcSDimitry Andric   // concatenation
558*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {
5590eae32dcSDimitry Andric     __pn_ += __x.__pn_;
5600eae32dcSDimitry Andric     return *this;
5610eae32dcSDimitry Andric   }
5620eae32dcSDimitry Andric 
563*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {
5640eae32dcSDimitry Andric     __pn_ += __x;
5650eae32dcSDimitry Andric     return *this;
5660eae32dcSDimitry Andric   }
5670eae32dcSDimitry Andric 
568*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {
5690eae32dcSDimitry Andric     __pn_ += __x;
5700eae32dcSDimitry Andric     return *this;
5710eae32dcSDimitry Andric   }
5720eae32dcSDimitry Andric 
573*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {
5740eae32dcSDimitry Andric     __pn_ += __x;
5750eae32dcSDimitry Andric     return *this;
5760eae32dcSDimitry Andric   }
5770eae32dcSDimitry Andric 
578*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {
5790eae32dcSDimitry Andric     __pn_ += __x;
5800eae32dcSDimitry Andric     return *this;
5810eae32dcSDimitry Andric   }
5820eae32dcSDimitry Andric 
5835f757f3fSDimitry Andric   template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
584*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
585*cb14a3feSDimitry Andric     _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
5860eae32dcSDimitry Andric     return *this;
5870eae32dcSDimitry Andric   }
5880eae32dcSDimitry Andric 
5890eae32dcSDimitry Andric   template <class _Source>
590*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {
5910eae32dcSDimitry Andric     return this->concat(__x);
5920eae32dcSDimitry Andric   }
5930eae32dcSDimitry Andric 
5940eae32dcSDimitry Andric   template <class _Source>
595*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {
5960eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __x);
5970eae32dcSDimitry Andric     return *this;
5980eae32dcSDimitry Andric   }
5990eae32dcSDimitry Andric 
6000eae32dcSDimitry Andric   template <class _InputIt>
601*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {
6020eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
6030eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
6040eae32dcSDimitry Andric     return *this;
6050eae32dcSDimitry Andric   }
6060eae32dcSDimitry Andric 
6070eae32dcSDimitry Andric   // modifiers
608*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }
6090eae32dcSDimitry Andric 
610*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& make_preferred() {
6110eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
6125f757f3fSDimitry Andric     std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
6130eae32dcSDimitry Andric #  endif
6140eae32dcSDimitry Andric     return *this;
6150eae32dcSDimitry Andric   }
6160eae32dcSDimitry Andric 
617*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& remove_filename() {
6180eae32dcSDimitry Andric     auto __fname = __filename();
6190eae32dcSDimitry Andric     if (!__fname.empty())
6200eae32dcSDimitry Andric       __pn_.erase(__fname.data() - __pn_.data());
6210eae32dcSDimitry Andric     return *this;
6220eae32dcSDimitry Andric   }
6230eae32dcSDimitry Andric 
624*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {
6250eae32dcSDimitry Andric     remove_filename();
6260eae32dcSDimitry Andric     return (*this /= __replacement);
6270eae32dcSDimitry Andric   }
6280eae32dcSDimitry Andric 
6290eae32dcSDimitry Andric   path& replace_extension(const path& __replacement = path());
6300eae32dcSDimitry Andric 
631bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
632bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) == 0;
633bdd1243dSDimitry Andric   }
634bdd1243dSDimitry Andric #  if _LIBCPP_STD_VER <= 17
635bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
636bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) != 0;
637bdd1243dSDimitry Andric   }
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 #  else  // _LIBCPP_STD_VER <= 17
651bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
652bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) <=> 0;
653bdd1243dSDimitry Andric   }
654bdd1243dSDimitry Andric #  endif // _LIBCPP_STD_VER <= 17
655bdd1243dSDimitry Andric 
656bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
657bdd1243dSDimitry Andric     path __result(__lhs);
658bdd1243dSDimitry Andric     __result /= __rhs;
659bdd1243dSDimitry Andric     return __result;
660bdd1243dSDimitry Andric   }
661bdd1243dSDimitry Andric 
662*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
6630eae32dcSDimitry Andric 
6640eae32dcSDimitry Andric   // private helper to allow reserving memory in the path
665*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }
6660eae32dcSDimitry Andric 
6670eae32dcSDimitry Andric   // native format observers
668*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }
6690eae32dcSDimitry Andric 
670*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }
6710eae32dcSDimitry Andric 
67281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
6730eae32dcSDimitry Andric 
6740eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
6755f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }
6760eae32dcSDimitry Andric 
677*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {
6785f757f3fSDimitry Andric     std::wstring __s;
6790eae32dcSDimitry Andric     __s.resize(__pn_.size());
6805f757f3fSDimitry Andric     std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
6810eae32dcSDimitry Andric     return __s;
6820eae32dcSDimitry Andric   }
6830eae32dcSDimitry Andric 
6840eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
685*cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
686*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
6870eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
6880eae32dcSDimitry Andric     _Str __s(__a);
6890eae32dcSDimitry Andric     __s.reserve(__pn_.size());
6900eae32dcSDimitry Andric     _PathExport<_ECharT>::__append(__s, __pn_);
6910eae32dcSDimitry Andric     return __s;
6920eae32dcSDimitry Andric   }
6930eae32dcSDimitry Andric 
694*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }
69581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
6960eae32dcSDimitry Andric     using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
6970eae32dcSDimitry Andric     __u8_string __s;
6980eae32dcSDimitry Andric     __s.reserve(__pn_.size());
6990eae32dcSDimitry Andric     _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
7000eae32dcSDimitry Andric     return __s;
7010eae32dcSDimitry Andric   }
7020eae32dcSDimitry Andric 
703*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
704*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
7050eae32dcSDimitry Andric 
7060eae32dcSDimitry Andric   // generic format observers
707*cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
708*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
7090eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
7100eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
7110eae32dcSDimitry Andric     _Str __s   = string<_ECharT, _Traits, _Allocator>(__a);
7120eae32dcSDimitry Andric     // Note: This (and generic_u8string below) is slightly suboptimal as
7130eae32dcSDimitry Andric     // it iterates twice over the string; once to convert it to the right
7140eae32dcSDimitry Andric     // character type, and once to replace path delimiters.
715*cb14a3feSDimitry Andric     std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
7160eae32dcSDimitry Andric     return __s;
7170eae32dcSDimitry Andric   }
7180eae32dcSDimitry Andric 
7195f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }
7205f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }
7215f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }
722*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {
7230eae32dcSDimitry Andric     __u8_string __s = u8string();
7245f757f3fSDimitry Andric     std::replace(__s.begin(), __s.end(), '\\', '/');
7250eae32dcSDimitry Andric     return __s;
7260eae32dcSDimitry Andric   }
7270eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7280eae32dcSDimitry Andric #  else    /* _LIBCPP_WIN32API */
7290eae32dcSDimitry Andric 
7305f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }
7310eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
7325f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
7330eae32dcSDimitry Andric #    else
7345f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }
7350eae32dcSDimitry Andric #    endif
7360eae32dcSDimitry Andric 
7370eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
738*cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
739*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
7400eae32dcSDimitry Andric     using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
7410eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
7420eae32dcSDimitry Andric     _Str __s(__a);
7430eae32dcSDimitry Andric     __s.reserve(__pn_.size());
744bdd1243dSDimitry Andric     _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
7450eae32dcSDimitry Andric     return __s;
7460eae32dcSDimitry Andric   }
7470eae32dcSDimitry Andric 
7480eae32dcSDimitry Andric #      ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
749*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }
7500eae32dcSDimitry Andric #      endif
751*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
752*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
7530eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7540eae32dcSDimitry Andric 
7550eae32dcSDimitry Andric   // generic format observers
7565f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }
7570eae32dcSDimitry Andric #    ifndef _LIBCPP_HAS_NO_CHAR8_T
7585f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
7590eae32dcSDimitry Andric #    else
7605f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }
7610eae32dcSDimitry Andric #    endif
7620eae32dcSDimitry Andric 
7630eae32dcSDimitry Andric #    if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
764*cb14a3feSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
765*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
7660eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
7670eae32dcSDimitry Andric     return string<_ECharT, _Traits, _Allocator>(__a);
7680eae32dcSDimitry Andric   }
7690eae32dcSDimitry Andric 
7700eae32dcSDimitry Andric #      ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
7715f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }
7720eae32dcSDimitry Andric #      endif
7735f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }
7745f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }
7750eae32dcSDimitry Andric #    endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
7760eae32dcSDimitry Andric #  endif   /* !_LIBCPP_WIN32API */
7770eae32dcSDimitry Andric 
7780eae32dcSDimitry Andric private:
7790eae32dcSDimitry Andric   int __compare(__string_view) const;
7800eae32dcSDimitry Andric   __string_view __root_name() const;
7810eae32dcSDimitry Andric   __string_view __root_directory() const;
7820eae32dcSDimitry Andric   __string_view __root_path_raw() const;
7830eae32dcSDimitry Andric   __string_view __relative_path() const;
7840eae32dcSDimitry Andric   __string_view __parent_path() const;
7850eae32dcSDimitry Andric   __string_view __filename() const;
7860eae32dcSDimitry Andric   __string_view __stem() const;
7870eae32dcSDimitry Andric   __string_view __extension() const;
7880eae32dcSDimitry Andric 
7890eae32dcSDimitry Andric public:
7900eae32dcSDimitry Andric   // compare
791*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }
792*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }
793*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }
794*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }
7950eae32dcSDimitry Andric 
7960eae32dcSDimitry Andric   // decomposition
797*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }
798*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }
79981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_path() const {
8000eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
8010eae32dcSDimitry Andric     return string_type(__root_path_raw());
8020eae32dcSDimitry Andric #  else
8030eae32dcSDimitry Andric     return root_name().append(string_type(__root_directory()));
8040eae32dcSDimitry Andric #  endif
8050eae32dcSDimitry Andric   }
806*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }
807*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }
808*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }
80981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
810*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }
8110eae32dcSDimitry Andric 
8120eae32dcSDimitry Andric   // query
813*cb14a3feSDimitry Andric   _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }
8140eae32dcSDimitry Andric 
815*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }
816*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }
817*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }
818*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }
819*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }
820*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }
82181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
822*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }
8230eae32dcSDimitry Andric 
82481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
8250eae32dcSDimitry Andric #  if defined(_LIBCPP_WIN32API)
8260eae32dcSDimitry Andric     __string_view __root_name_str = __root_name();
8270eae32dcSDimitry Andric     __string_view __root_dir      = __root_directory();
8280eae32dcSDimitry Andric     if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
8290eae32dcSDimitry Andric       // A drive letter with no root directory is relative, e.g. x:example.
8300eae32dcSDimitry Andric       return !__root_dir.empty();
8310eae32dcSDimitry Andric     }
8320eae32dcSDimitry Andric     // If no root name, it's relative, e.g. \example is relative to the current drive
8330eae32dcSDimitry Andric     if (__root_name_str.empty())
8340eae32dcSDimitry Andric       return false;
8350eae32dcSDimitry Andric     if (__root_name_str.size() < 3)
8360eae32dcSDimitry Andric       return false;
8370eae32dcSDimitry Andric     // A server root name, like \\server, is always absolute
8380eae32dcSDimitry Andric     if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
8390eae32dcSDimitry Andric       return false;
8400eae32dcSDimitry Andric     if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
8410eae32dcSDimitry Andric       return false;
8420eae32dcSDimitry Andric     // Seems to be a server root name
8430eae32dcSDimitry Andric     return true;
8440eae32dcSDimitry Andric #  else
8450eae32dcSDimitry Andric     return has_root_directory();
8460eae32dcSDimitry Andric #  endif
8470eae32dcSDimitry Andric   }
84881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
8490eae32dcSDimitry Andric 
8500eae32dcSDimitry Andric   // relative paths
8510eae32dcSDimitry Andric   path lexically_normal() const;
8520eae32dcSDimitry Andric   path lexically_relative(const path& __base) const;
8530eae32dcSDimitry Andric 
85481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
8550eae32dcSDimitry Andric     path __result = this->lexically_relative(__base);
8560eae32dcSDimitry Andric     if (__result.native().empty())
8570eae32dcSDimitry Andric       return *this;
8580eae32dcSDimitry Andric     return __result;
8590eae32dcSDimitry Andric   }
8600eae32dcSDimitry Andric 
8610eae32dcSDimitry Andric   // iterators
86206c3fb27SDimitry Andric   class _LIBCPP_EXPORTED_FROM_ABI iterator;
8630eae32dcSDimitry Andric   typedef iterator const_iterator;
8640eae32dcSDimitry Andric 
8650eae32dcSDimitry Andric   iterator begin() const;
8660eae32dcSDimitry Andric   iterator end() const;
8670eae32dcSDimitry Andric 
8680eae32dcSDimitry Andric #  if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
869*cb14a3feSDimitry Andric   template <
870*cb14a3feSDimitry Andric       class _CharT,
871*cb14a3feSDimitry Andric       class _Traits,
872*cb14a3feSDimitry Andric       __enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>
873*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
8740eae32dcSDimitry Andric   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
8755f757f3fSDimitry Andric     __os << std::__quoted(__p.native());
8760eae32dcSDimitry Andric     return __os;
8770eae32dcSDimitry Andric   }
8780eae32dcSDimitry Andric 
879*cb14a3feSDimitry Andric   template <
880*cb14a3feSDimitry Andric       class _CharT,
881*cb14a3feSDimitry Andric       class _Traits,
882*cb14a3feSDimitry Andric       __enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>
883*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
8840eae32dcSDimitry Andric   operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
8855f757f3fSDimitry Andric     __os << std::__quoted(__p.string<_CharT, _Traits>());
8860eae32dcSDimitry Andric     return __os;
8870eae32dcSDimitry Andric   }
8880eae32dcSDimitry Andric 
8890eae32dcSDimitry Andric   template <class _CharT, class _Traits>
89081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
8910eae32dcSDimitry Andric   operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
8920eae32dcSDimitry Andric     basic_string<_CharT, _Traits> __tmp;
8935f757f3fSDimitry Andric     __is >> std::__quoted(__tmp);
8940eae32dcSDimitry Andric     __p = __tmp;
8950eae32dcSDimitry Andric     return __is;
8960eae32dcSDimitry Andric   }
8970eae32dcSDimitry Andric #  endif // !_LIBCPP_HAS_NO_LOCALIZATION
8980eae32dcSDimitry Andric 
8990eae32dcSDimitry Andric private:
9005f757f3fSDimitry Andric   inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {
9010eae32dcSDimitry Andric     __pn_ = string_type(__s);
9020eae32dcSDimitry Andric     return *this;
9030eae32dcSDimitry Andric   }
9040eae32dcSDimitry Andric   string_type __pn_;
9050eae32dcSDimitry Andric };
9060eae32dcSDimitry Andric 
907*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
9080eae32dcSDimitry Andric 
90906c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
9100eae32dcSDimitry Andric 
91106c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
9120eae32dcSDimitry Andric 
9130eae32dcSDimitry Andric _LIBCPP_END_NAMESPACE_FILESYSTEM
9140eae32dcSDimitry Andric 
91506c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
91606c3fb27SDimitry Andric 
91706c3fb27SDimitry Andric template <>
9185f757f3fSDimitry Andric struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {
9195f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {
9205f757f3fSDimitry Andric     return filesystem::hash_value(__p);
92106c3fb27SDimitry Andric   }
92206c3fb27SDimitry Andric };
92306c3fb27SDimitry Andric 
92406c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
92506c3fb27SDimitry Andric 
9265f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 17
9270eae32dcSDimitry Andric 
9280eae32dcSDimitry Andric #endif // _LIBCPP___FILESYSTEM_PATH_H
929