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