1*4bdff4beSrobert // -*- C++ -*- 2*4bdff4beSrobert //===----------------------------------------------------------------------===// 3*4bdff4beSrobert // 4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information. 6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4bdff4beSrobert // 8*4bdff4beSrobert //===----------------------------------------------------------------------===// 9*4bdff4beSrobert 10*4bdff4beSrobert #ifndef _LIBCPP___FILESYSTEM_PATH_H 11*4bdff4beSrobert #define _LIBCPP___FILESYSTEM_PATH_H 12*4bdff4beSrobert 13*4bdff4beSrobert #include <__algorithm/replace.h> 14*4bdff4beSrobert #include <__algorithm/replace_copy.h> 15*4bdff4beSrobert #include <__availability> 16*4bdff4beSrobert #include <__config> 17*4bdff4beSrobert #include <__iterator/back_insert_iterator.h> 18*4bdff4beSrobert #include <__iterator/iterator_traits.h> 19*4bdff4beSrobert #include <cstddef> 20*4bdff4beSrobert #include <string> 21*4bdff4beSrobert #include <string_view> 22*4bdff4beSrobert #include <type_traits> 23*4bdff4beSrobert 24*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 25*4bdff4beSrobert # include <iomanip> // for quoted 26*4bdff4beSrobert # include <locale> 27*4bdff4beSrobert #endif 28*4bdff4beSrobert 29*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30*4bdff4beSrobert # pragma GCC system_header 31*4bdff4beSrobert #endif 32*4bdff4beSrobert 33*4bdff4beSrobert #ifndef _LIBCPP_CXX03_LANG 34*4bdff4beSrobert 35*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM 36*4bdff4beSrobert 37*4bdff4beSrobert _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH 38*4bdff4beSrobert 39*4bdff4beSrobert template <class _Tp> 40*4bdff4beSrobert struct __can_convert_char { 41*4bdff4beSrobert static const bool value = false; 42*4bdff4beSrobert }; 43*4bdff4beSrobert template <class _Tp> 44*4bdff4beSrobert struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {}; 45*4bdff4beSrobert template <> 46*4bdff4beSrobert struct __can_convert_char<char> { 47*4bdff4beSrobert static const bool value = true; 48*4bdff4beSrobert using __char_type = char; 49*4bdff4beSrobert }; 50*4bdff4beSrobert template <> 51*4bdff4beSrobert struct __can_convert_char<wchar_t> { 52*4bdff4beSrobert static const bool value = true; 53*4bdff4beSrobert using __char_type = wchar_t; 54*4bdff4beSrobert }; 55*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T 56*4bdff4beSrobert template <> 57*4bdff4beSrobert struct __can_convert_char<char8_t> { 58*4bdff4beSrobert static const bool value = true; 59*4bdff4beSrobert using __char_type = char8_t; 60*4bdff4beSrobert }; 61*4bdff4beSrobert #endif 62*4bdff4beSrobert template <> 63*4bdff4beSrobert struct __can_convert_char<char16_t> { 64*4bdff4beSrobert static const bool value = true; 65*4bdff4beSrobert using __char_type = char16_t; 66*4bdff4beSrobert }; 67*4bdff4beSrobert template <> 68*4bdff4beSrobert struct __can_convert_char<char32_t> { 69*4bdff4beSrobert static const bool value = true; 70*4bdff4beSrobert using __char_type = char32_t; 71*4bdff4beSrobert }; 72*4bdff4beSrobert 73*4bdff4beSrobert template <class _ECharT> 74*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 75*4bdff4beSrobert typename enable_if<__can_convert_char<_ECharT>::value, bool>::type 76*4bdff4beSrobert __is_separator(_ECharT __e) { 77*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 78*4bdff4beSrobert return __e == _ECharT('/') || __e == _ECharT('\\'); 79*4bdff4beSrobert #else 80*4bdff4beSrobert return __e == _ECharT('/'); 81*4bdff4beSrobert #endif 82*4bdff4beSrobert } 83*4bdff4beSrobert 84*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T 85*4bdff4beSrobert typedef u8string __u8_string; 86*4bdff4beSrobert #else 87*4bdff4beSrobert typedef string __u8_string; 88*4bdff4beSrobert #endif 89*4bdff4beSrobert 90*4bdff4beSrobert struct _NullSentinel {}; 91*4bdff4beSrobert 92*4bdff4beSrobert template <class _Tp> 93*4bdff4beSrobert using _Void = void; 94*4bdff4beSrobert 95*4bdff4beSrobert template <class _Tp, class = void> 96*4bdff4beSrobert struct __is_pathable_string : public false_type {}; 97*4bdff4beSrobert 98*4bdff4beSrobert template <class _ECharT, class _Traits, class _Alloc> 99*4bdff4beSrobert struct __is_pathable_string< 100*4bdff4beSrobert basic_string<_ECharT, _Traits, _Alloc>, 101*4bdff4beSrobert _Void<typename __can_convert_char<_ECharT>::__char_type> > 102*4bdff4beSrobert : public __can_convert_char<_ECharT> { 103*4bdff4beSrobert using _Str = basic_string<_ECharT, _Traits, _Alloc>; 104*4bdff4beSrobert using _Base = __can_convert_char<_ECharT>; 105*4bdff4beSrobert 106*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 107*4bdff4beSrobert static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } 108*4bdff4beSrobert 109*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 110*4bdff4beSrobert static _ECharT const* __range_end(_Str const& __s) { 111*4bdff4beSrobert return __s.data() + __s.length(); 112*4bdff4beSrobert } 113*4bdff4beSrobert 114*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 115*4bdff4beSrobert static _ECharT __first_or_null(_Str const& __s) { 116*4bdff4beSrobert return __s.empty() ? _ECharT{} : __s[0]; 117*4bdff4beSrobert } 118*4bdff4beSrobert }; 119*4bdff4beSrobert 120*4bdff4beSrobert template <class _ECharT, class _Traits> 121*4bdff4beSrobert struct __is_pathable_string< 122*4bdff4beSrobert basic_string_view<_ECharT, _Traits>, 123*4bdff4beSrobert _Void<typename __can_convert_char<_ECharT>::__char_type> > 124*4bdff4beSrobert : public __can_convert_char<_ECharT> { 125*4bdff4beSrobert using _Str = basic_string_view<_ECharT, _Traits>; 126*4bdff4beSrobert using _Base = __can_convert_char<_ECharT>; 127*4bdff4beSrobert 128*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 129*4bdff4beSrobert static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } 130*4bdff4beSrobert 131*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 132*4bdff4beSrobert static _ECharT const* __range_end(_Str const& __s) { 133*4bdff4beSrobert return __s.data() + __s.length(); 134*4bdff4beSrobert } 135*4bdff4beSrobert 136*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 137*4bdff4beSrobert static _ECharT __first_or_null(_Str const& __s) { 138*4bdff4beSrobert return __s.empty() ? _ECharT{} : __s[0]; 139*4bdff4beSrobert } 140*4bdff4beSrobert }; 141*4bdff4beSrobert 142*4bdff4beSrobert template <class _Source, class _DS = typename decay<_Source>::type, 143*4bdff4beSrobert class _UnqualPtrType = 144*4bdff4beSrobert __remove_const_t<__remove_pointer_t<_DS> >, 145*4bdff4beSrobert bool _IsCharPtr = is_pointer<_DS>::value&& 146*4bdff4beSrobert __can_convert_char<_UnqualPtrType>::value> 147*4bdff4beSrobert struct __is_pathable_char_array : false_type {}; 148*4bdff4beSrobert 149*4bdff4beSrobert template <class _Source, class _ECharT, class _UPtr> 150*4bdff4beSrobert struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> 151*4bdff4beSrobert : __can_convert_char<__remove_const_t<_ECharT> > { 152*4bdff4beSrobert using _Base = __can_convert_char<__remove_const_t<_ECharT> >; 153*4bdff4beSrobert 154*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 155*4bdff4beSrobert static _ECharT const* __range_begin(const _ECharT* __b) { return __b; } 156*4bdff4beSrobert 157*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 158*4bdff4beSrobert static _ECharT const* __range_end(const _ECharT* __b) { 159*4bdff4beSrobert using _Iter = const _ECharT*; 160*4bdff4beSrobert const _ECharT __sentinel = _ECharT{}; 161*4bdff4beSrobert _Iter __e = __b; 162*4bdff4beSrobert for (; *__e != __sentinel; ++__e) 163*4bdff4beSrobert ; 164*4bdff4beSrobert return __e; 165*4bdff4beSrobert } 166*4bdff4beSrobert 167*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 168*4bdff4beSrobert static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } 169*4bdff4beSrobert }; 170*4bdff4beSrobert 171*4bdff4beSrobert template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value, 172*4bdff4beSrobert class = void> 173*4bdff4beSrobert struct __is_pathable_iter : false_type {}; 174*4bdff4beSrobert 175*4bdff4beSrobert template <class _Iter> 176*4bdff4beSrobert struct __is_pathable_iter< 177*4bdff4beSrobert _Iter, true, 178*4bdff4beSrobert _Void<typename __can_convert_char< 179*4bdff4beSrobert typename iterator_traits<_Iter>::value_type>::__char_type> > 180*4bdff4beSrobert : __can_convert_char<typename iterator_traits<_Iter>::value_type> { 181*4bdff4beSrobert using _ECharT = typename iterator_traits<_Iter>::value_type; 182*4bdff4beSrobert using _Base = __can_convert_char<_ECharT>; 183*4bdff4beSrobert 184*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 185*4bdff4beSrobert static _Iter __range_begin(_Iter __b) { return __b; } 186*4bdff4beSrobert 187*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 188*4bdff4beSrobert static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; } 189*4bdff4beSrobert 190*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 191*4bdff4beSrobert static _ECharT __first_or_null(_Iter __b) { return *__b; } 192*4bdff4beSrobert }; 193*4bdff4beSrobert 194*4bdff4beSrobert template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value, 195*4bdff4beSrobert bool _IsCharIterT = __is_pathable_char_array<_Tp>::value, 196*4bdff4beSrobert bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value> 197*4bdff4beSrobert struct __is_pathable : false_type { 198*4bdff4beSrobert static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false"); 199*4bdff4beSrobert }; 200*4bdff4beSrobert 201*4bdff4beSrobert template <class _Tp> 202*4bdff4beSrobert struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {}; 203*4bdff4beSrobert 204*4bdff4beSrobert template <class _Tp> 205*4bdff4beSrobert struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> { 206*4bdff4beSrobert }; 207*4bdff4beSrobert 208*4bdff4beSrobert template <class _Tp> 209*4bdff4beSrobert struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {}; 210*4bdff4beSrobert 211*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 212*4bdff4beSrobert typedef wstring __path_string; 213*4bdff4beSrobert typedef wchar_t __path_value; 214*4bdff4beSrobert #else 215*4bdff4beSrobert typedef string __path_string; 216*4bdff4beSrobert typedef char __path_value; 217*4bdff4beSrobert #endif 218*4bdff4beSrobert 219*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 220*4bdff4beSrobert _LIBCPP_FUNC_VIS 221*4bdff4beSrobert size_t __wide_to_char(const wstring&, char*, size_t); 222*4bdff4beSrobert _LIBCPP_FUNC_VIS 223*4bdff4beSrobert size_t __char_to_wide(const string&, wchar_t*, size_t); 224*4bdff4beSrobert #endif 225*4bdff4beSrobert 226*4bdff4beSrobert template <class _ECharT> 227*4bdff4beSrobert struct _PathCVT; 228*4bdff4beSrobert 229*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 230*4bdff4beSrobert template <class _ECharT> 231*4bdff4beSrobert struct _PathCVT { 232*4bdff4beSrobert static_assert(__can_convert_char<_ECharT>::value, 233*4bdff4beSrobert "Char type not convertible"); 234*4bdff4beSrobert 235*4bdff4beSrobert typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower; 236*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 237*4bdff4beSrobert typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener; 238*4bdff4beSrobert #endif 239*4bdff4beSrobert 240*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 241*4bdff4beSrobert static void __append_range(__path_string& __dest, _ECharT const* __b, 242*4bdff4beSrobert _ECharT const* __e) { 243*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 244*4bdff4beSrobert string __utf8; 245*4bdff4beSrobert _Narrower()(back_inserter(__utf8), __b, __e); 246*4bdff4beSrobert _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); 247*4bdff4beSrobert #else 248*4bdff4beSrobert _Narrower()(back_inserter(__dest), __b, __e); 249*4bdff4beSrobert #endif 250*4bdff4beSrobert } 251*4bdff4beSrobert 252*4bdff4beSrobert template <class _Iter> 253*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 254*4bdff4beSrobert static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) { 255*4bdff4beSrobert static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); 256*4bdff4beSrobert if (__b == __e) 257*4bdff4beSrobert return; 258*4bdff4beSrobert basic_string<_ECharT> __tmp(__b, __e); 259*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 260*4bdff4beSrobert string __utf8; 261*4bdff4beSrobert _Narrower()(back_inserter(__utf8), __tmp.data(), 262*4bdff4beSrobert __tmp.data() + __tmp.length()); 263*4bdff4beSrobert _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); 264*4bdff4beSrobert #else 265*4bdff4beSrobert _Narrower()(back_inserter(__dest), __tmp.data(), 266*4bdff4beSrobert __tmp.data() + __tmp.length()); 267*4bdff4beSrobert #endif 268*4bdff4beSrobert } 269*4bdff4beSrobert 270*4bdff4beSrobert template <class _Iter> 271*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 272*4bdff4beSrobert static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { 273*4bdff4beSrobert static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); 274*4bdff4beSrobert const _ECharT __sentinel = _ECharT{}; 275*4bdff4beSrobert if (*__b == __sentinel) 276*4bdff4beSrobert return; 277*4bdff4beSrobert basic_string<_ECharT> __tmp; 278*4bdff4beSrobert for (; *__b != __sentinel; ++__b) 279*4bdff4beSrobert __tmp.push_back(*__b); 280*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 281*4bdff4beSrobert string __utf8; 282*4bdff4beSrobert _Narrower()(back_inserter(__utf8), __tmp.data(), 283*4bdff4beSrobert __tmp.data() + __tmp.length()); 284*4bdff4beSrobert _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); 285*4bdff4beSrobert #else 286*4bdff4beSrobert _Narrower()(back_inserter(__dest), __tmp.data(), 287*4bdff4beSrobert __tmp.data() + __tmp.length()); 288*4bdff4beSrobert #endif 289*4bdff4beSrobert } 290*4bdff4beSrobert 291*4bdff4beSrobert template <class _Source> 292*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 293*4bdff4beSrobert static void __append_source(__path_string& __dest, _Source const& __s) { 294*4bdff4beSrobert using _Traits = __is_pathable<_Source>; 295*4bdff4beSrobert __append_range(__dest, _Traits::__range_begin(__s), 296*4bdff4beSrobert _Traits::__range_end(__s)); 297*4bdff4beSrobert } 298*4bdff4beSrobert }; 299*4bdff4beSrobert #endif // !_LIBCPP_HAS_NO_LOCALIZATION 300*4bdff4beSrobert 301*4bdff4beSrobert template <> 302*4bdff4beSrobert struct _PathCVT<__path_value> { 303*4bdff4beSrobert 304*4bdff4beSrobert template <class _Iter> 305*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 306*4bdff4beSrobert static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type 307*4bdff4beSrobert __append_range(__path_string& __dest, _Iter __b, _Iter __e) { 308*4bdff4beSrobert for (; __b != __e; ++__b) 309*4bdff4beSrobert __dest.push_back(*__b); 310*4bdff4beSrobert } 311*4bdff4beSrobert 312*4bdff4beSrobert template <class _Iter> 313*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 314*4bdff4beSrobert static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type 315*4bdff4beSrobert __append_range(__path_string& __dest, _Iter __b, _Iter __e) { 316*4bdff4beSrobert __dest.append(__b, __e); 317*4bdff4beSrobert } 318*4bdff4beSrobert 319*4bdff4beSrobert template <class _Iter> 320*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 321*4bdff4beSrobert static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { 322*4bdff4beSrobert const char __sentinel = char{}; 323*4bdff4beSrobert for (; *__b != __sentinel; ++__b) 324*4bdff4beSrobert __dest.push_back(*__b); 325*4bdff4beSrobert } 326*4bdff4beSrobert 327*4bdff4beSrobert template <class _Source> 328*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 329*4bdff4beSrobert static void __append_source(__path_string& __dest, _Source const& __s) { 330*4bdff4beSrobert using _Traits = __is_pathable<_Source>; 331*4bdff4beSrobert __append_range(__dest, _Traits::__range_begin(__s), 332*4bdff4beSrobert _Traits::__range_end(__s)); 333*4bdff4beSrobert } 334*4bdff4beSrobert }; 335*4bdff4beSrobert 336*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 337*4bdff4beSrobert template <> 338*4bdff4beSrobert struct _PathCVT<char> { 339*4bdff4beSrobert 340*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 341*4bdff4beSrobert static void 342*4bdff4beSrobert __append_string(__path_string& __dest, const basic_string<char> &__str) { 343*4bdff4beSrobert size_t __size = __char_to_wide(__str, nullptr, 0); 344*4bdff4beSrobert size_t __pos = __dest.size(); 345*4bdff4beSrobert __dest.resize(__pos + __size); 346*4bdff4beSrobert __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size); 347*4bdff4beSrobert } 348*4bdff4beSrobert 349*4bdff4beSrobert template <class _Iter> 350*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 351*4bdff4beSrobert static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type 352*4bdff4beSrobert __append_range(__path_string& __dest, _Iter __b, _Iter __e) { 353*4bdff4beSrobert basic_string<char> __tmp(__b, __e); 354*4bdff4beSrobert __append_string(__dest, __tmp); 355*4bdff4beSrobert } 356*4bdff4beSrobert 357*4bdff4beSrobert template <class _Iter> 358*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 359*4bdff4beSrobert static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type 360*4bdff4beSrobert __append_range(__path_string& __dest, _Iter __b, _Iter __e) { 361*4bdff4beSrobert basic_string<char> __tmp(__b, __e); 362*4bdff4beSrobert __append_string(__dest, __tmp); 363*4bdff4beSrobert } 364*4bdff4beSrobert 365*4bdff4beSrobert template <class _Iter> 366*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 367*4bdff4beSrobert static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { 368*4bdff4beSrobert const char __sentinel = char{}; 369*4bdff4beSrobert basic_string<char> __tmp; 370*4bdff4beSrobert for (; *__b != __sentinel; ++__b) 371*4bdff4beSrobert __tmp.push_back(*__b); 372*4bdff4beSrobert __append_string(__dest, __tmp); 373*4bdff4beSrobert } 374*4bdff4beSrobert 375*4bdff4beSrobert template <class _Source> 376*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 377*4bdff4beSrobert static void __append_source(__path_string& __dest, _Source const& __s) { 378*4bdff4beSrobert using _Traits = __is_pathable<_Source>; 379*4bdff4beSrobert __append_range(__dest, _Traits::__range_begin(__s), 380*4bdff4beSrobert _Traits::__range_end(__s)); 381*4bdff4beSrobert } 382*4bdff4beSrobert }; 383*4bdff4beSrobert 384*4bdff4beSrobert template <class _ECharT> 385*4bdff4beSrobert struct _PathExport { 386*4bdff4beSrobert typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower; 387*4bdff4beSrobert typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener; 388*4bdff4beSrobert 389*4bdff4beSrobert template <class _Str> 390*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 391*4bdff4beSrobert static void __append(_Str& __dest, const __path_string& __src) { 392*4bdff4beSrobert string __utf8; 393*4bdff4beSrobert _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size()); 394*4bdff4beSrobert _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); 395*4bdff4beSrobert } 396*4bdff4beSrobert }; 397*4bdff4beSrobert 398*4bdff4beSrobert template <> 399*4bdff4beSrobert struct _PathExport<char> { 400*4bdff4beSrobert template <class _Str> 401*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 402*4bdff4beSrobert static void __append(_Str& __dest, const __path_string& __src) { 403*4bdff4beSrobert size_t __size = __wide_to_char(__src, nullptr, 0); 404*4bdff4beSrobert size_t __pos = __dest.size(); 405*4bdff4beSrobert __dest.resize(__size); 406*4bdff4beSrobert __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size); 407*4bdff4beSrobert } 408*4bdff4beSrobert }; 409*4bdff4beSrobert 410*4bdff4beSrobert template <> 411*4bdff4beSrobert struct _PathExport<wchar_t> { 412*4bdff4beSrobert template <class _Str> 413*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 414*4bdff4beSrobert static void __append(_Str& __dest, const __path_string& __src) { 415*4bdff4beSrobert __dest.append(__src.begin(), __src.end()); 416*4bdff4beSrobert } 417*4bdff4beSrobert }; 418*4bdff4beSrobert 419*4bdff4beSrobert template <> 420*4bdff4beSrobert struct _PathExport<char16_t> { 421*4bdff4beSrobert template <class _Str> 422*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 423*4bdff4beSrobert static void __append(_Str& __dest, const __path_string& __src) { 424*4bdff4beSrobert __dest.append(__src.begin(), __src.end()); 425*4bdff4beSrobert } 426*4bdff4beSrobert }; 427*4bdff4beSrobert 428*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T 429*4bdff4beSrobert template <> 430*4bdff4beSrobert struct _PathExport<char8_t> { 431*4bdff4beSrobert typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower; 432*4bdff4beSrobert 433*4bdff4beSrobert template <class _Str> 434*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 435*4bdff4beSrobert static void __append(_Str& __dest, const __path_string& __src) { 436*4bdff4beSrobert _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size()); 437*4bdff4beSrobert } 438*4bdff4beSrobert }; 439*4bdff4beSrobert #endif /* !_LIBCPP_HAS_NO_CHAR8_T */ 440*4bdff4beSrobert #endif /* _LIBCPP_WIN32API */ 441*4bdff4beSrobert 442*4bdff4beSrobert class _LIBCPP_TYPE_VIS path { 443*4bdff4beSrobert template <class _SourceOrIter, class _Tp = path&> 444*4bdff4beSrobert using _EnableIfPathable = 445*4bdff4beSrobert typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; 446*4bdff4beSrobert 447*4bdff4beSrobert template <class _Tp> 448*4bdff4beSrobert using _SourceChar = typename __is_pathable<_Tp>::__char_type; 449*4bdff4beSrobert 450*4bdff4beSrobert template <class _Tp> 451*4bdff4beSrobert using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; 452*4bdff4beSrobert 453*4bdff4beSrobert public: 454*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 455*4bdff4beSrobert typedef wchar_t value_type; 456*4bdff4beSrobert static constexpr value_type preferred_separator = L'\\'; 457*4bdff4beSrobert #else 458*4bdff4beSrobert typedef char value_type; 459*4bdff4beSrobert static constexpr value_type preferred_separator = '/'; 460*4bdff4beSrobert #endif 461*4bdff4beSrobert typedef basic_string<value_type> string_type; 462*4bdff4beSrobert typedef basic_string_view<value_type> __string_view; 463*4bdff4beSrobert 464*4bdff4beSrobert enum _LIBCPP_ENUM_VIS format : unsigned char { 465*4bdff4beSrobert auto_format, 466*4bdff4beSrobert native_format, 467*4bdff4beSrobert generic_format 468*4bdff4beSrobert }; 469*4bdff4beSrobert 470*4bdff4beSrobert // constructors and destructor 471*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path() noexcept {} 472*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {} 473*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept 474*4bdff4beSrobert : __pn_(_VSTD::move(__p.__pn_)) {} 475*4bdff4beSrobert 476*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 477*4bdff4beSrobert path(string_type&& __s, format = format::auto_format) noexcept 478*4bdff4beSrobert : __pn_(_VSTD::move(__s)) {} 479*4bdff4beSrobert 480*4bdff4beSrobert template <class _Source, class = _EnableIfPathable<_Source, void> > 481*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 482*4bdff4beSrobert path(const _Source& __src, format = format::auto_format) { 483*4bdff4beSrobert _SourceCVT<_Source>::__append_source(__pn_, __src); 484*4bdff4beSrobert } 485*4bdff4beSrobert 486*4bdff4beSrobert template <class _InputIt> 487*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 488*4bdff4beSrobert path(_InputIt __first, _InputIt __last, format = format::auto_format) { 489*4bdff4beSrobert typedef typename iterator_traits<_InputIt>::value_type _ItVal; 490*4bdff4beSrobert _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); 491*4bdff4beSrobert } 492*4bdff4beSrobert 493*4bdff4beSrobert /* 494*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 495*4bdff4beSrobert // TODO Implement locale conversions. 496*4bdff4beSrobert template <class _Source, class = _EnableIfPathable<_Source, void> > 497*4bdff4beSrobert path(const _Source& __src, const locale& __loc, format = format::auto_format); 498*4bdff4beSrobert template <class _InputIt> 499*4bdff4beSrobert path(_InputIt __first, _InputIt _last, const locale& __loc, 500*4bdff4beSrobert format = format::auto_format); 501*4bdff4beSrobert #endif 502*4bdff4beSrobert */ 503*4bdff4beSrobert 504*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 505*4bdff4beSrobert ~path() = default; 506*4bdff4beSrobert 507*4bdff4beSrobert // assignments 508*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 509*4bdff4beSrobert path& operator=(const path& __p) { 510*4bdff4beSrobert __pn_ = __p.__pn_; 511*4bdff4beSrobert return *this; 512*4bdff4beSrobert } 513*4bdff4beSrobert 514*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 515*4bdff4beSrobert path& operator=(path&& __p) noexcept { 516*4bdff4beSrobert __pn_ = _VSTD::move(__p.__pn_); 517*4bdff4beSrobert return *this; 518*4bdff4beSrobert } 519*4bdff4beSrobert 520*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 521*4bdff4beSrobert path& operator=(string_type&& __s) noexcept { 522*4bdff4beSrobert __pn_ = _VSTD::move(__s); 523*4bdff4beSrobert return *this; 524*4bdff4beSrobert } 525*4bdff4beSrobert 526*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 527*4bdff4beSrobert path& assign(string_type&& __s) noexcept { 528*4bdff4beSrobert __pn_ = _VSTD::move(__s); 529*4bdff4beSrobert return *this; 530*4bdff4beSrobert } 531*4bdff4beSrobert 532*4bdff4beSrobert template <class _Source> 533*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> 534*4bdff4beSrobert operator=(const _Source& __src) { 535*4bdff4beSrobert return this->assign(__src); 536*4bdff4beSrobert } 537*4bdff4beSrobert 538*4bdff4beSrobert template <class _Source> 539*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 540*4bdff4beSrobert _EnableIfPathable<_Source> assign(const _Source& __src) { 541*4bdff4beSrobert __pn_.clear(); 542*4bdff4beSrobert _SourceCVT<_Source>::__append_source(__pn_, __src); 543*4bdff4beSrobert return *this; 544*4bdff4beSrobert } 545*4bdff4beSrobert 546*4bdff4beSrobert template <class _InputIt> 547*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 548*4bdff4beSrobert path& assign(_InputIt __first, _InputIt __last) { 549*4bdff4beSrobert typedef typename iterator_traits<_InputIt>::value_type _ItVal; 550*4bdff4beSrobert __pn_.clear(); 551*4bdff4beSrobert _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); 552*4bdff4beSrobert return *this; 553*4bdff4beSrobert } 554*4bdff4beSrobert 555*4bdff4beSrobert public: 556*4bdff4beSrobert // appends 557*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 558*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 559*4bdff4beSrobert path& operator/=(const path& __p) { 560*4bdff4beSrobert auto __p_root_name = __p.__root_name(); 561*4bdff4beSrobert auto __p_root_name_size = __p_root_name.size(); 562*4bdff4beSrobert if (__p.is_absolute() || 563*4bdff4beSrobert (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) { 564*4bdff4beSrobert __pn_ = __p.__pn_; 565*4bdff4beSrobert return *this; 566*4bdff4beSrobert } 567*4bdff4beSrobert if (__p.has_root_directory()) { 568*4bdff4beSrobert path __root_name_str = root_name(); 569*4bdff4beSrobert __pn_ = __root_name_str.native(); 570*4bdff4beSrobert __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); 571*4bdff4beSrobert return *this; 572*4bdff4beSrobert } 573*4bdff4beSrobert if (has_filename() || (!has_root_directory() && is_absolute())) 574*4bdff4beSrobert __pn_ += preferred_separator; 575*4bdff4beSrobert __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); 576*4bdff4beSrobert return *this; 577*4bdff4beSrobert } 578*4bdff4beSrobert template <class _Source> 579*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> 580*4bdff4beSrobert operator/=(const _Source& __src) { 581*4bdff4beSrobert return operator/=(path(__src)); 582*4bdff4beSrobert } 583*4bdff4beSrobert 584*4bdff4beSrobert template <class _Source> 585*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 586*4bdff4beSrobert _EnableIfPathable<_Source> append(const _Source& __src) { 587*4bdff4beSrobert return operator/=(path(__src)); 588*4bdff4beSrobert } 589*4bdff4beSrobert 590*4bdff4beSrobert template <class _InputIt> 591*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 592*4bdff4beSrobert path& append(_InputIt __first, _InputIt __last) { 593*4bdff4beSrobert return operator/=(path(__first, __last)); 594*4bdff4beSrobert } 595*4bdff4beSrobert #else 596*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 597*4bdff4beSrobert path& operator/=(const path& __p) { 598*4bdff4beSrobert if (__p.is_absolute()) { 599*4bdff4beSrobert __pn_ = __p.__pn_; 600*4bdff4beSrobert return *this; 601*4bdff4beSrobert } 602*4bdff4beSrobert if (has_filename()) 603*4bdff4beSrobert __pn_ += preferred_separator; 604*4bdff4beSrobert __pn_ += __p.native(); 605*4bdff4beSrobert return *this; 606*4bdff4beSrobert } 607*4bdff4beSrobert 608*4bdff4beSrobert // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src 609*4bdff4beSrobert // is known at compile time to be "/' since the user almost certainly intended 610*4bdff4beSrobert // to append a separator instead of overwriting the path with "/" 611*4bdff4beSrobert template <class _Source> 612*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> 613*4bdff4beSrobert operator/=(const _Source& __src) { 614*4bdff4beSrobert return this->append(__src); 615*4bdff4beSrobert } 616*4bdff4beSrobert 617*4bdff4beSrobert template <class _Source> 618*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 619*4bdff4beSrobert _EnableIfPathable<_Source> append(const _Source& __src) { 620*4bdff4beSrobert using _Traits = __is_pathable<_Source>; 621*4bdff4beSrobert using _CVT = _PathCVT<_SourceChar<_Source> >; 622*4bdff4beSrobert bool __source_is_absolute = _VSTD_FS::__is_separator(_Traits::__first_or_null(__src)); 623*4bdff4beSrobert if (__source_is_absolute) 624*4bdff4beSrobert __pn_.clear(); 625*4bdff4beSrobert else if (has_filename()) 626*4bdff4beSrobert __pn_ += preferred_separator; 627*4bdff4beSrobert _CVT::__append_source(__pn_, __src); 628*4bdff4beSrobert return *this; 629*4bdff4beSrobert } 630*4bdff4beSrobert 631*4bdff4beSrobert template <class _InputIt> 632*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 633*4bdff4beSrobert path& append(_InputIt __first, _InputIt __last) { 634*4bdff4beSrobert typedef typename iterator_traits<_InputIt>::value_type _ItVal; 635*4bdff4beSrobert static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); 636*4bdff4beSrobert using _CVT = _PathCVT<_ItVal>; 637*4bdff4beSrobert if (__first != __last && _VSTD_FS::__is_separator(*__first)) 638*4bdff4beSrobert __pn_.clear(); 639*4bdff4beSrobert else if (has_filename()) 640*4bdff4beSrobert __pn_ += preferred_separator; 641*4bdff4beSrobert _CVT::__append_range(__pn_, __first, __last); 642*4bdff4beSrobert return *this; 643*4bdff4beSrobert } 644*4bdff4beSrobert #endif 645*4bdff4beSrobert 646*4bdff4beSrobert // concatenation 647*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 648*4bdff4beSrobert path& operator+=(const path& __x) { 649*4bdff4beSrobert __pn_ += __x.__pn_; 650*4bdff4beSrobert return *this; 651*4bdff4beSrobert } 652*4bdff4beSrobert 653*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 654*4bdff4beSrobert path& operator+=(const string_type& __x) { 655*4bdff4beSrobert __pn_ += __x; 656*4bdff4beSrobert return *this; 657*4bdff4beSrobert } 658*4bdff4beSrobert 659*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 660*4bdff4beSrobert path& operator+=(__string_view __x) { 661*4bdff4beSrobert __pn_ += __x; 662*4bdff4beSrobert return *this; 663*4bdff4beSrobert } 664*4bdff4beSrobert 665*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 666*4bdff4beSrobert path& operator+=(const value_type* __x) { 667*4bdff4beSrobert __pn_ += __x; 668*4bdff4beSrobert return *this; 669*4bdff4beSrobert } 670*4bdff4beSrobert 671*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 672*4bdff4beSrobert path& operator+=(value_type __x) { 673*4bdff4beSrobert __pn_ += __x; 674*4bdff4beSrobert return *this; 675*4bdff4beSrobert } 676*4bdff4beSrobert 677*4bdff4beSrobert template <class _ECharT> 678*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 679*4bdff4beSrobert typename enable_if<__can_convert_char<_ECharT>::value, path&>::type 680*4bdff4beSrobert operator+=(_ECharT __x) { 681*4bdff4beSrobert _PathCVT<_ECharT>::__append_source(__pn_, 682*4bdff4beSrobert basic_string_view<_ECharT>(&__x, 1)); 683*4bdff4beSrobert return *this; 684*4bdff4beSrobert } 685*4bdff4beSrobert 686*4bdff4beSrobert template <class _Source> 687*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 688*4bdff4beSrobert _EnableIfPathable<_Source> operator+=(const _Source& __x) { 689*4bdff4beSrobert return this->concat(__x); 690*4bdff4beSrobert } 691*4bdff4beSrobert 692*4bdff4beSrobert template <class _Source> 693*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 694*4bdff4beSrobert _EnableIfPathable<_Source> concat(const _Source& __x) { 695*4bdff4beSrobert _SourceCVT<_Source>::__append_source(__pn_, __x); 696*4bdff4beSrobert return *this; 697*4bdff4beSrobert } 698*4bdff4beSrobert 699*4bdff4beSrobert template <class _InputIt> 700*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 701*4bdff4beSrobert path& concat(_InputIt __first, _InputIt __last) { 702*4bdff4beSrobert typedef typename iterator_traits<_InputIt>::value_type _ItVal; 703*4bdff4beSrobert _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); 704*4bdff4beSrobert return *this; 705*4bdff4beSrobert } 706*4bdff4beSrobert 707*4bdff4beSrobert // modifiers 708*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 709*4bdff4beSrobert void clear() noexcept { __pn_.clear(); } 710*4bdff4beSrobert 711*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 712*4bdff4beSrobert path& make_preferred() { 713*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 714*4bdff4beSrobert _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\'); 715*4bdff4beSrobert #endif 716*4bdff4beSrobert return *this; 717*4bdff4beSrobert } 718*4bdff4beSrobert 719*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 720*4bdff4beSrobert path& remove_filename() { 721*4bdff4beSrobert auto __fname = __filename(); 722*4bdff4beSrobert if (!__fname.empty()) 723*4bdff4beSrobert __pn_.erase(__fname.data() - __pn_.data()); 724*4bdff4beSrobert return *this; 725*4bdff4beSrobert } 726*4bdff4beSrobert 727*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 728*4bdff4beSrobert path& replace_filename(const path& __replacement) { 729*4bdff4beSrobert remove_filename(); 730*4bdff4beSrobert return (*this /= __replacement); 731*4bdff4beSrobert } 732*4bdff4beSrobert 733*4bdff4beSrobert path& replace_extension(const path& __replacement = path()); 734*4bdff4beSrobert 735*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept { 736*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) == 0; 737*4bdff4beSrobert } 738*4bdff4beSrobert # if _LIBCPP_STD_VER <= 17 739*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept { 740*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) != 0; 741*4bdff4beSrobert } 742*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept { 743*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) < 0; 744*4bdff4beSrobert } 745*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept { 746*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) <= 0; 747*4bdff4beSrobert } 748*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept { 749*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) > 0; 750*4bdff4beSrobert } 751*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept { 752*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) >= 0; 753*4bdff4beSrobert } 754*4bdff4beSrobert # else // _LIBCPP_STD_VER <= 17 755*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept { 756*4bdff4beSrobert return __lhs.__compare(__rhs.__pn_) <=> 0; 757*4bdff4beSrobert } 758*4bdff4beSrobert # endif // _LIBCPP_STD_VER <= 17 759*4bdff4beSrobert 760*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) { 761*4bdff4beSrobert path __result(__lhs); 762*4bdff4beSrobert __result /= __rhs; 763*4bdff4beSrobert return __result; 764*4bdff4beSrobert } 765*4bdff4beSrobert 766*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 767*4bdff4beSrobert void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } 768*4bdff4beSrobert 769*4bdff4beSrobert // private helper to allow reserving memory in the path 770*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 771*4bdff4beSrobert void __reserve(size_t __s) { __pn_.reserve(__s); } 772*4bdff4beSrobert 773*4bdff4beSrobert // native format observers 774*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 775*4bdff4beSrobert const string_type& native() const noexcept { return __pn_; } 776*4bdff4beSrobert 777*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 778*4bdff4beSrobert const value_type* c_str() const noexcept { return __pn_.c_str(); } 779*4bdff4beSrobert 780*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; } 781*4bdff4beSrobert 782*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 783*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const { return __pn_; } 784*4bdff4beSrobert 785*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 786*4bdff4beSrobert _VSTD::wstring generic_wstring() const { 787*4bdff4beSrobert _VSTD::wstring __s; 788*4bdff4beSrobert __s.resize(__pn_.size()); 789*4bdff4beSrobert _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/'); 790*4bdff4beSrobert return __s; 791*4bdff4beSrobert } 792*4bdff4beSrobert 793*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 794*4bdff4beSrobert template <class _ECharT, class _Traits = char_traits<_ECharT>, 795*4bdff4beSrobert class _Allocator = allocator<_ECharT> > 796*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 797*4bdff4beSrobert basic_string<_ECharT, _Traits, _Allocator> 798*4bdff4beSrobert string(const _Allocator& __a = _Allocator()) const { 799*4bdff4beSrobert using _Str = basic_string<_ECharT, _Traits, _Allocator>; 800*4bdff4beSrobert _Str __s(__a); 801*4bdff4beSrobert __s.reserve(__pn_.size()); 802*4bdff4beSrobert _PathExport<_ECharT>::__append(__s, __pn_); 803*4bdff4beSrobert return __s; 804*4bdff4beSrobert } 805*4bdff4beSrobert 806*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const { 807*4bdff4beSrobert return string<char>(); 808*4bdff4beSrobert } 809*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const { 810*4bdff4beSrobert using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>; 811*4bdff4beSrobert __u8_string __s; 812*4bdff4beSrobert __s.reserve(__pn_.size()); 813*4bdff4beSrobert _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); 814*4bdff4beSrobert return __s; 815*4bdff4beSrobert } 816*4bdff4beSrobert 817*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const { 818*4bdff4beSrobert return string<char16_t>(); 819*4bdff4beSrobert } 820*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const { 821*4bdff4beSrobert return string<char32_t>(); 822*4bdff4beSrobert } 823*4bdff4beSrobert 824*4bdff4beSrobert // generic format observers 825*4bdff4beSrobert template <class _ECharT, class _Traits = char_traits<_ECharT>, 826*4bdff4beSrobert class _Allocator = allocator<_ECharT> > 827*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 828*4bdff4beSrobert basic_string<_ECharT, _Traits, _Allocator> 829*4bdff4beSrobert generic_string(const _Allocator& __a = _Allocator()) const { 830*4bdff4beSrobert using _Str = basic_string<_ECharT, _Traits, _Allocator>; 831*4bdff4beSrobert _Str __s = string<_ECharT, _Traits, _Allocator>(__a); 832*4bdff4beSrobert // Note: This (and generic_u8string below) is slightly suboptimal as 833*4bdff4beSrobert // it iterates twice over the string; once to convert it to the right 834*4bdff4beSrobert // character type, and once to replace path delimiters. 835*4bdff4beSrobert _VSTD::replace(__s.begin(), __s.end(), 836*4bdff4beSrobert static_cast<_ECharT>('\\'), static_cast<_ECharT>('/')); 837*4bdff4beSrobert return __s; 838*4bdff4beSrobert } 839*4bdff4beSrobert 840*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return generic_string<char>(); } 841*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); } 842*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); } 843*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 844*4bdff4beSrobert __u8_string generic_u8string() const { 845*4bdff4beSrobert __u8_string __s = u8string(); 846*4bdff4beSrobert _VSTD::replace(__s.begin(), __s.end(), '\\', '/'); 847*4bdff4beSrobert return __s; 848*4bdff4beSrobert } 849*4bdff4beSrobert #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ 850*4bdff4beSrobert #else /* _LIBCPP_WIN32API */ 851*4bdff4beSrobert 852*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const { return __pn_; } 853*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T 854*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } 855*4bdff4beSrobert #else 856*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string u8string() const { return __pn_; } 857*4bdff4beSrobert #endif 858*4bdff4beSrobert 859*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 860*4bdff4beSrobert template <class _ECharT, class _Traits = char_traits<_ECharT>, 861*4bdff4beSrobert class _Allocator = allocator<_ECharT> > 862*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 863*4bdff4beSrobert basic_string<_ECharT, _Traits, _Allocator> 864*4bdff4beSrobert string(const _Allocator& __a = _Allocator()) const { 865*4bdff4beSrobert using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>; 866*4bdff4beSrobert using _Str = basic_string<_ECharT, _Traits, _Allocator>; 867*4bdff4beSrobert _Str __s(__a); 868*4bdff4beSrobert __s.reserve(__pn_.size()); 869*4bdff4beSrobert _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); 870*4bdff4beSrobert return __s; 871*4bdff4beSrobert } 872*4bdff4beSrobert 873*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 874*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const { 875*4bdff4beSrobert return string<wchar_t>(); 876*4bdff4beSrobert } 877*4bdff4beSrobert #endif 878*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const { 879*4bdff4beSrobert return string<char16_t>(); 880*4bdff4beSrobert } 881*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const { 882*4bdff4beSrobert return string<char32_t>(); 883*4bdff4beSrobert } 884*4bdff4beSrobert #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ 885*4bdff4beSrobert 886*4bdff4beSrobert // generic format observers 887*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return __pn_; } 888*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T 889*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } 890*4bdff4beSrobert #else 891*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_u8string() const { return __pn_; } 892*4bdff4beSrobert #endif 893*4bdff4beSrobert 894*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 895*4bdff4beSrobert template <class _ECharT, class _Traits = char_traits<_ECharT>, 896*4bdff4beSrobert class _Allocator = allocator<_ECharT> > 897*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 898*4bdff4beSrobert basic_string<_ECharT, _Traits, _Allocator> 899*4bdff4beSrobert generic_string(const _Allocator& __a = _Allocator()) const { 900*4bdff4beSrobert return string<_ECharT, _Traits, _Allocator>(__a); 901*4bdff4beSrobert } 902*4bdff4beSrobert 903*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 904*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::wstring generic_wstring() const { return string<wchar_t>(); } 905*4bdff4beSrobert #endif 906*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return string<char16_t>(); } 907*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return string<char32_t>(); } 908*4bdff4beSrobert #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ 909*4bdff4beSrobert #endif /* !_LIBCPP_WIN32API */ 910*4bdff4beSrobert 911*4bdff4beSrobert private: 912*4bdff4beSrobert int __compare(__string_view) const; 913*4bdff4beSrobert __string_view __root_name() const; 914*4bdff4beSrobert __string_view __root_directory() const; 915*4bdff4beSrobert __string_view __root_path_raw() const; 916*4bdff4beSrobert __string_view __relative_path() const; 917*4bdff4beSrobert __string_view __parent_path() const; 918*4bdff4beSrobert __string_view __filename() const; 919*4bdff4beSrobert __string_view __stem() const; 920*4bdff4beSrobert __string_view __extension() const; 921*4bdff4beSrobert 922*4bdff4beSrobert public: 923*4bdff4beSrobert // compare 924*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { 925*4bdff4beSrobert return __compare(__p.__pn_); 926*4bdff4beSrobert } 927*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { 928*4bdff4beSrobert return __compare(__s); 929*4bdff4beSrobert } 930*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { 931*4bdff4beSrobert return __compare(__s); 932*4bdff4beSrobert } 933*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { 934*4bdff4beSrobert return __compare(__s); 935*4bdff4beSrobert } 936*4bdff4beSrobert 937*4bdff4beSrobert // decomposition 938*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path root_name() const { 939*4bdff4beSrobert return string_type(__root_name()); 940*4bdff4beSrobert } 941*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path root_directory() const { 942*4bdff4beSrobert return string_type(__root_directory()); 943*4bdff4beSrobert } 944*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path root_path() const { 945*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 946*4bdff4beSrobert return string_type(__root_path_raw()); 947*4bdff4beSrobert #else 948*4bdff4beSrobert return root_name().append(string_type(__root_directory())); 949*4bdff4beSrobert #endif 950*4bdff4beSrobert } 951*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path relative_path() const { 952*4bdff4beSrobert return string_type(__relative_path()); 953*4bdff4beSrobert } 954*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path parent_path() const { 955*4bdff4beSrobert return string_type(__parent_path()); 956*4bdff4beSrobert } 957*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path filename() const { 958*4bdff4beSrobert return string_type(__filename()); 959*4bdff4beSrobert } 960*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); } 961*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path extension() const { 962*4bdff4beSrobert return string_type(__extension()); 963*4bdff4beSrobert } 964*4bdff4beSrobert 965*4bdff4beSrobert // query 966*4bdff4beSrobert _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool 967*4bdff4beSrobert empty() const noexcept { 968*4bdff4beSrobert return __pn_.empty(); 969*4bdff4beSrobert } 970*4bdff4beSrobert 971*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { 972*4bdff4beSrobert return !__root_name().empty(); 973*4bdff4beSrobert } 974*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { 975*4bdff4beSrobert return !__root_directory().empty(); 976*4bdff4beSrobert } 977*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { 978*4bdff4beSrobert return !__root_path_raw().empty(); 979*4bdff4beSrobert } 980*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { 981*4bdff4beSrobert return !__relative_path().empty(); 982*4bdff4beSrobert } 983*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { 984*4bdff4beSrobert return !__parent_path().empty(); 985*4bdff4beSrobert } 986*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_filename() const { 987*4bdff4beSrobert return !__filename().empty(); 988*4bdff4beSrobert } 989*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); } 990*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool has_extension() const { 991*4bdff4beSrobert return !__extension().empty(); 992*4bdff4beSrobert } 993*4bdff4beSrobert 994*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool is_absolute() const { 995*4bdff4beSrobert #if defined(_LIBCPP_WIN32API) 996*4bdff4beSrobert __string_view __root_name_str = __root_name(); 997*4bdff4beSrobert __string_view __root_dir = __root_directory(); 998*4bdff4beSrobert if (__root_name_str.size() == 2 && __root_name_str[1] == ':') { 999*4bdff4beSrobert // A drive letter with no root directory is relative, e.g. x:example. 1000*4bdff4beSrobert return !__root_dir.empty(); 1001*4bdff4beSrobert } 1002*4bdff4beSrobert // If no root name, it's relative, e.g. \example is relative to the current drive 1003*4bdff4beSrobert if (__root_name_str.empty()) 1004*4bdff4beSrobert return false; 1005*4bdff4beSrobert if (__root_name_str.size() < 3) 1006*4bdff4beSrobert return false; 1007*4bdff4beSrobert // A server root name, like \\server, is always absolute 1008*4bdff4beSrobert if (__root_name_str[0] != '/' && __root_name_str[0] != '\\') 1009*4bdff4beSrobert return false; 1010*4bdff4beSrobert if (__root_name_str[1] != '/' && __root_name_str[1] != '\\') 1011*4bdff4beSrobert return false; 1012*4bdff4beSrobert // Seems to be a server root name 1013*4bdff4beSrobert return true; 1014*4bdff4beSrobert #else 1015*4bdff4beSrobert return has_root_directory(); 1016*4bdff4beSrobert #endif 1017*4bdff4beSrobert } 1018*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); } 1019*4bdff4beSrobert 1020*4bdff4beSrobert // relative paths 1021*4bdff4beSrobert path lexically_normal() const; 1022*4bdff4beSrobert path lexically_relative(const path& __base) const; 1023*4bdff4beSrobert 1024*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const { 1025*4bdff4beSrobert path __result = this->lexically_relative(__base); 1026*4bdff4beSrobert if (__result.native().empty()) 1027*4bdff4beSrobert return *this; 1028*4bdff4beSrobert return __result; 1029*4bdff4beSrobert } 1030*4bdff4beSrobert 1031*4bdff4beSrobert // iterators 1032*4bdff4beSrobert class _LIBCPP_TYPE_VIS iterator; 1033*4bdff4beSrobert typedef iterator const_iterator; 1034*4bdff4beSrobert 1035*4bdff4beSrobert iterator begin() const; 1036*4bdff4beSrobert iterator end() const; 1037*4bdff4beSrobert 1038*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) 1039*4bdff4beSrobert template <class _CharT, class _Traits> 1040*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend 1041*4bdff4beSrobert typename enable_if<is_same<_CharT, value_type>::value && 1042*4bdff4beSrobert is_same<_Traits, char_traits<value_type> >::value, 1043*4bdff4beSrobert basic_ostream<_CharT, _Traits>&>::type 1044*4bdff4beSrobert operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { 1045*4bdff4beSrobert __os << _VSTD::__quoted(__p.native()); 1046*4bdff4beSrobert return __os; 1047*4bdff4beSrobert } 1048*4bdff4beSrobert 1049*4bdff4beSrobert template <class _CharT, class _Traits> 1050*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend 1051*4bdff4beSrobert typename enable_if<!is_same<_CharT, value_type>::value || 1052*4bdff4beSrobert !is_same<_Traits, char_traits<value_type> >::value, 1053*4bdff4beSrobert basic_ostream<_CharT, _Traits>&>::type 1054*4bdff4beSrobert operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { 1055*4bdff4beSrobert __os << _VSTD::__quoted(__p.string<_CharT, _Traits>()); 1056*4bdff4beSrobert return __os; 1057*4bdff4beSrobert } 1058*4bdff4beSrobert 1059*4bdff4beSrobert template <class _CharT, class _Traits> 1060*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>& 1061*4bdff4beSrobert operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) { 1062*4bdff4beSrobert basic_string<_CharT, _Traits> __tmp; 1063*4bdff4beSrobert __is >> _VSTD::__quoted(__tmp); 1064*4bdff4beSrobert __p = __tmp; 1065*4bdff4beSrobert return __is; 1066*4bdff4beSrobert } 1067*4bdff4beSrobert #endif // !_LIBCPP_HAS_NO_LOCALIZATION 1068*4bdff4beSrobert 1069*4bdff4beSrobert private: 1070*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI path& 1071*4bdff4beSrobert __assign_view(__string_view const& __s) noexcept { 1072*4bdff4beSrobert __pn_ = string_type(__s); 1073*4bdff4beSrobert return *this; 1074*4bdff4beSrobert } 1075*4bdff4beSrobert string_type __pn_; 1076*4bdff4beSrobert }; 1077*4bdff4beSrobert 1078*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { 1079*4bdff4beSrobert __lhs.swap(__rhs); 1080*4bdff4beSrobert } 1081*4bdff4beSrobert 1082*4bdff4beSrobert _LIBCPP_FUNC_VIS 1083*4bdff4beSrobert size_t hash_value(const path& __p) noexcept; 1084*4bdff4beSrobert 1085*4bdff4beSrobert _LIBCPP_AVAILABILITY_FILESYSTEM_POP 1086*4bdff4beSrobert 1087*4bdff4beSrobert _LIBCPP_END_NAMESPACE_FILESYSTEM 1088*4bdff4beSrobert 1089*4bdff4beSrobert #endif // _LIBCPP_CXX03_LANG 1090*4bdff4beSrobert 1091*4bdff4beSrobert #endif // _LIBCPP___FILESYSTEM_PATH_H 1092