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