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