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