[clang][Driver] Support simplified triple versions for config files (#111387)
[llvm-project.git] / libcxx / include / __filesystem / path.h
blob509d1cc8052f0dfdc1fb1a3ad23ebb890b53b7d4
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 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___FILESYSTEM_PATH_H
11 #define _LIBCPP___FILESYSTEM_PATH_H
13 #include <__algorithm/replace.h>
14 #include <__algorithm/replace_copy.h>
15 #include <__config>
16 #include <__functional/unary_function.h>
17 #include <__fwd/functional.h>
18 #include <__iterator/back_insert_iterator.h>
19 #include <__iterator/iterator_traits.h>
20 #include <__type_traits/decay.h>
21 #include <__type_traits/is_pointer.h>
22 #include <__type_traits/remove_const.h>
23 #include <__type_traits/remove_pointer.h>
24 #include <__utility/move.h>
25 #include <string>
26 #include <string_view>
28 #if _LIBCPP_HAS_LOCALIZATION
29 # include <iomanip> // for quoted
30 # include <locale>
31 #endif
33 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
34 # pragma GCC system_header
35 #endif
37 _LIBCPP_PUSH_MACROS
38 #include <__undef_macros>
40 #if _LIBCPP_STD_VER >= 17
42 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
44 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
46 template <class _Tp>
47 struct __can_convert_char {
48 static const bool value = false;
50 template <class _Tp>
51 struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
52 template <>
53 struct __can_convert_char<char> {
54 static const bool value = true;
55 using __char_type = char;
57 template <>
58 struct __can_convert_char<wchar_t> {
59 static const bool value = true;
60 using __char_type = wchar_t;
62 # if _LIBCPP_HAS_CHAR8_T
63 template <>
64 struct __can_convert_char<char8_t> {
65 static const bool value = true;
66 using __char_type = char8_t;
68 # endif
69 template <>
70 struct __can_convert_char<char16_t> {
71 static const bool value = true;
72 using __char_type = char16_t;
74 template <>
75 struct __can_convert_char<char32_t> {
76 static const bool value = true;
77 using __char_type = char32_t;
80 template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
81 _LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {
82 # if defined(_LIBCPP_WIN32API)
83 return __e == _ECharT('/') || __e == _ECharT('\\');
84 # else
85 return __e == _ECharT('/');
86 # endif
89 # if _LIBCPP_HAS_CHAR8_T
90 typedef u8string __u8_string;
91 # else
92 typedef string __u8_string;
93 # endif
95 struct _NullSentinel {};
97 template <class _Tp>
98 using _Void = void;
100 template <class _Tp, class = void>
101 struct __is_pathable_string : public false_type {};
103 template <class _ECharT, class _Traits, class _Alloc>
104 struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>,
105 _Void<typename __can_convert_char<_ECharT>::__char_type> >
106 : public __can_convert_char<_ECharT> {
107 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
109 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
111 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
113 _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
116 template <class _ECharT, class _Traits>
117 struct __is_pathable_string< basic_string_view<_ECharT, _Traits>,
118 _Void<typename __can_convert_char<_ECharT>::__char_type> >
119 : public __can_convert_char<_ECharT> {
120 using _Str = basic_string_view<_ECharT, _Traits>;
122 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
124 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
126 _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
129 template <class _Source,
130 class _DS = __decay_t<_Source>,
131 class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
132 bool _IsCharPtr = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
133 struct __is_pathable_char_array : false_type {};
135 template <class _Source, class _ECharT, class _UPtr>
136 struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> : __can_convert_char<__remove_const_t<_ECharT> > {
137 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
139 _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {
140 using _Iter = const _ECharT*;
141 const _ECharT __sentinel = _ECharT{};
142 _Iter __e = __b;
143 for (; *__e != __sentinel; ++__e)
145 return __e;
148 _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
151 template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
152 struct __is_pathable_iter : false_type {};
154 template <class _Iter>
155 struct __is_pathable_iter<
156 _Iter,
157 true,
158 _Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >
159 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
160 using _ECharT = typename iterator_traits<_Iter>::value_type;
162 _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }
164 _LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
166 _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }
169 template <class _Tp,
170 bool _IsStringT = __is_pathable_string<_Tp>::value,
171 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
172 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
173 struct __is_pathable : false_type {
174 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
177 template <class _Tp>
178 struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
180 template <class _Tp>
181 struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
183 template <class _Tp>
184 struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
186 # if defined(_LIBCPP_WIN32API)
187 typedef wstring __path_string;
188 typedef wchar_t __path_value;
189 # else
190 typedef string __path_string;
191 typedef char __path_value;
192 # endif
194 # if defined(_LIBCPP_WIN32API)
195 _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
196 _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
197 # endif
199 template <class _ECharT>
200 struct _PathCVT;
202 # if _LIBCPP_HAS_LOCALIZATION
203 template <class _ECharT>
204 struct _PathCVT {
205 static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
207 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
208 # if defined(_LIBCPP_WIN32API)
209 typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
210 # endif
212 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {
213 # if defined(_LIBCPP_WIN32API)
214 string __utf8;
215 _Narrower()(back_inserter(__utf8), __b, __e);
216 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
217 # else
218 _Narrower()(back_inserter(__dest), __b, __e);
219 # endif
222 template <class _Iter>
223 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
224 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
225 if (__b == __e)
226 return;
227 basic_string<_ECharT> __tmp(__b, __e);
228 # if defined(_LIBCPP_WIN32API)
229 string __utf8;
230 _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
231 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
232 # else
233 _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
234 # endif
237 template <class _Iter>
238 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
239 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
240 const _ECharT __sentinel = _ECharT{};
241 if (*__b == __sentinel)
242 return;
243 basic_string<_ECharT> __tmp;
244 for (; *__b != __sentinel; ++__b)
245 __tmp.push_back(*__b);
246 # if defined(_LIBCPP_WIN32API)
247 string __utf8;
248 _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
249 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
250 # else
251 _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
252 # endif
255 template <class _Source>
256 _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
257 using _Traits = __is_pathable<_Source>;
258 __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
261 # endif // _LIBCPP_HAS_LOCALIZATION
263 template <>
264 struct _PathCVT<__path_value> {
265 template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
266 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
267 for (; __b != __e; ++__b)
268 __dest.push_back(*__b);
271 template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
272 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
273 __dest.append(__b, __e);
276 template <class _Iter>
277 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
278 const char __sentinel = char{};
279 for (; *__b != __sentinel; ++__b)
280 __dest.push_back(*__b);
283 template <class _Source>
284 _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
285 using _Traits = __is_pathable<_Source>;
286 __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
290 # if defined(_LIBCPP_WIN32API)
291 template <>
292 struct _PathCVT<char> {
293 _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
294 size_t __size = __char_to_wide(__str, nullptr, 0);
295 size_t __pos = __dest.size();
296 __dest.resize(__pos + __size);
297 __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
300 template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
301 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
302 basic_string<char> __tmp(__b, __e);
303 __append_string(__dest, __tmp);
306 template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
307 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
308 basic_string<char> __tmp(__b, __e);
309 __append_string(__dest, __tmp);
312 template <class _Iter>
313 _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
314 const char __sentinel = char{};
315 basic_string<char> __tmp;
316 for (; *__b != __sentinel; ++__b)
317 __tmp.push_back(*__b);
318 __append_string(__dest, __tmp);
321 template <class _Source>
322 _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
323 using _Traits = __is_pathable<_Source>;
324 __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
328 template <class _ECharT>
329 struct _PathExport {
330 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
331 typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
333 template <class _Str>
334 _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
335 string __utf8;
336 _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
337 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
341 template <>
342 struct _PathExport<char> {
343 template <class _Str>
344 _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
345 size_t __size = __wide_to_char(__src, nullptr, 0);
346 size_t __pos = __dest.size();
347 __dest.resize(__size);
348 __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
352 template <>
353 struct _PathExport<wchar_t> {
354 template <class _Str>
355 _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
356 __dest.append(__src.begin(), __src.end());
360 template <>
361 struct _PathExport<char16_t> {
362 template <class _Str>
363 _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
364 __dest.append(__src.begin(), __src.end());
368 # if _LIBCPP_HAS_CHAR8_T
369 template <>
370 struct _PathExport<char8_t> {
371 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
373 template <class _Str>
374 _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
375 _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
378 # endif // _LIBCPP_HAS_CHAR8_T
379 # endif /* _LIBCPP_WIN32API */
381 class _LIBCPP_EXPORTED_FROM_ABI path {
382 template <class _SourceOrIter, class _Tp = path&>
383 using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;
385 template <class _Tp>
386 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
388 template <class _Tp>
389 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
391 public:
392 # if defined(_LIBCPP_WIN32API)
393 typedef wchar_t value_type;
394 static constexpr value_type preferred_separator = L'\\';
395 # else
396 typedef char value_type;
397 static constexpr value_type preferred_separator = '/';
398 # endif
399 typedef basic_string<value_type> string_type;
400 typedef basic_string_view<value_type> __string_view;
402 enum format : unsigned char { auto_format, native_format, generic_format };
404 // constructors and destructor
405 _LIBCPP_HIDE_FROM_ABI path() noexcept {}
406 _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
407 _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}
409 _LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}
411 template <class _Source, class = _EnableIfPathable<_Source, void> >
412 _LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {
413 _SourceCVT<_Source>::__append_source(__pn_, __src);
416 template <class _InputIt>
417 _LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {
418 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
419 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
423 #if _LIBCPP_HAS_LOCALIZATION
424 // TODO Implement locale conversions.
425 template <class _Source, class = _EnableIfPathable<_Source, void> >
426 path(const _Source& __src, const locale& __loc, format = format::auto_format);
427 template <class _InputIt>
428 path(_InputIt __first, _InputIt _last, const locale& __loc,
429 format = format::auto_format);
430 #endif
433 _LIBCPP_HIDE_FROM_ABI ~path() = default;
435 // assignments
436 _LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {
437 __pn_ = __p.__pn_;
438 return *this;
441 _LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {
442 __pn_ = std::move(__p.__pn_);
443 return *this;
446 _LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {
447 __pn_ = std::move(__s);
448 return *this;
451 _LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {
452 __pn_ = std::move(__s);
453 return *this;
456 template <class _Source>
457 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {
458 return this->assign(__src);
461 template <class _Source>
462 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {
463 __pn_.clear();
464 _SourceCVT<_Source>::__append_source(__pn_, __src);
465 return *this;
468 template <class _InputIt>
469 _LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {
470 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
471 __pn_.clear();
472 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
473 return *this;
476 public:
477 // appends
478 # if defined(_LIBCPP_WIN32API)
479 _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
480 auto __p_root_name = __p.__root_name();
481 auto __p_root_name_size = __p_root_name.size();
482 if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
483 __pn_ = __p.__pn_;
484 return *this;
486 if (__p.has_root_directory()) {
487 path __root_name_str = root_name();
488 __pn_ = __root_name_str.native();
489 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
490 return *this;
492 if (has_filename() || (!has_root_directory() && is_absolute()))
493 __pn_ += preferred_separator;
494 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
495 return *this;
497 template <class _Source>
498 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
499 return operator/=(path(__src));
502 template <class _Source>
503 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
504 return operator/=(path(__src));
507 template <class _InputIt>
508 _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
509 return operator/=(path(__first, __last));
511 # else
512 _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
513 if (__p.is_absolute()) {
514 __pn_ = __p.__pn_;
515 return *this;
517 if (has_filename())
518 __pn_ += preferred_separator;
519 __pn_ += __p.native();
520 return *this;
523 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
524 // is known at compile time to be "/' since the user almost certainly intended
525 // to append a separator instead of overwriting the path with "/"
526 template <class _Source>
527 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
528 return this->append(__src);
531 template <class _Source>
532 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
533 using _Traits = __is_pathable<_Source>;
534 using _CVT = _PathCVT<_SourceChar<_Source> >;
535 bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));
536 if (__source_is_absolute)
537 __pn_.clear();
538 else if (has_filename())
539 __pn_ += preferred_separator;
540 _CVT::__append_source(__pn_, __src);
541 return *this;
544 template <class _InputIt>
545 _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
546 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
547 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
548 using _CVT = _PathCVT<_ItVal>;
549 if (__first != __last && filesystem::__is_separator(*__first))
550 __pn_.clear();
551 else if (has_filename())
552 __pn_ += preferred_separator;
553 _CVT::__append_range(__pn_, __first, __last);
554 return *this;
556 # endif
558 // concatenation
559 _LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {
560 __pn_ += __x.__pn_;
561 return *this;
564 _LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {
565 __pn_ += __x;
566 return *this;
569 _LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {
570 __pn_ += __x;
571 return *this;
574 _LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {
575 __pn_ += __x;
576 return *this;
579 _LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {
580 __pn_ += __x;
581 return *this;
584 template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
585 _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
586 _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
587 return *this;
590 template <class _Source>
591 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {
592 return this->concat(__x);
595 template <class _Source>
596 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {
597 _SourceCVT<_Source>::__append_source(__pn_, __x);
598 return *this;
601 template <class _InputIt>
602 _LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {
603 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
604 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
605 return *this;
608 // modifiers
609 _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }
611 _LIBCPP_HIDE_FROM_ABI path& make_preferred() {
612 # if defined(_LIBCPP_WIN32API)
613 std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
614 # endif
615 return *this;
618 _LIBCPP_HIDE_FROM_ABI path& remove_filename() {
619 auto __fname = __filename();
620 if (!__fname.empty())
621 __pn_.erase(__fname.data() - __pn_.data());
622 return *this;
625 _LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {
626 remove_filename();
627 return (*this /= __replacement);
630 path& replace_extension(const path& __replacement = path());
632 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
633 return __lhs.__compare(__rhs.__pn_) == 0;
635 # if _LIBCPP_STD_VER <= 17
636 friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
637 return __lhs.__compare(__rhs.__pn_) != 0;
639 friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {
640 return __lhs.__compare(__rhs.__pn_) < 0;
642 friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {
643 return __lhs.__compare(__rhs.__pn_) <= 0;
645 friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {
646 return __lhs.__compare(__rhs.__pn_) > 0;
648 friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {
649 return __lhs.__compare(__rhs.__pn_) >= 0;
651 # else // _LIBCPP_STD_VER <= 17
652 friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
653 return __lhs.__compare(__rhs.__pn_) <=> 0;
655 # endif // _LIBCPP_STD_VER <= 17
657 friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
658 path __result(__lhs);
659 __result /= __rhs;
660 return __result;
663 _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
665 // private helper to allow reserving memory in the path
666 _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }
668 // native format observers
669 _LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }
671 _LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }
673 _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
675 # if defined(_LIBCPP_WIN32API)
676 _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }
678 _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {
679 std::wstring __s;
680 __s.resize(__pn_.size());
681 std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
682 return __s;
685 # if _LIBCPP_HAS_LOCALIZATION
686 template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
687 _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
688 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
689 _Str __s(__a);
690 __s.reserve(__pn_.size());
691 _PathExport<_ECharT>::__append(__s, __pn_);
692 return __s;
695 _LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }
696 _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
697 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
698 __u8_string __s;
699 __s.reserve(__pn_.size());
700 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
701 return __s;
704 _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
705 _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
707 // generic format observers
708 template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
709 _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
710 generic_string(const _Allocator& __a = _Allocator()) const {
711 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
712 _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
713 // Note: This (and generic_u8string below) is slightly suboptimal as
714 // it iterates twice over the string; once to convert it to the right
715 // character type, and once to replace path delimiters.
716 std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
717 return __s;
720 _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }
721 _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }
722 _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }
723 _LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {
724 __u8_string __s = u8string();
725 std::replace(__s.begin(), __s.end(), '\\', '/');
726 return __s;
728 # endif // _LIBCPP_HAS_LOCALIZATION
729 # else /* _LIBCPP_WIN32API */
731 _LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }
732 # if _LIBCPP_HAS_CHAR8_T
733 _LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
734 # else
735 _LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }
736 # endif
738 # if _LIBCPP_HAS_LOCALIZATION
739 template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
740 _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
741 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
742 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
743 _Str __s(__a);
744 __s.reserve(__pn_.size());
745 _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
746 return __s;
749 # if _LIBCPP_HAS_WIDE_CHARACTERS
750 _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }
751 # endif
752 _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
753 _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
754 # endif // _LIBCPP_HAS_LOCALIZATION
756 // generic format observers
757 _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }
758 # if _LIBCPP_HAS_CHAR8_T
759 _LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
760 # else
761 _LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }
762 # endif
764 # if _LIBCPP_HAS_LOCALIZATION
765 template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
766 _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
767 generic_string(const _Allocator& __a = _Allocator()) const {
768 return string<_ECharT, _Traits, _Allocator>(__a);
771 # if _LIBCPP_HAS_WIDE_CHARACTERS
772 _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }
773 # endif
774 _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }
775 _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }
776 # endif // _LIBCPP_HAS_LOCALIZATION
777 # endif /* !_LIBCPP_WIN32API */
779 private:
780 int __compare(__string_view) const;
781 __string_view __root_name() const;
782 __string_view __root_directory() const;
783 __string_view __root_path_raw() const;
784 __string_view __relative_path() const;
785 __string_view __parent_path() const;
786 __string_view __filename() const;
787 __string_view __stem() const;
788 __string_view __extension() const;
790 public:
791 // compare
792 _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }
793 _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }
794 _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }
795 _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }
797 // decomposition
798 _LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }
799 _LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }
800 _LIBCPP_HIDE_FROM_ABI path root_path() const {
801 # if defined(_LIBCPP_WIN32API)
802 return string_type(__root_path_raw());
803 # else
804 return root_name().append(string_type(__root_directory()));
805 # endif
807 _LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }
808 _LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }
809 _LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }
810 _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
811 _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }
813 // query
814 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }
816 _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }
817 _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }
818 _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }
819 _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }
820 _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }
821 _LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }
822 _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
823 _LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }
825 _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
826 # if defined(_LIBCPP_WIN32API)
827 __string_view __root_name_str = __root_name();
828 __string_view __root_dir = __root_directory();
829 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
830 // A drive letter with no root directory is relative, e.g. x:example.
831 return !__root_dir.empty();
833 // If no root name, it's relative, e.g. \example is relative to the current drive
834 if (__root_name_str.empty())
835 return false;
836 if (__root_name_str.size() < 3)
837 return false;
838 // A server root name, like \\server, is always absolute
839 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
840 return false;
841 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
842 return false;
843 // Seems to be a server root name
844 return true;
845 # else
846 return has_root_directory();
847 # endif
849 _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
851 // relative paths
852 path lexically_normal() const;
853 path lexically_relative(const path& __base) const;
855 _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
856 path __result = this->lexically_relative(__base);
857 if (__result.native().empty())
858 return *this;
859 return __result;
862 // iterators
863 class _LIBCPP_EXPORTED_FROM_ABI iterator;
864 typedef iterator const_iterator;
866 iterator begin() const;
867 iterator end() const;
869 # if _LIBCPP_HAS_LOCALIZATION
870 template <
871 class _CharT,
872 class _Traits,
873 __enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>
874 _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
875 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
876 __os << std::__quoted(__p.native());
877 return __os;
880 template <
881 class _CharT,
882 class _Traits,
883 __enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>
884 _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
885 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
886 __os << std::__quoted(__p.string<_CharT, _Traits>());
887 return __os;
890 template <class _CharT, class _Traits>
891 _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
892 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
893 basic_string<_CharT, _Traits> __tmp;
894 __is >> std::__quoted(__tmp);
895 __p = __tmp;
896 return __is;
898 # endif // _LIBCPP_HAS_LOCALIZATION
900 private:
901 inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {
902 __pn_ = string_type(__s);
903 return *this;
905 string_type __pn_;
908 inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
910 _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
912 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
914 _LIBCPP_END_NAMESPACE_FILESYSTEM
916 _LIBCPP_BEGIN_NAMESPACE_STD
918 template <>
919 struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {
920 _LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {
921 return filesystem::hash_value(__p);
925 _LIBCPP_END_NAMESPACE_STD
927 #endif // _LIBCPP_STD_VER >= 17
929 _LIBCPP_POP_MACROS
931 #endif // _LIBCPP___FILESYSTEM_PATH_H