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