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