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