xref: /freebsd-src/contrib/llvm-project/libcxx/include/__filesystem/path.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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>
17*06c3fb27SDimitry Andric #include <__functional/hash.h>
18*06c3fb27SDimitry Andric #include <__functional/unary_function.h>
19*06c3fb27SDimitry Andric #include <__fwd/hash.h>
200eae32dcSDimitry Andric #include <__iterator/back_insert_iterator.h>
210eae32dcSDimitry Andric #include <__iterator/iterator_traits.h>
22*06c3fb27SDimitry Andric #include <__type_traits/decay.h>
23*06c3fb27SDimitry Andric #include <__type_traits/is_pointer.h>
24*06c3fb27SDimitry Andric #include <__type_traits/remove_const.h>
25*06c3fb27SDimitry 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 
390eae32dcSDimitry Andric #ifndef _LIBCPP_CXX03_LANG
400eae32dcSDimitry Andric 
410eae32dcSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
420eae32dcSDimitry Andric 
43*06c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric template <class _Tp>
460eae32dcSDimitry Andric struct __can_convert_char {
470eae32dcSDimitry Andric   static const bool value = false;
480eae32dcSDimitry Andric };
490eae32dcSDimitry Andric template <class _Tp>
500eae32dcSDimitry Andric struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
510eae32dcSDimitry Andric template <>
520eae32dcSDimitry Andric struct __can_convert_char<char> {
530eae32dcSDimitry Andric   static const bool value = true;
540eae32dcSDimitry Andric   using __char_type = char;
550eae32dcSDimitry Andric };
560eae32dcSDimitry Andric template <>
570eae32dcSDimitry Andric struct __can_convert_char<wchar_t> {
580eae32dcSDimitry Andric   static const bool value = true;
590eae32dcSDimitry Andric   using __char_type = wchar_t;
600eae32dcSDimitry Andric };
610eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
620eae32dcSDimitry Andric template <>
630eae32dcSDimitry Andric struct __can_convert_char<char8_t> {
640eae32dcSDimitry Andric   static const bool value = true;
650eae32dcSDimitry Andric   using __char_type = char8_t;
660eae32dcSDimitry Andric };
670eae32dcSDimitry Andric #endif
680eae32dcSDimitry Andric template <>
690eae32dcSDimitry Andric struct __can_convert_char<char16_t> {
700eae32dcSDimitry Andric   static const bool value = true;
710eae32dcSDimitry Andric   using __char_type = char16_t;
720eae32dcSDimitry Andric };
730eae32dcSDimitry Andric template <>
740eae32dcSDimitry Andric struct __can_convert_char<char32_t> {
750eae32dcSDimitry Andric   static const bool value = true;
760eae32dcSDimitry Andric   using __char_type = char32_t;
770eae32dcSDimitry Andric };
780eae32dcSDimitry Andric 
790eae32dcSDimitry Andric template <class _ECharT>
8081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI
810eae32dcSDimitry Andric typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
820eae32dcSDimitry Andric __is_separator(_ECharT __e) {
830eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
840eae32dcSDimitry Andric   return __e == _ECharT('/') || __e == _ECharT('\\');
850eae32dcSDimitry Andric #else
860eae32dcSDimitry Andric   return __e == _ECharT('/');
870eae32dcSDimitry Andric #endif
880eae32dcSDimitry Andric }
890eae32dcSDimitry Andric 
900eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
910eae32dcSDimitry Andric typedef u8string __u8_string;
920eae32dcSDimitry Andric #else
930eae32dcSDimitry Andric typedef string __u8_string;
940eae32dcSDimitry Andric #endif
950eae32dcSDimitry Andric 
960eae32dcSDimitry Andric struct _NullSentinel {};
970eae32dcSDimitry Andric 
980eae32dcSDimitry Andric template <class _Tp>
990eae32dcSDimitry Andric using _Void = void;
1000eae32dcSDimitry Andric 
1010eae32dcSDimitry Andric template <class _Tp, class = void>
1020eae32dcSDimitry Andric struct __is_pathable_string : public false_type {};
1030eae32dcSDimitry Andric 
1040eae32dcSDimitry Andric template <class _ECharT, class _Traits, class _Alloc>
1050eae32dcSDimitry Andric struct __is_pathable_string<
1060eae32dcSDimitry Andric     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>;
1100eae32dcSDimitry Andric   using _Base = __can_convert_char<_ECharT>;
11181ad6265SDimitry Andric 
11281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1130eae32dcSDimitry Andric   static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
11481ad6265SDimitry Andric 
11581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1160eae32dcSDimitry Andric   static _ECharT const* __range_end(_Str const& __s) {
1170eae32dcSDimitry Andric     return __s.data() + __s.length();
1180eae32dcSDimitry Andric   }
11981ad6265SDimitry Andric 
12081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1210eae32dcSDimitry Andric   static _ECharT __first_or_null(_Str const& __s) {
1220eae32dcSDimitry Andric     return __s.empty() ? _ECharT{} : __s[0];
1230eae32dcSDimitry Andric   }
1240eae32dcSDimitry Andric };
1250eae32dcSDimitry Andric 
1260eae32dcSDimitry Andric template <class _ECharT, class _Traits>
1270eae32dcSDimitry Andric struct __is_pathable_string<
1280eae32dcSDimitry Andric     basic_string_view<_ECharT, _Traits>,
1290eae32dcSDimitry Andric     _Void<typename __can_convert_char<_ECharT>::__char_type> >
1300eae32dcSDimitry Andric     : public __can_convert_char<_ECharT> {
1310eae32dcSDimitry Andric   using _Str = basic_string_view<_ECharT, _Traits>;
1320eae32dcSDimitry Andric   using _Base = __can_convert_char<_ECharT>;
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1350eae32dcSDimitry Andric   static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
13681ad6265SDimitry Andric 
13781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1380eae32dcSDimitry Andric   static _ECharT const* __range_end(_Str const& __s) {
1390eae32dcSDimitry Andric     return __s.data() + __s.length();
1400eae32dcSDimitry Andric   }
14181ad6265SDimitry Andric 
14281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1430eae32dcSDimitry Andric   static _ECharT __first_or_null(_Str const& __s) {
1440eae32dcSDimitry Andric     return __s.empty() ? _ECharT{} : __s[0];
1450eae32dcSDimitry Andric   }
1460eae32dcSDimitry Andric };
1470eae32dcSDimitry Andric 
148*06c3fb27SDimitry Andric template <class _Source, class _DS = __decay_t<_Source>,
1490eae32dcSDimitry Andric           class _UnqualPtrType =
150bdd1243dSDimitry Andric               __remove_const_t<__remove_pointer_t<_DS> >,
1510eae32dcSDimitry Andric           bool _IsCharPtr = is_pointer<_DS>::value&&
1520eae32dcSDimitry Andric               __can_convert_char<_UnqualPtrType>::value>
1530eae32dcSDimitry Andric struct __is_pathable_char_array : false_type {};
1540eae32dcSDimitry Andric 
1550eae32dcSDimitry Andric template <class _Source, class _ECharT, class _UPtr>
1560eae32dcSDimitry Andric struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
157bdd1243dSDimitry Andric     : __can_convert_char<__remove_const_t<_ECharT> > {
158bdd1243dSDimitry Andric   using _Base = __can_convert_char<__remove_const_t<_ECharT> >;
1590eae32dcSDimitry Andric 
16081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1610eae32dcSDimitry Andric   static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
16281ad6265SDimitry Andric 
16381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1640eae32dcSDimitry Andric   static _ECharT const* __range_end(const _ECharT* __b) {
1650eae32dcSDimitry Andric     using _Iter = const _ECharT*;
1660eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
1670eae32dcSDimitry Andric     _Iter __e = __b;
1680eae32dcSDimitry Andric     for (; *__e != __sentinel; ++__e)
1690eae32dcSDimitry Andric       ;
1700eae32dcSDimitry Andric     return __e;
1710eae32dcSDimitry Andric   }
1720eae32dcSDimitry Andric 
17381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1740eae32dcSDimitry Andric   static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
1750eae32dcSDimitry Andric };
1760eae32dcSDimitry Andric 
177*06c3fb27SDimitry Andric template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value,
1780eae32dcSDimitry Andric           class = void>
1790eae32dcSDimitry Andric struct __is_pathable_iter : false_type {};
1800eae32dcSDimitry Andric 
1810eae32dcSDimitry Andric template <class _Iter>
1820eae32dcSDimitry Andric struct __is_pathable_iter<
1830eae32dcSDimitry Andric     _Iter, true,
1840eae32dcSDimitry Andric     _Void<typename __can_convert_char<
1850eae32dcSDimitry Andric         typename iterator_traits<_Iter>::value_type>::__char_type> >
1860eae32dcSDimitry Andric     : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
1870eae32dcSDimitry Andric   using _ECharT = typename iterator_traits<_Iter>::value_type;
1880eae32dcSDimitry Andric   using _Base = __can_convert_char<_ECharT>;
1890eae32dcSDimitry Andric 
19081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1910eae32dcSDimitry Andric   static _Iter __range_begin(_Iter __b) { return __b; }
19281ad6265SDimitry Andric 
19381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1940eae32dcSDimitry Andric   static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
1950eae32dcSDimitry Andric 
19681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
1970eae32dcSDimitry Andric   static _ECharT __first_or_null(_Iter __b) { return *__b; }
1980eae32dcSDimitry Andric };
1990eae32dcSDimitry Andric 
2000eae32dcSDimitry Andric template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
2010eae32dcSDimitry Andric           bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
2020eae32dcSDimitry Andric           bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
2030eae32dcSDimitry Andric struct __is_pathable : false_type {
2040eae32dcSDimitry Andric   static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
2050eae32dcSDimitry Andric };
2060eae32dcSDimitry Andric 
2070eae32dcSDimitry Andric template <class _Tp>
2080eae32dcSDimitry Andric struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
2090eae32dcSDimitry Andric 
2100eae32dcSDimitry Andric template <class _Tp>
2110eae32dcSDimitry Andric struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
2120eae32dcSDimitry Andric };
2130eae32dcSDimitry Andric 
2140eae32dcSDimitry Andric template <class _Tp>
2150eae32dcSDimitry Andric struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
2160eae32dcSDimitry Andric 
2170eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
2180eae32dcSDimitry Andric typedef wstring __path_string;
2190eae32dcSDimitry Andric typedef wchar_t __path_value;
2200eae32dcSDimitry Andric #else
2210eae32dcSDimitry Andric typedef string __path_string;
2220eae32dcSDimitry Andric typedef char __path_value;
2230eae32dcSDimitry Andric #endif
2240eae32dcSDimitry Andric 
2250eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
226*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
227*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
2280eae32dcSDimitry Andric #endif
2290eae32dcSDimitry Andric 
2300eae32dcSDimitry Andric template <class _ECharT>
2310eae32dcSDimitry Andric struct _PathCVT;
2320eae32dcSDimitry Andric 
2330eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
2340eae32dcSDimitry Andric template <class _ECharT>
2350eae32dcSDimitry Andric struct _PathCVT {
2360eae32dcSDimitry Andric   static_assert(__can_convert_char<_ECharT>::value,
2370eae32dcSDimitry Andric                 "Char type not convertible");
2380eae32dcSDimitry Andric 
2390eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
2400eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
2410eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
2420eae32dcSDimitry Andric #endif
2430eae32dcSDimitry Andric 
24481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
2450eae32dcSDimitry Andric   static void __append_range(__path_string& __dest, _ECharT const* __b,
2460eae32dcSDimitry Andric                              _ECharT const* __e) {
2470eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
2480eae32dcSDimitry Andric     string __utf8;
2490eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __b, __e);
2500eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2510eae32dcSDimitry Andric #else
2520eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __b, __e);
2530eae32dcSDimitry Andric #endif
2540eae32dcSDimitry Andric   }
2550eae32dcSDimitry Andric 
2560eae32dcSDimitry Andric   template <class _Iter>
25781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
2580eae32dcSDimitry Andric   static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
2590eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2600eae32dcSDimitry Andric     if (__b == __e)
2610eae32dcSDimitry Andric       return;
2620eae32dcSDimitry Andric     basic_string<_ECharT> __tmp(__b, __e);
2630eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
2640eae32dcSDimitry Andric     string __utf8;
2650eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(),
2660eae32dcSDimitry Andric                 __tmp.data() + __tmp.length());
2670eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2680eae32dcSDimitry Andric #else
2690eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(),
2700eae32dcSDimitry Andric                 __tmp.data() + __tmp.length());
2710eae32dcSDimitry Andric #endif
2720eae32dcSDimitry Andric   }
2730eae32dcSDimitry Andric 
2740eae32dcSDimitry Andric   template <class _Iter>
27581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
2760eae32dcSDimitry Andric   static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
2770eae32dcSDimitry Andric     static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
2780eae32dcSDimitry Andric     const _ECharT __sentinel = _ECharT{};
2790eae32dcSDimitry Andric     if (*__b == __sentinel)
2800eae32dcSDimitry Andric       return;
2810eae32dcSDimitry Andric     basic_string<_ECharT> __tmp;
2820eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
2830eae32dcSDimitry Andric       __tmp.push_back(*__b);
2840eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
2850eae32dcSDimitry Andric     string __utf8;
2860eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __tmp.data(),
2870eae32dcSDimitry Andric                 __tmp.data() + __tmp.length());
2880eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
2890eae32dcSDimitry Andric #else
2900eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __tmp.data(),
2910eae32dcSDimitry Andric                 __tmp.data() + __tmp.length());
2920eae32dcSDimitry Andric #endif
2930eae32dcSDimitry Andric   }
2940eae32dcSDimitry Andric 
2950eae32dcSDimitry Andric   template <class _Source>
29681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
2970eae32dcSDimitry Andric   static void __append_source(__path_string& __dest, _Source const& __s) {
2980eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
2990eae32dcSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s),
3000eae32dcSDimitry Andric                    _Traits::__range_end(__s));
3010eae32dcSDimitry Andric   }
3020eae32dcSDimitry Andric };
3030eae32dcSDimitry Andric #endif // !_LIBCPP_HAS_NO_LOCALIZATION
3040eae32dcSDimitry Andric 
3050eae32dcSDimitry Andric template <>
3060eae32dcSDimitry Andric struct _PathCVT<__path_value> {
3070eae32dcSDimitry Andric 
3080eae32dcSDimitry Andric   template <class _Iter>
30981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
310*06c3fb27SDimitry Andric   static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type
3110eae32dcSDimitry Andric   __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3120eae32dcSDimitry Andric     for (; __b != __e; ++__b)
3130eae32dcSDimitry Andric       __dest.push_back(*__b);
3140eae32dcSDimitry Andric   }
3150eae32dcSDimitry Andric 
3160eae32dcSDimitry Andric   template <class _Iter>
31781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
318*06c3fb27SDimitry Andric   static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type
3190eae32dcSDimitry Andric   __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3200eae32dcSDimitry Andric     __dest.append(__b, __e);
3210eae32dcSDimitry Andric   }
3220eae32dcSDimitry Andric 
3230eae32dcSDimitry Andric   template <class _Iter>
32481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3250eae32dcSDimitry Andric   static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
3260eae32dcSDimitry Andric     const char __sentinel = char{};
3270eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
3280eae32dcSDimitry Andric       __dest.push_back(*__b);
3290eae32dcSDimitry Andric   }
3300eae32dcSDimitry Andric 
3310eae32dcSDimitry Andric   template <class _Source>
33281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3330eae32dcSDimitry Andric   static void __append_source(__path_string& __dest, _Source const& __s) {
3340eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
3350eae32dcSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s),
3360eae32dcSDimitry Andric                    _Traits::__range_end(__s));
3370eae32dcSDimitry Andric   }
3380eae32dcSDimitry Andric };
3390eae32dcSDimitry Andric 
3400eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
3410eae32dcSDimitry Andric template <>
3420eae32dcSDimitry Andric struct _PathCVT<char> {
3430eae32dcSDimitry Andric 
34481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3450eae32dcSDimitry Andric   static void
3460eae32dcSDimitry Andric   __append_string(__path_string& __dest, const basic_string<char> &__str) {
3470eae32dcSDimitry Andric       size_t __size = __char_to_wide(__str, nullptr, 0);
3480eae32dcSDimitry Andric       size_t __pos = __dest.size();
3490eae32dcSDimitry Andric       __dest.resize(__pos + __size);
3500eae32dcSDimitry Andric       __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
3510eae32dcSDimitry Andric   }
3520eae32dcSDimitry Andric 
3530eae32dcSDimitry Andric   template <class _Iter>
35481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
355*06c3fb27SDimitry Andric   static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type
3560eae32dcSDimitry Andric   __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3570eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3580eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3590eae32dcSDimitry Andric   }
3600eae32dcSDimitry Andric 
3610eae32dcSDimitry Andric   template <class _Iter>
36281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
363*06c3fb27SDimitry Andric   static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type
3640eae32dcSDimitry Andric   __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
3650eae32dcSDimitry Andric     basic_string<char> __tmp(__b, __e);
3660eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3670eae32dcSDimitry Andric   }
3680eae32dcSDimitry Andric 
3690eae32dcSDimitry Andric   template <class _Iter>
37081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3710eae32dcSDimitry Andric   static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
3720eae32dcSDimitry Andric     const char __sentinel = char{};
3730eae32dcSDimitry Andric     basic_string<char> __tmp;
3740eae32dcSDimitry Andric     for (; *__b != __sentinel; ++__b)
3750eae32dcSDimitry Andric       __tmp.push_back(*__b);
3760eae32dcSDimitry Andric     __append_string(__dest, __tmp);
3770eae32dcSDimitry Andric   }
3780eae32dcSDimitry Andric 
3790eae32dcSDimitry Andric   template <class _Source>
38081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3810eae32dcSDimitry Andric   static void __append_source(__path_string& __dest, _Source const& __s) {
3820eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
3830eae32dcSDimitry Andric     __append_range(__dest, _Traits::__range_begin(__s),
3840eae32dcSDimitry Andric                    _Traits::__range_end(__s));
3850eae32dcSDimitry Andric   }
3860eae32dcSDimitry Andric };
3870eae32dcSDimitry Andric 
3880eae32dcSDimitry Andric template <class _ECharT>
3890eae32dcSDimitry Andric struct _PathExport {
3900eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
3910eae32dcSDimitry Andric   typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
3920eae32dcSDimitry Andric 
3930eae32dcSDimitry Andric   template <class _Str>
39481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
3950eae32dcSDimitry Andric   static void __append(_Str& __dest, const __path_string& __src) {
3960eae32dcSDimitry Andric     string __utf8;
3970eae32dcSDimitry Andric     _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
3980eae32dcSDimitry Andric     _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
3990eae32dcSDimitry Andric   }
4000eae32dcSDimitry Andric };
4010eae32dcSDimitry Andric 
4020eae32dcSDimitry Andric template <>
4030eae32dcSDimitry Andric struct _PathExport<char> {
4040eae32dcSDimitry Andric   template <class _Str>
40581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4060eae32dcSDimitry Andric   static void __append(_Str& __dest, const __path_string& __src) {
4070eae32dcSDimitry Andric     size_t __size = __wide_to_char(__src, nullptr, 0);
4080eae32dcSDimitry Andric     size_t __pos = __dest.size();
4090eae32dcSDimitry Andric     __dest.resize(__size);
4100eae32dcSDimitry Andric     __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
4110eae32dcSDimitry Andric   }
4120eae32dcSDimitry Andric };
4130eae32dcSDimitry Andric 
4140eae32dcSDimitry Andric template <>
4150eae32dcSDimitry Andric struct _PathExport<wchar_t> {
4160eae32dcSDimitry Andric   template <class _Str>
41781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4180eae32dcSDimitry Andric   static void __append(_Str& __dest, const __path_string& __src) {
4190eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
4200eae32dcSDimitry Andric   }
4210eae32dcSDimitry Andric };
4220eae32dcSDimitry Andric 
4230eae32dcSDimitry Andric template <>
4240eae32dcSDimitry Andric struct _PathExport<char16_t> {
4250eae32dcSDimitry Andric   template <class _Str>
42681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4270eae32dcSDimitry Andric   static void __append(_Str& __dest, const __path_string& __src) {
4280eae32dcSDimitry Andric     __dest.append(__src.begin(), __src.end());
4290eae32dcSDimitry Andric   }
4300eae32dcSDimitry Andric };
4310eae32dcSDimitry Andric 
4320eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
4330eae32dcSDimitry Andric template <>
4340eae32dcSDimitry Andric struct _PathExport<char8_t> {
4350eae32dcSDimitry Andric   typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
4360eae32dcSDimitry Andric 
4370eae32dcSDimitry Andric   template <class _Str>
43881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4390eae32dcSDimitry Andric   static void __append(_Str& __dest, const __path_string& __src) {
4400eae32dcSDimitry Andric     _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
4410eae32dcSDimitry Andric   }
4420eae32dcSDimitry Andric };
4430eae32dcSDimitry Andric #endif /* !_LIBCPP_HAS_NO_CHAR8_T */
4440eae32dcSDimitry Andric #endif /* _LIBCPP_WIN32API */
4450eae32dcSDimitry Andric 
446*06c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI path {
4470eae32dcSDimitry Andric   template <class _SourceOrIter, class _Tp = path&>
4480eae32dcSDimitry Andric   using _EnableIfPathable =
4490eae32dcSDimitry Andric       typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
4500eae32dcSDimitry Andric 
4510eae32dcSDimitry Andric   template <class _Tp>
4520eae32dcSDimitry Andric   using _SourceChar = typename __is_pathable<_Tp>::__char_type;
4530eae32dcSDimitry Andric 
4540eae32dcSDimitry Andric   template <class _Tp>
4550eae32dcSDimitry Andric   using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
4560eae32dcSDimitry Andric 
4570eae32dcSDimitry Andric public:
4580eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
4590eae32dcSDimitry Andric   typedef wchar_t value_type;
4600eae32dcSDimitry Andric   static constexpr value_type preferred_separator = L'\\';
4610eae32dcSDimitry Andric #else
4620eae32dcSDimitry Andric   typedef char value_type;
4630eae32dcSDimitry Andric   static constexpr value_type preferred_separator = '/';
4640eae32dcSDimitry Andric #endif
4650eae32dcSDimitry Andric   typedef basic_string<value_type> string_type;
4660eae32dcSDimitry Andric   typedef basic_string_view<value_type> __string_view;
4670eae32dcSDimitry Andric 
4680eae32dcSDimitry Andric   enum _LIBCPP_ENUM_VIS format : unsigned char {
4690eae32dcSDimitry Andric     auto_format,
4700eae32dcSDimitry Andric     native_format,
4710eae32dcSDimitry Andric     generic_format
4720eae32dcSDimitry Andric   };
4730eae32dcSDimitry Andric 
4740eae32dcSDimitry Andric   // constructors and destructor
47581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path() noexcept {}
47681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
47781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept
4780eae32dcSDimitry Andric       : __pn_(_VSTD::move(__p.__pn_)) {}
4790eae32dcSDimitry Andric 
48081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4810eae32dcSDimitry Andric   path(string_type&& __s, format = format::auto_format) noexcept
4820eae32dcSDimitry Andric       : __pn_(_VSTD::move(__s)) {}
4830eae32dcSDimitry Andric 
4840eae32dcSDimitry Andric   template <class _Source, class = _EnableIfPathable<_Source, void> >
48581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4860eae32dcSDimitry Andric   path(const _Source& __src, format = format::auto_format) {
4870eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
4880eae32dcSDimitry Andric   }
4890eae32dcSDimitry Andric 
4900eae32dcSDimitry Andric   template <class _InputIt>
49181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4920eae32dcSDimitry Andric   path(_InputIt __first, _InputIt __last, format = format::auto_format) {
4930eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
4940eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
4950eae32dcSDimitry Andric   }
4960eae32dcSDimitry Andric 
4970eae32dcSDimitry Andric /*
4980eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
4990eae32dcSDimitry Andric   // TODO Implement locale conversions.
5000eae32dcSDimitry Andric   template <class _Source, class = _EnableIfPathable<_Source, void> >
5010eae32dcSDimitry Andric   path(const _Source& __src, const locale& __loc, format = format::auto_format);
5020eae32dcSDimitry Andric   template <class _InputIt>
5030eae32dcSDimitry Andric   path(_InputIt __first, _InputIt _last, const locale& __loc,
5040eae32dcSDimitry Andric        format = format::auto_format);
5050eae32dcSDimitry Andric #endif
5060eae32dcSDimitry Andric */
5070eae32dcSDimitry Andric 
50881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5090eae32dcSDimitry Andric   ~path() = default;
5100eae32dcSDimitry Andric 
5110eae32dcSDimitry Andric   // assignments
51281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5130eae32dcSDimitry Andric   path& operator=(const path& __p) {
5140eae32dcSDimitry Andric     __pn_ = __p.__pn_;
5150eae32dcSDimitry Andric     return *this;
5160eae32dcSDimitry Andric   }
5170eae32dcSDimitry Andric 
51881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5190eae32dcSDimitry Andric   path& operator=(path&& __p) noexcept {
5200eae32dcSDimitry Andric     __pn_ = _VSTD::move(__p.__pn_);
5210eae32dcSDimitry Andric     return *this;
5220eae32dcSDimitry Andric   }
5230eae32dcSDimitry Andric 
52481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5250eae32dcSDimitry Andric   path& operator=(string_type&& __s) noexcept {
5260eae32dcSDimitry Andric     __pn_ = _VSTD::move(__s);
5270eae32dcSDimitry Andric     return *this;
5280eae32dcSDimitry Andric   }
5290eae32dcSDimitry Andric 
53081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5310eae32dcSDimitry Andric   path& assign(string_type&& __s) noexcept {
5320eae32dcSDimitry Andric     __pn_ = _VSTD::move(__s);
5330eae32dcSDimitry Andric     return *this;
5340eae32dcSDimitry Andric   }
5350eae32dcSDimitry Andric 
5360eae32dcSDimitry Andric   template <class _Source>
53781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source>
5380eae32dcSDimitry Andric   operator=(const _Source& __src) {
5390eae32dcSDimitry Andric     return this->assign(__src);
5400eae32dcSDimitry Andric   }
5410eae32dcSDimitry Andric 
5420eae32dcSDimitry Andric   template <class _Source>
54381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5440eae32dcSDimitry Andric   _EnableIfPathable<_Source> assign(const _Source& __src) {
5450eae32dcSDimitry Andric     __pn_.clear();
5460eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __src);
5470eae32dcSDimitry Andric     return *this;
5480eae32dcSDimitry Andric   }
5490eae32dcSDimitry Andric 
5500eae32dcSDimitry Andric   template <class _InputIt>
55181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5520eae32dcSDimitry Andric   path& assign(_InputIt __first, _InputIt __last) {
5530eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
5540eae32dcSDimitry Andric     __pn_.clear();
5550eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
5560eae32dcSDimitry Andric     return *this;
5570eae32dcSDimitry Andric   }
5580eae32dcSDimitry Andric 
5590eae32dcSDimitry Andric public:
5600eae32dcSDimitry Andric   // appends
5610eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
56281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5630eae32dcSDimitry Andric   path& operator/=(const path& __p) {
5640eae32dcSDimitry Andric     auto __p_root_name = __p.__root_name();
5650eae32dcSDimitry Andric     auto __p_root_name_size = __p_root_name.size();
5660eae32dcSDimitry Andric     if (__p.is_absolute() ||
5670eae32dcSDimitry Andric         (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
5680eae32dcSDimitry Andric       __pn_ = __p.__pn_;
5690eae32dcSDimitry Andric       return *this;
5700eae32dcSDimitry Andric     }
5710eae32dcSDimitry Andric     if (__p.has_root_directory()) {
5720eae32dcSDimitry Andric       path __root_name_str = root_name();
5730eae32dcSDimitry Andric       __pn_ = __root_name_str.native();
5740eae32dcSDimitry Andric       __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
5750eae32dcSDimitry Andric       return *this;
5760eae32dcSDimitry Andric     }
5770eae32dcSDimitry Andric     if (has_filename() || (!has_root_directory() && is_absolute()))
5780eae32dcSDimitry Andric       __pn_ += preferred_separator;
5790eae32dcSDimitry Andric     __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
5800eae32dcSDimitry Andric     return *this;
5810eae32dcSDimitry Andric   }
5820eae32dcSDimitry Andric   template <class _Source>
5830eae32dcSDimitry Andric   _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
5840eae32dcSDimitry Andric   operator/=(const _Source& __src) {
5850eae32dcSDimitry Andric     return operator/=(path(__src));
5860eae32dcSDimitry Andric   }
5870eae32dcSDimitry Andric 
5880eae32dcSDimitry Andric   template <class _Source>
58981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5900eae32dcSDimitry Andric   _EnableIfPathable<_Source> append(const _Source& __src) {
5910eae32dcSDimitry Andric     return operator/=(path(__src));
5920eae32dcSDimitry Andric   }
5930eae32dcSDimitry Andric 
5940eae32dcSDimitry Andric   template <class _InputIt>
59581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
5960eae32dcSDimitry Andric   path& append(_InputIt __first, _InputIt __last) {
5970eae32dcSDimitry Andric     return operator/=(path(__first, __last));
5980eae32dcSDimitry Andric   }
5990eae32dcSDimitry Andric #else
60081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6010eae32dcSDimitry Andric   path& operator/=(const path& __p) {
6020eae32dcSDimitry Andric     if (__p.is_absolute()) {
6030eae32dcSDimitry Andric       __pn_ = __p.__pn_;
6040eae32dcSDimitry Andric       return *this;
6050eae32dcSDimitry Andric     }
6060eae32dcSDimitry Andric     if (has_filename())
6070eae32dcSDimitry Andric       __pn_ += preferred_separator;
6080eae32dcSDimitry Andric     __pn_ += __p.native();
6090eae32dcSDimitry Andric     return *this;
6100eae32dcSDimitry Andric   }
6110eae32dcSDimitry Andric 
6120eae32dcSDimitry Andric   // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
6130eae32dcSDimitry Andric   // is known at compile time to be "/' since the user almost certainly intended
6140eae32dcSDimitry Andric   // to append a separator instead of overwriting the path with "/"
6150eae32dcSDimitry Andric   template <class _Source>
61681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source>
6170eae32dcSDimitry Andric   operator/=(const _Source& __src) {
6180eae32dcSDimitry Andric     return this->append(__src);
6190eae32dcSDimitry Andric   }
6200eae32dcSDimitry Andric 
6210eae32dcSDimitry Andric   template <class _Source>
62281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6230eae32dcSDimitry Andric   _EnableIfPathable<_Source> append(const _Source& __src) {
6240eae32dcSDimitry Andric     using _Traits = __is_pathable<_Source>;
6250eae32dcSDimitry Andric     using _CVT = _PathCVT<_SourceChar<_Source> >;
626bdd1243dSDimitry Andric     bool __source_is_absolute = _VSTD_FS::__is_separator(_Traits::__first_or_null(__src));
6270eae32dcSDimitry Andric     if (__source_is_absolute)
6280eae32dcSDimitry Andric       __pn_.clear();
6290eae32dcSDimitry Andric     else if (has_filename())
6300eae32dcSDimitry Andric       __pn_ += preferred_separator;
6310eae32dcSDimitry Andric     _CVT::__append_source(__pn_, __src);
6320eae32dcSDimitry Andric     return *this;
6330eae32dcSDimitry Andric   }
6340eae32dcSDimitry Andric 
6350eae32dcSDimitry Andric   template <class _InputIt>
63681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6370eae32dcSDimitry Andric   path& append(_InputIt __first, _InputIt __last) {
6380eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
6390eae32dcSDimitry Andric     static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
6400eae32dcSDimitry Andric     using _CVT = _PathCVT<_ItVal>;
641bdd1243dSDimitry Andric     if (__first != __last && _VSTD_FS::__is_separator(*__first))
6420eae32dcSDimitry Andric       __pn_.clear();
6430eae32dcSDimitry Andric     else if (has_filename())
6440eae32dcSDimitry Andric       __pn_ += preferred_separator;
6450eae32dcSDimitry Andric     _CVT::__append_range(__pn_, __first, __last);
6460eae32dcSDimitry Andric     return *this;
6470eae32dcSDimitry Andric   }
6480eae32dcSDimitry Andric #endif
6490eae32dcSDimitry Andric 
6500eae32dcSDimitry Andric   // concatenation
65181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6520eae32dcSDimitry Andric   path& operator+=(const path& __x) {
6530eae32dcSDimitry Andric     __pn_ += __x.__pn_;
6540eae32dcSDimitry Andric     return *this;
6550eae32dcSDimitry Andric   }
6560eae32dcSDimitry Andric 
65781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6580eae32dcSDimitry Andric   path& operator+=(const string_type& __x) {
6590eae32dcSDimitry Andric     __pn_ += __x;
6600eae32dcSDimitry Andric     return *this;
6610eae32dcSDimitry Andric   }
6620eae32dcSDimitry Andric 
66381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6640eae32dcSDimitry Andric   path& operator+=(__string_view __x) {
6650eae32dcSDimitry Andric     __pn_ += __x;
6660eae32dcSDimitry Andric     return *this;
6670eae32dcSDimitry Andric   }
6680eae32dcSDimitry Andric 
66981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6700eae32dcSDimitry Andric   path& operator+=(const value_type* __x) {
6710eae32dcSDimitry Andric     __pn_ += __x;
6720eae32dcSDimitry Andric     return *this;
6730eae32dcSDimitry Andric   }
6740eae32dcSDimitry Andric 
67581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6760eae32dcSDimitry Andric   path& operator+=(value_type __x) {
6770eae32dcSDimitry Andric     __pn_ += __x;
6780eae32dcSDimitry Andric     return *this;
6790eae32dcSDimitry Andric   }
6800eae32dcSDimitry Andric 
6810eae32dcSDimitry Andric   template <class _ECharT>
68281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6830eae32dcSDimitry Andric   typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
6840eae32dcSDimitry Andric   operator+=(_ECharT __x) {
6850eae32dcSDimitry Andric     _PathCVT<_ECharT>::__append_source(__pn_,
6860eae32dcSDimitry Andric                                        basic_string_view<_ECharT>(&__x, 1));
6870eae32dcSDimitry Andric     return *this;
6880eae32dcSDimitry Andric   }
6890eae32dcSDimitry Andric 
6900eae32dcSDimitry Andric   template <class _Source>
69181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6920eae32dcSDimitry Andric   _EnableIfPathable<_Source> operator+=(const _Source& __x) {
6930eae32dcSDimitry Andric     return this->concat(__x);
6940eae32dcSDimitry Andric   }
6950eae32dcSDimitry Andric 
6960eae32dcSDimitry Andric   template <class _Source>
69781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
6980eae32dcSDimitry Andric   _EnableIfPathable<_Source> concat(const _Source& __x) {
6990eae32dcSDimitry Andric     _SourceCVT<_Source>::__append_source(__pn_, __x);
7000eae32dcSDimitry Andric     return *this;
7010eae32dcSDimitry Andric   }
7020eae32dcSDimitry Andric 
7030eae32dcSDimitry Andric   template <class _InputIt>
70481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7050eae32dcSDimitry Andric   path& concat(_InputIt __first, _InputIt __last) {
7060eae32dcSDimitry Andric     typedef typename iterator_traits<_InputIt>::value_type _ItVal;
7070eae32dcSDimitry Andric     _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
7080eae32dcSDimitry Andric     return *this;
7090eae32dcSDimitry Andric   }
7100eae32dcSDimitry Andric 
7110eae32dcSDimitry Andric   // modifiers
71281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7130eae32dcSDimitry Andric   void clear() noexcept { __pn_.clear(); }
7140eae32dcSDimitry Andric 
71581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7160eae32dcSDimitry Andric   path& make_preferred() {
7170eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
7180eae32dcSDimitry Andric     _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
7190eae32dcSDimitry Andric #endif
7200eae32dcSDimitry Andric     return *this;
7210eae32dcSDimitry Andric   }
7220eae32dcSDimitry Andric 
72381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7240eae32dcSDimitry Andric   path& remove_filename() {
7250eae32dcSDimitry Andric     auto __fname = __filename();
7260eae32dcSDimitry Andric     if (!__fname.empty())
7270eae32dcSDimitry Andric       __pn_.erase(__fname.data() - __pn_.data());
7280eae32dcSDimitry Andric     return *this;
7290eae32dcSDimitry Andric   }
7300eae32dcSDimitry Andric 
73181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7320eae32dcSDimitry Andric   path& replace_filename(const path& __replacement) {
7330eae32dcSDimitry Andric     remove_filename();
7340eae32dcSDimitry Andric     return (*this /= __replacement);
7350eae32dcSDimitry Andric   }
7360eae32dcSDimitry Andric 
7370eae32dcSDimitry Andric   path& replace_extension(const path& __replacement = path());
7380eae32dcSDimitry Andric 
739bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
740bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) == 0;
741bdd1243dSDimitry Andric   }
742bdd1243dSDimitry Andric #  if _LIBCPP_STD_VER <= 17
743bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
744bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) != 0;
745bdd1243dSDimitry Andric   }
746bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {
747bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) < 0;
748bdd1243dSDimitry Andric   }
749bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {
750bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) <= 0;
751bdd1243dSDimitry Andric   }
752bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {
753bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) > 0;
754bdd1243dSDimitry Andric   }
755bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {
756bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) >= 0;
757bdd1243dSDimitry Andric   }
758bdd1243dSDimitry Andric #  else // _LIBCPP_STD_VER <= 17
759bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
760bdd1243dSDimitry Andric     return __lhs.__compare(__rhs.__pn_) <=> 0;
761bdd1243dSDimitry Andric   }
762bdd1243dSDimitry Andric #  endif // _LIBCPP_STD_VER <= 17
763bdd1243dSDimitry Andric 
764bdd1243dSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
765bdd1243dSDimitry Andric     path __result(__lhs);
766bdd1243dSDimitry Andric     __result /= __rhs;
767bdd1243dSDimitry Andric     return __result;
768bdd1243dSDimitry Andric   }
769bdd1243dSDimitry Andric 
77081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7710eae32dcSDimitry Andric   void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
7720eae32dcSDimitry Andric 
7730eae32dcSDimitry Andric   // private helper to allow reserving memory in the path
77481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7750eae32dcSDimitry Andric   void __reserve(size_t __s) { __pn_.reserve(__s); }
7760eae32dcSDimitry Andric 
7770eae32dcSDimitry Andric   // native format observers
77881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7790eae32dcSDimitry Andric   const string_type& native() const noexcept { return __pn_; }
7800eae32dcSDimitry Andric 
78181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7820eae32dcSDimitry Andric   const value_type* c_str() const noexcept { return __pn_.c_str(); }
7830eae32dcSDimitry Andric 
78481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
7850eae32dcSDimitry Andric 
7860eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
78781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const { return __pn_; }
7880eae32dcSDimitry Andric 
78981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
7900eae32dcSDimitry Andric   _VSTD::wstring generic_wstring() const {
7910eae32dcSDimitry Andric     _VSTD::wstring __s;
7920eae32dcSDimitry Andric     __s.resize(__pn_.size());
7930eae32dcSDimitry Andric     _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
7940eae32dcSDimitry Andric     return __s;
7950eae32dcSDimitry Andric   }
7960eae32dcSDimitry Andric 
7970eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
7980eae32dcSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>,
7990eae32dcSDimitry Andric             class _Allocator = allocator<_ECharT> >
80081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
8010eae32dcSDimitry Andric   basic_string<_ECharT, _Traits, _Allocator>
8020eae32dcSDimitry Andric   string(const _Allocator& __a = _Allocator()) const {
8030eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
8040eae32dcSDimitry Andric     _Str __s(__a);
8050eae32dcSDimitry Andric     __s.reserve(__pn_.size());
8060eae32dcSDimitry Andric     _PathExport<_ECharT>::__append(__s, __pn_);
8070eae32dcSDimitry Andric     return __s;
8080eae32dcSDimitry Andric   }
8090eae32dcSDimitry Andric 
81081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const {
8110eae32dcSDimitry Andric     return string<char>();
8120eae32dcSDimitry Andric   }
81381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
8140eae32dcSDimitry Andric     using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
8150eae32dcSDimitry Andric     __u8_string __s;
8160eae32dcSDimitry Andric     __s.reserve(__pn_.size());
8170eae32dcSDimitry Andric     _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
8180eae32dcSDimitry Andric     return __s;
8190eae32dcSDimitry Andric   }
8200eae32dcSDimitry Andric 
82181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const {
8220eae32dcSDimitry Andric     return string<char16_t>();
8230eae32dcSDimitry Andric   }
82481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const {
8250eae32dcSDimitry Andric     return string<char32_t>();
8260eae32dcSDimitry Andric   }
8270eae32dcSDimitry Andric 
8280eae32dcSDimitry Andric   // generic format observers
8290eae32dcSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>,
8300eae32dcSDimitry Andric             class _Allocator = allocator<_ECharT> >
83181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
8320eae32dcSDimitry Andric   basic_string<_ECharT, _Traits, _Allocator>
8330eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
8340eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
8350eae32dcSDimitry Andric     _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
8360eae32dcSDimitry Andric     // Note: This (and generic_u8string below) is slightly suboptimal as
8370eae32dcSDimitry Andric     // it iterates twice over the string; once to convert it to the right
8380eae32dcSDimitry Andric     // character type, and once to replace path delimiters.
8390eae32dcSDimitry Andric     _VSTD::replace(__s.begin(), __s.end(),
8400eae32dcSDimitry Andric                    static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
8410eae32dcSDimitry Andric     return __s;
8420eae32dcSDimitry Andric   }
8430eae32dcSDimitry Andric 
84481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return generic_string<char>(); }
84581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
84681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
84781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
8480eae32dcSDimitry Andric   __u8_string generic_u8string() const {
8490eae32dcSDimitry Andric     __u8_string __s = u8string();
8500eae32dcSDimitry Andric     _VSTD::replace(__s.begin(), __s.end(), '\\', '/');
8510eae32dcSDimitry Andric     return __s;
8520eae32dcSDimitry Andric   }
8530eae32dcSDimitry Andric #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
8540eae32dcSDimitry Andric #else /* _LIBCPP_WIN32API */
8550eae32dcSDimitry Andric 
85681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const { return __pn_; }
8570eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
85881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
8590eae32dcSDimitry Andric #else
86081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string u8string() const { return __pn_; }
8610eae32dcSDimitry Andric #endif
8620eae32dcSDimitry Andric 
8630eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
8640eae32dcSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>,
8650eae32dcSDimitry Andric             class _Allocator = allocator<_ECharT> >
86681ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
8670eae32dcSDimitry Andric   basic_string<_ECharT, _Traits, _Allocator>
8680eae32dcSDimitry Andric   string(const _Allocator& __a = _Allocator()) const {
8690eae32dcSDimitry Andric     using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
8700eae32dcSDimitry Andric     using _Str = basic_string<_ECharT, _Traits, _Allocator>;
8710eae32dcSDimitry Andric     _Str __s(__a);
8720eae32dcSDimitry Andric     __s.reserve(__pn_.size());
873bdd1243dSDimitry Andric     _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
8740eae32dcSDimitry Andric     return __s;
8750eae32dcSDimitry Andric   }
8760eae32dcSDimitry Andric 
8770eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
87881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const {
8790eae32dcSDimitry Andric     return string<wchar_t>();
8800eae32dcSDimitry Andric   }
8810eae32dcSDimitry Andric #endif
88281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const {
8830eae32dcSDimitry Andric     return string<char16_t>();
8840eae32dcSDimitry Andric   }
88581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const {
8860eae32dcSDimitry Andric     return string<char32_t>();
8870eae32dcSDimitry Andric   }
8880eae32dcSDimitry Andric #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
8890eae32dcSDimitry Andric 
8900eae32dcSDimitry Andric   // generic format observers
89181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return __pn_; }
8920eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
89381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
8940eae32dcSDimitry Andric #else
89581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_u8string() const { return __pn_; }
8960eae32dcSDimitry Andric #endif
8970eae32dcSDimitry Andric 
8980eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
8990eae32dcSDimitry Andric   template <class _ECharT, class _Traits = char_traits<_ECharT>,
9000eae32dcSDimitry Andric             class _Allocator = allocator<_ECharT> >
90181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
9020eae32dcSDimitry Andric   basic_string<_ECharT, _Traits, _Allocator>
9030eae32dcSDimitry Andric   generic_string(const _Allocator& __a = _Allocator()) const {
9040eae32dcSDimitry Andric     return string<_ECharT, _Traits, _Allocator>(__a);
9050eae32dcSDimitry Andric   }
9060eae32dcSDimitry Andric 
9070eae32dcSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
90881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
9090eae32dcSDimitry Andric #endif
91081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
91181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
9120eae32dcSDimitry Andric #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
9130eae32dcSDimitry Andric #endif /* !_LIBCPP_WIN32API */
9140eae32dcSDimitry Andric 
9150eae32dcSDimitry Andric private:
9160eae32dcSDimitry Andric   int __compare(__string_view) const;
9170eae32dcSDimitry Andric   __string_view __root_name() const;
9180eae32dcSDimitry Andric   __string_view __root_directory() const;
9190eae32dcSDimitry Andric   __string_view __root_path_raw() const;
9200eae32dcSDimitry Andric   __string_view __relative_path() const;
9210eae32dcSDimitry Andric   __string_view __parent_path() const;
9220eae32dcSDimitry Andric   __string_view __filename() const;
9230eae32dcSDimitry Andric   __string_view __stem() const;
9240eae32dcSDimitry Andric   __string_view __extension() const;
9250eae32dcSDimitry Andric 
9260eae32dcSDimitry Andric public:
9270eae32dcSDimitry Andric   // compare
92881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept {
9290eae32dcSDimitry Andric     return __compare(__p.__pn_);
9300eae32dcSDimitry Andric   }
93181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const {
9320eae32dcSDimitry Andric     return __compare(__s);
9330eae32dcSDimitry Andric   }
93481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const {
9350eae32dcSDimitry Andric     return __compare(__s);
9360eae32dcSDimitry Andric   }
93781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const {
9380eae32dcSDimitry Andric     return __compare(__s);
9390eae32dcSDimitry Andric   }
9400eae32dcSDimitry Andric 
9410eae32dcSDimitry Andric   // decomposition
94281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_name() const {
9430eae32dcSDimitry Andric     return string_type(__root_name());
9440eae32dcSDimitry Andric   }
94581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_directory() const {
9460eae32dcSDimitry Andric     return string_type(__root_directory());
9470eae32dcSDimitry Andric   }
94881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path root_path() const {
9490eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
9500eae32dcSDimitry Andric     return string_type(__root_path_raw());
9510eae32dcSDimitry Andric #else
9520eae32dcSDimitry Andric     return root_name().append(string_type(__root_directory()));
9530eae32dcSDimitry Andric #endif
9540eae32dcSDimitry Andric   }
95581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path relative_path() const {
9560eae32dcSDimitry Andric     return string_type(__relative_path());
9570eae32dcSDimitry Andric   }
95881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path parent_path() const {
9590eae32dcSDimitry Andric     return string_type(__parent_path());
9600eae32dcSDimitry Andric   }
96181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path filename() const {
9620eae32dcSDimitry Andric     return string_type(__filename());
9630eae32dcSDimitry Andric   }
96481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
96581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path extension() const {
9660eae32dcSDimitry Andric     return string_type(__extension());
9670eae32dcSDimitry Andric   }
9680eae32dcSDimitry Andric 
9690eae32dcSDimitry Andric   // query
97081ad6265SDimitry Andric   _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool
9710eae32dcSDimitry Andric   empty() const noexcept {
9720eae32dcSDimitry Andric     return __pn_.empty();
9730eae32dcSDimitry Andric   }
9740eae32dcSDimitry Andric 
97581ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_name() const {
9760eae32dcSDimitry Andric     return !__root_name().empty();
9770eae32dcSDimitry Andric   }
97881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const {
9790eae32dcSDimitry Andric     return !__root_directory().empty();
9800eae32dcSDimitry Andric   }
98181ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_root_path() const {
9820eae32dcSDimitry Andric     return !__root_path_raw().empty();
9830eae32dcSDimitry Andric   }
98481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const {
9850eae32dcSDimitry Andric     return !__relative_path().empty();
9860eae32dcSDimitry Andric   }
98781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const {
9880eae32dcSDimitry Andric     return !__parent_path().empty();
9890eae32dcSDimitry Andric   }
99081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_filename() const {
9910eae32dcSDimitry Andric     return !__filename().empty();
9920eae32dcSDimitry Andric   }
99381ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
99481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool has_extension() const {
9950eae32dcSDimitry Andric     return !__extension().empty();
9960eae32dcSDimitry Andric   }
9970eae32dcSDimitry Andric 
99881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
9990eae32dcSDimitry Andric #if defined(_LIBCPP_WIN32API)
10000eae32dcSDimitry Andric     __string_view __root_name_str = __root_name();
10010eae32dcSDimitry Andric     __string_view __root_dir = __root_directory();
10020eae32dcSDimitry Andric     if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
10030eae32dcSDimitry Andric       // A drive letter with no root directory is relative, e.g. x:example.
10040eae32dcSDimitry Andric       return !__root_dir.empty();
10050eae32dcSDimitry Andric     }
10060eae32dcSDimitry Andric     // If no root name, it's relative, e.g. \example is relative to the current drive
10070eae32dcSDimitry Andric     if (__root_name_str.empty())
10080eae32dcSDimitry Andric       return false;
10090eae32dcSDimitry Andric     if (__root_name_str.size() < 3)
10100eae32dcSDimitry Andric       return false;
10110eae32dcSDimitry Andric     // A server root name, like \\server, is always absolute
10120eae32dcSDimitry Andric     if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
10130eae32dcSDimitry Andric       return false;
10140eae32dcSDimitry Andric     if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
10150eae32dcSDimitry Andric       return false;
10160eae32dcSDimitry Andric     // Seems to be a server root name
10170eae32dcSDimitry Andric     return true;
10180eae32dcSDimitry Andric #else
10190eae32dcSDimitry Andric     return has_root_directory();
10200eae32dcSDimitry Andric #endif
10210eae32dcSDimitry Andric   }
102281ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
10230eae32dcSDimitry Andric 
10240eae32dcSDimitry Andric   // relative paths
10250eae32dcSDimitry Andric   path lexically_normal() const;
10260eae32dcSDimitry Andric   path lexically_relative(const path& __base) const;
10270eae32dcSDimitry Andric 
102881ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
10290eae32dcSDimitry Andric     path __result = this->lexically_relative(__base);
10300eae32dcSDimitry Andric     if (__result.native().empty())
10310eae32dcSDimitry Andric       return *this;
10320eae32dcSDimitry Andric     return __result;
10330eae32dcSDimitry Andric   }
10340eae32dcSDimitry Andric 
10350eae32dcSDimitry Andric   // iterators
1036*06c3fb27SDimitry Andric   class _LIBCPP_EXPORTED_FROM_ABI iterator;
10370eae32dcSDimitry Andric   typedef iterator const_iterator;
10380eae32dcSDimitry Andric 
10390eae32dcSDimitry Andric   iterator begin() const;
10400eae32dcSDimitry Andric   iterator end() const;
10410eae32dcSDimitry Andric 
10420eae32dcSDimitry Andric #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
10430eae32dcSDimitry Andric   template <class _CharT, class _Traits>
104481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend
10450eae32dcSDimitry Andric       typename enable_if<is_same<_CharT, value_type>::value &&
10460eae32dcSDimitry Andric                              is_same<_Traits, char_traits<value_type> >::value,
10470eae32dcSDimitry Andric                          basic_ostream<_CharT, _Traits>&>::type
10480eae32dcSDimitry Andric       operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
10490eae32dcSDimitry Andric     __os << _VSTD::__quoted(__p.native());
10500eae32dcSDimitry Andric     return __os;
10510eae32dcSDimitry Andric   }
10520eae32dcSDimitry Andric 
10530eae32dcSDimitry Andric   template <class _CharT, class _Traits>
105481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend
10550eae32dcSDimitry Andric       typename enable_if<!is_same<_CharT, value_type>::value ||
10560eae32dcSDimitry Andric                              !is_same<_Traits, char_traits<value_type> >::value,
10570eae32dcSDimitry Andric                          basic_ostream<_CharT, _Traits>&>::type
10580eae32dcSDimitry Andric       operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
10590eae32dcSDimitry Andric     __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
10600eae32dcSDimitry Andric     return __os;
10610eae32dcSDimitry Andric   }
10620eae32dcSDimitry Andric 
10630eae32dcSDimitry Andric   template <class _CharT, class _Traits>
106481ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
10650eae32dcSDimitry Andric   operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
10660eae32dcSDimitry Andric     basic_string<_CharT, _Traits> __tmp;
106781ad6265SDimitry Andric     __is >> _VSTD::__quoted(__tmp);
10680eae32dcSDimitry Andric     __p = __tmp;
10690eae32dcSDimitry Andric     return __is;
10700eae32dcSDimitry Andric   }
10710eae32dcSDimitry Andric #endif // !_LIBCPP_HAS_NO_LOCALIZATION
10720eae32dcSDimitry Andric 
10730eae32dcSDimitry Andric private:
107481ad6265SDimitry Andric   inline _LIBCPP_HIDE_FROM_ABI path&
10750eae32dcSDimitry Andric   __assign_view(__string_view const& __s) noexcept {
10760eae32dcSDimitry Andric     __pn_ = string_type(__s);
10770eae32dcSDimitry Andric     return *this;
10780eae32dcSDimitry Andric   }
10790eae32dcSDimitry Andric   string_type __pn_;
10800eae32dcSDimitry Andric };
10810eae32dcSDimitry Andric 
108281ad6265SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept {
10830eae32dcSDimitry Andric   __lhs.swap(__rhs);
10840eae32dcSDimitry Andric }
10850eae32dcSDimitry Andric 
1086*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
10870eae32dcSDimitry Andric 
1088*06c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
10890eae32dcSDimitry Andric 
10900eae32dcSDimitry Andric _LIBCPP_END_NAMESPACE_FILESYSTEM
10910eae32dcSDimitry Andric 
1092*06c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
1093*06c3fb27SDimitry Andric 
1094*06c3fb27SDimitry Andric template <>
1095*06c3fb27SDimitry Andric struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<_VSTD_FS::path> : __unary_function<_VSTD_FS::path, size_t> {
1096*06c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_t operator()(_VSTD_FS::path const& __p) const noexcept {
1097*06c3fb27SDimitry Andric     return _VSTD_FS::hash_value(__p);
1098*06c3fb27SDimitry Andric   }
1099*06c3fb27SDimitry Andric };
1100*06c3fb27SDimitry Andric 
1101*06c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
1102*06c3fb27SDimitry Andric 
11030eae32dcSDimitry Andric #endif // _LIBCPP_CXX03_LANG
11040eae32dcSDimitry Andric 
11050eae32dcSDimitry Andric #endif // _LIBCPP___FILESYSTEM_PATH_H
1106