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