2 //===----------------------------------------------------------------------===//
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
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 <__availability>
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>
28 #include <string_view>
30 #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
31 # include <iomanip> // for quoted
35 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
36 # pragma GCC system_header
39 #ifndef _LIBCPP_CXX03_LANG
41 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
43 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
46 struct __can_convert_char
{
47 static const bool value
= false;
50 struct __can_convert_char
<const _Tp
> : public __can_convert_char
<_Tp
> {};
52 struct __can_convert_char
<char> {
53 static const bool value
= true;
54 using __char_type
= char;
57 struct __can_convert_char
<wchar_t> {
58 static const bool value
= true;
59 using __char_type
= wchar_t;
61 #ifndef _LIBCPP_HAS_NO_CHAR8_T
63 struct __can_convert_char
<char8_t
> {
64 static const bool value
= true;
65 using __char_type
= char8_t
;
69 struct __can_convert_char
<char16_t
> {
70 static const bool value
= true;
71 using __char_type
= char16_t
;
74 struct __can_convert_char
<char32_t
> {
75 static const bool value
= true;
76 using __char_type
= char32_t
;
79 template <class _ECharT
, __enable_if_t
<__can_convert_char
<_ECharT
>::value
, int> = 0>
82 __is_separator(_ECharT __e
) {
83 #if defined(_LIBCPP_WIN32API)
84 return __e
== _ECharT('/') || __e
== _ECharT('\\');
86 return __e
== _ECharT('/');
90 #ifndef _LIBCPP_HAS_NO_CHAR8_T
91 typedef u8string __u8_string
;
93 typedef string __u8_string
;
96 struct _NullSentinel
{};
101 template <class _Tp
, class = void>
102 struct __is_pathable_string
: public false_type
{};
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
>;
111 _LIBCPP_HIDE_FROM_ABI
112 static _ECharT
const* __range_begin(_Str
const& __s
) { return __s
.data(); }
114 _LIBCPP_HIDE_FROM_ABI
115 static _ECharT
const* __range_end(_Str
const& __s
) {
116 return __s
.data() + __s
.length();
119 _LIBCPP_HIDE_FROM_ABI
120 static _ECharT
__first_or_null(_Str
const& __s
) {
121 return __s
.empty() ? _ECharT
{} : __s
[0];
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
>;
132 _LIBCPP_HIDE_FROM_ABI
133 static _ECharT
const* __range_begin(_Str
const& __s
) { return __s
.data(); }
135 _LIBCPP_HIDE_FROM_ABI
136 static _ECharT
const* __range_end(_Str
const& __s
) {
137 return __s
.data() + __s
.length();
140 _LIBCPP_HIDE_FROM_ABI
141 static _ECharT
__first_or_null(_Str
const& __s
) {
142 return __s
.empty() ? _ECharT
{} : __s
[0];
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
{};
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
; }
159 _LIBCPP_HIDE_FROM_ABI
160 static _ECharT
const* __range_end(const _ECharT
* __b
) {
161 using _Iter
= const _ECharT
*;
162 const _ECharT __sentinel
= _ECharT
{};
164 for (; *__e
!= __sentinel
; ++__e
)
169 _LIBCPP_HIDE_FROM_ABI
170 static _ECharT
__first_or_null(const _ECharT
* __b
) { return *__b
; }
173 template <class _Iter
, bool _IsIt
= __has_input_iterator_category
<_Iter
>::value
,
175 struct __is_pathable_iter
: false_type
{};
177 template <class _Iter
>
178 struct __is_pathable_iter
<
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
;
185 _LIBCPP_HIDE_FROM_ABI
186 static _Iter
__range_begin(_Iter __b
) { return __b
; }
188 _LIBCPP_HIDE_FROM_ABI
189 static _NullSentinel
__range_end(_Iter
) { return _NullSentinel
{}; }
191 _LIBCPP_HIDE_FROM_ABI
192 static _ECharT
__first_or_null(_Iter __b
) { return *__b
; }
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");
203 struct __is_pathable
<_Tp
, true, false, false> : __is_pathable_string
<_Tp
> {};
206 struct __is_pathable
<_Tp
, false, true, false> : __is_pathable_char_array
<_Tp
> {
210 struct __is_pathable
<_Tp
, false, false, true> : __is_pathable_iter
<_Tp
> {};
212 #if defined(_LIBCPP_WIN32API)
213 typedef wstring __path_string
;
214 typedef wchar_t __path_value
;
216 typedef string __path_string
;
217 typedef char __path_value
;
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);
225 template <class _ECharT
>
228 #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
229 template <class _ECharT
>
231 static_assert(__can_convert_char
<_ECharT
>::value
,
232 "Char type not convertible");
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
;
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)
244 _Narrower()(back_inserter(__utf8
), __b
, __e
);
245 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
247 _Narrower()(back_inserter(__dest
), __b
, __e
);
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");
257 basic_string
<_ECharT
> __tmp(__b
, __e
);
258 #if defined(_LIBCPP_WIN32API)
260 _Narrower()(back_inserter(__utf8
), __tmp
.data(),
261 __tmp
.data() + __tmp
.length());
262 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
264 _Narrower()(back_inserter(__dest
), __tmp
.data(),
265 __tmp
.data() + __tmp
.length());
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
)
276 basic_string
<_ECharT
> __tmp
;
277 for (; *__b
!= __sentinel
; ++__b
)
278 __tmp
.push_back(*__b
);
279 #if defined(_LIBCPP_WIN32API)
281 _Narrower()(back_inserter(__utf8
), __tmp
.data(),
282 __tmp
.data() + __tmp
.length());
283 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
285 _Narrower()(back_inserter(__dest
), __tmp
.data(),
286 __tmp
.data() + __tmp
.length());
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
));
298 #endif // !_LIBCPP_HAS_NO_LOCALIZATION
301 struct _PathCVT
<__path_value
> {
303 template <class _Iter
, __enable_if_t
<__has_exactly_input_iterator_category
<_Iter
>::value
, int> = 0>
304 _LIBCPP_HIDE_FROM_ABI
306 __append_range(__path_string
& __dest
, _Iter __b
, _Iter __e
) {
307 for (; __b
!= __e
; ++__b
)
308 __dest
.push_back(*__b
);
311 template <class _Iter
, __enable_if_t
<__has_forward_iterator_category
<_Iter
>::value
, int> = 0>
312 _LIBCPP_HIDE_FROM_ABI
314 __append_range(__path_string
& __dest
, _Iter __b
, _Iter __e
) {
315 __dest
.append(__b
, __e
);
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
);
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
));
335 #if defined(_LIBCPP_WIN32API)
337 struct _PathCVT
<char> {
339 _LIBCPP_HIDE_FROM_ABI
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
);
348 template <class _Iter
, __enable_if_t
<__has_exactly_input_iterator_category
<_Iter
>::value
, int> = 0>
349 _LIBCPP_HIDE_FROM_ABI
351 __append_range(__path_string
& __dest
, _Iter __b
, _Iter __e
) {
352 basic_string
<char> __tmp(__b
, __e
);
353 __append_string(__dest
, __tmp
);
356 template <class _Iter
, __enable_if_t
<__has_forward_iterator_category
<_Iter
>::value
, int> = 0>
357 _LIBCPP_HIDE_FROM_ABI
359 __append_range(__path_string
& __dest
, _Iter __b
, _Iter __e
) {
360 basic_string
<char> __tmp(__b
, __e
);
361 __append_string(__dest
, __tmp
);
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
);
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
));
383 template <class _ECharT
>
385 typedef __narrow_to_utf8
<sizeof(wchar_t) * __CHAR_BIT__
> _Narrower
;
386 typedef __widen_from_utf8
<sizeof(_ECharT
) * __CHAR_BIT__
> _Widener
;
388 template <class _Str
>
389 _LIBCPP_HIDE_FROM_ABI
390 static void __append(_Str
& __dest
, const __path_string
& __src
) {
392 _Narrower()(back_inserter(__utf8
), __src
.data(), __src
.data() + __src
.size());
393 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
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
);
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());
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());
427 #ifndef _LIBCPP_HAS_NO_CHAR8_T
429 struct _PathExport
<char8_t
> {
430 typedef __narrow_to_utf8
<sizeof(wchar_t) * __CHAR_BIT__
> _Narrower
;
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());
438 #endif /* !_LIBCPP_HAS_NO_CHAR8_T */
439 #endif /* _LIBCPP_WIN32API */
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
>;
446 using _SourceChar
= typename __is_pathable
<_Tp
>::__char_type
;
449 using _SourceCVT
= _PathCVT
<_SourceChar
<_Tp
> >;
452 #if defined(_LIBCPP_WIN32API)
453 typedef wchar_t value_type
;
454 static constexpr value_type preferred_separator
= L
'\\';
456 typedef char value_type
;
457 static constexpr value_type preferred_separator
= '/';
459 typedef basic_string
<value_type
> string_type
;
460 typedef basic_string_view
<value_type
> __string_view
;
462 enum format
: unsigned char {
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_
)) {}
474 _LIBCPP_HIDE_FROM_ABI
475 path(string_type
&& __s
, format
= format::auto_format
) noexcept
476 : __pn_(_VSTD::move(__s
)) {}
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
);
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
);
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);
502 _LIBCPP_HIDE_FROM_ABI
506 _LIBCPP_HIDE_FROM_ABI
507 path
& operator=(const path
& __p
) {
512 _LIBCPP_HIDE_FROM_ABI
513 path
& operator=(path
&& __p
) noexcept
{
514 __pn_
= _VSTD::move(__p
.__pn_
);
518 _LIBCPP_HIDE_FROM_ABI
519 path
& operator=(string_type
&& __s
) noexcept
{
520 __pn_
= _VSTD::move(__s
);
524 _LIBCPP_HIDE_FROM_ABI
525 path
& assign(string_type
&& __s
) noexcept
{
526 __pn_
= _VSTD::move(__s
);
530 template <class _Source
>
531 _LIBCPP_HIDE_FROM_ABI _EnableIfPathable
<_Source
>
532 operator=(const _Source
& __src
) {
533 return this->assign(__src
);
536 template <class _Source
>
537 _LIBCPP_HIDE_FROM_ABI
538 _EnableIfPathable
<_Source
> assign(const _Source
& __src
) {
540 _SourceCVT
<_Source
>::__append_source(__pn_
, __src
);
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
;
549 _PathCVT
<_ItVal
>::__append_range(__pn_
, __first
, __last
);
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_
))) {
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
);
571 if (has_filename() || (!has_root_directory() && is_absolute()))
572 __pn_
+= preferred_separator
;
573 __pn_
+= __string_view(__p
.__pn_
).substr(__p_root_name_size
);
576 template <class _Source
>
577 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable
<_Source
>
578 operator/=(const _Source
& __src
) {
579 return operator/=(path(__src
));
582 template <class _Source
>
583 _LIBCPP_HIDE_FROM_ABI
584 _EnableIfPathable
<_Source
> append(const _Source
& __src
) {
585 return operator/=(path(__src
));
588 template <class _InputIt
>
589 _LIBCPP_HIDE_FROM_ABI
590 path
& append(_InputIt __first
, _InputIt __last
) {
591 return operator/=(path(__first
, __last
));
594 _LIBCPP_HIDE_FROM_ABI
595 path
& operator/=(const path
& __p
) {
596 if (__p
.is_absolute()) {
601 __pn_
+= preferred_separator
;
602 __pn_
+= __p
.native();
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
);
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
= _VSTD_FS::__is_separator(_Traits::__first_or_null(__src
));
621 if (__source_is_absolute
)
623 else if (has_filename())
624 __pn_
+= preferred_separator
;
625 _CVT::__append_source(__pn_
, __src
);
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
&& _VSTD_FS::__is_separator(*__first
))
637 else if (has_filename())
638 __pn_
+= preferred_separator
;
639 _CVT::__append_range(__pn_
, __first
, __last
);
645 _LIBCPP_HIDE_FROM_ABI
646 path
& operator+=(const path
& __x
) {
651 _LIBCPP_HIDE_FROM_ABI
652 path
& operator+=(const string_type
& __x
) {
657 _LIBCPP_HIDE_FROM_ABI
658 path
& operator+=(__string_view __x
) {
663 _LIBCPP_HIDE_FROM_ABI
664 path
& operator+=(const value_type
* __x
) {
669 _LIBCPP_HIDE_FROM_ABI
670 path
& operator+=(value_type __x
) {
675 template <class _ECharT
, __enable_if_t
<__can_convert_char
<_ECharT
>::value
, int> = 0>
676 _LIBCPP_HIDE_FROM_ABI
678 operator+=(_ECharT __x
) {
679 _PathCVT
<_ECharT
>::__append_source(__pn_
,
680 basic_string_view
<_ECharT
>(&__x
, 1));
684 template <class _Source
>
685 _LIBCPP_HIDE_FROM_ABI
686 _EnableIfPathable
<_Source
> operator+=(const _Source
& __x
) {
687 return this->concat(__x
);
690 template <class _Source
>
691 _LIBCPP_HIDE_FROM_ABI
692 _EnableIfPathable
<_Source
> concat(const _Source
& __x
) {
693 _SourceCVT
<_Source
>::__append_source(__pn_
, __x
);
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
);
706 _LIBCPP_HIDE_FROM_ABI
707 void clear() noexcept
{ __pn_
.clear(); }
709 _LIBCPP_HIDE_FROM_ABI
710 path
& make_preferred() {
711 #if defined(_LIBCPP_WIN32API)
712 _VSTD::replace(__pn_
.begin(), __pn_
.end(), L
'/', L
'\\');
717 _LIBCPP_HIDE_FROM_ABI
718 path
& remove_filename() {
719 auto __fname
= __filename();
720 if (!__fname
.empty())
721 __pn_
.erase(__fname
.data() - __pn_
.data());
725 _LIBCPP_HIDE_FROM_ABI
726 path
& replace_filename(const path
& __replacement
) {
728 return (*this /= __replacement
);
731 path
& replace_extension(const path
& __replacement
= path());
733 friend _LIBCPP_HIDE_FROM_ABI
bool operator==(const path
& __lhs
, const path
& __rhs
) noexcept
{
734 return __lhs
.__compare(__rhs
.__pn_
) == 0;
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;
740 friend _LIBCPP_HIDE_FROM_ABI
bool operator<(const path
& __lhs
, const path
& __rhs
) noexcept
{
741 return __lhs
.__compare(__rhs
.__pn_
) < 0;
743 friend _LIBCPP_HIDE_FROM_ABI
bool operator<=(const path
& __lhs
, const path
& __rhs
) noexcept
{
744 return __lhs
.__compare(__rhs
.__pn_
) <= 0;
746 friend _LIBCPP_HIDE_FROM_ABI
bool operator>(const path
& __lhs
, const path
& __rhs
) noexcept
{
747 return __lhs
.__compare(__rhs
.__pn_
) > 0;
749 friend _LIBCPP_HIDE_FROM_ABI
bool operator>=(const path
& __lhs
, const path
& __rhs
) noexcept
{
750 return __lhs
.__compare(__rhs
.__pn_
) >= 0;
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;
756 # endif // _LIBCPP_STD_VER <= 17
758 friend _LIBCPP_HIDE_FROM_ABI path
operator/(const path
& __lhs
, const path
& __rhs
) {
759 path
__result(__lhs
);
764 _LIBCPP_HIDE_FROM_ABI
765 void swap(path
& __rhs
) noexcept
{ __pn_
.swap(__rhs
.__pn_
); }
767 // private helper to allow reserving memory in the path
768 _LIBCPP_HIDE_FROM_ABI
769 void __reserve(size_t __s
) { __pn_
.reserve(__s
); }
771 // native format observers
772 _LIBCPP_HIDE_FROM_ABI
773 const string_type
& native() const noexcept
{ return __pn_
; }
775 _LIBCPP_HIDE_FROM_ABI
776 const value_type
* c_str() const noexcept
{ return __pn_
.c_str(); }
778 _LIBCPP_HIDE_FROM_ABI
operator string_type() const { return __pn_
; }
780 #if defined(_LIBCPP_WIN32API)
781 _LIBCPP_HIDE_FROM_ABI
_VSTD::wstring
wstring() const { return __pn_
; }
783 _LIBCPP_HIDE_FROM_ABI
784 _VSTD::wstring
generic_wstring() const {
786 __s
.resize(__pn_
.size());
787 _VSTD::replace_copy(__pn_
.begin(), __pn_
.end(), __s
.begin(), '\\', '/');
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
>;
799 __s
.reserve(__pn_
.size());
800 _PathExport
<_ECharT
>::__append(__s
, __pn_
);
804 _LIBCPP_HIDE_FROM_ABI
_VSTD::string
string() const {
805 return string
<char>();
807 _LIBCPP_HIDE_FROM_ABI __u8_string
u8string() const {
808 using _CVT
= __narrow_to_utf8
<sizeof(wchar_t) * __CHAR_BIT__
>;
810 __s
.reserve(__pn_
.size());
811 _CVT()(back_inserter(__s
), __pn_
.data(), __pn_
.data() + __pn_
.size());
815 _LIBCPP_HIDE_FROM_ABI
_VSTD::u16string
u16string() const {
816 return string
<char16_t
>();
818 _LIBCPP_HIDE_FROM_ABI
_VSTD::u32string
u32string() const {
819 return string
<char32_t
>();
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
>('/'));
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(), '\\', '/');
847 #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
848 #else /* _LIBCPP_WIN32API */
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()); }
854 _LIBCPP_HIDE_FROM_ABI
_VSTD::string
u8string() const { return __pn_
; }
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
>;
866 __s
.reserve(__pn_
.size());
867 _CVT()(std::back_inserter(__s
), __pn_
.data(), __pn_
.data() + __pn_
.size());
871 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
872 _LIBCPP_HIDE_FROM_ABI
_VSTD::wstring
wstring() const {
873 return string
<wchar_t>();
876 _LIBCPP_HIDE_FROM_ABI
_VSTD::u16string
u16string() const {
877 return string
<char16_t
>();
879 _LIBCPP_HIDE_FROM_ABI
_VSTD::u32string
u32string() const {
880 return string
<char32_t
>();
882 #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
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()); }
889 _LIBCPP_HIDE_FROM_ABI
_VSTD::string
generic_u8string() const { return __pn_
; }
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
);
901 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
902 _LIBCPP_HIDE_FROM_ABI
_VSTD::wstring
generic_wstring() const { return string
<wchar_t>(); }
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 */
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;
922 _LIBCPP_HIDE_FROM_ABI
int compare(const path
& __p
) const noexcept
{
923 return __compare(__p
.__pn_
);
925 _LIBCPP_HIDE_FROM_ABI
int compare(const string_type
& __s
) const {
926 return __compare(__s
);
928 _LIBCPP_HIDE_FROM_ABI
int compare(__string_view __s
) const {
929 return __compare(__s
);
931 _LIBCPP_HIDE_FROM_ABI
int compare(const value_type
* __s
) const {
932 return __compare(__s
);
936 _LIBCPP_HIDE_FROM_ABI path
root_name() const {
937 return string_type(__root_name());
939 _LIBCPP_HIDE_FROM_ABI path
root_directory() const {
940 return string_type(__root_directory());
942 _LIBCPP_HIDE_FROM_ABI path
root_path() const {
943 #if defined(_LIBCPP_WIN32API)
944 return string_type(__root_path_raw());
946 return root_name().append(string_type(__root_directory()));
949 _LIBCPP_HIDE_FROM_ABI path
relative_path() const {
950 return string_type(__relative_path());
952 _LIBCPP_HIDE_FROM_ABI path
parent_path() const {
953 return string_type(__parent_path());
955 _LIBCPP_HIDE_FROM_ABI path
filename() const {
956 return string_type(__filename());
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());
964 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
bool
965 empty() const noexcept
{
966 return __pn_
.empty();
969 _LIBCPP_HIDE_FROM_ABI
bool has_root_name() const {
970 return !__root_name().empty();
972 _LIBCPP_HIDE_FROM_ABI
bool has_root_directory() const {
973 return !__root_directory().empty();
975 _LIBCPP_HIDE_FROM_ABI
bool has_root_path() const {
976 return !__root_path_raw().empty();
978 _LIBCPP_HIDE_FROM_ABI
bool has_relative_path() const {
979 return !__relative_path().empty();
981 _LIBCPP_HIDE_FROM_ABI
bool has_parent_path() const {
982 return !__parent_path().empty();
984 _LIBCPP_HIDE_FROM_ABI
bool has_filename() const {
985 return !__filename().empty();
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();
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();
1000 // If no root name, it's relative, e.g. \example is relative to the current drive
1001 if (__root_name_str
.empty())
1003 if (__root_name_str
.size() < 3)
1005 // A server root name, like \\server, is always absolute
1006 if (__root_name_str
[0] != '/' && __root_name_str
[0] != '\\')
1008 if (__root_name_str
[1] != '/' && __root_name_str
[1] != '\\')
1010 // Seems to be a server root name
1013 return has_root_directory();
1016 _LIBCPP_HIDE_FROM_ABI
bool is_relative() const { return !is_absolute(); }
1019 path
lexically_normal() const;
1020 path
lexically_relative(const path
& __base
) const;
1022 _LIBCPP_HIDE_FROM_ABI path
lexically_proximate(const path
& __base
) const {
1023 path __result
= this->lexically_relative(__base
);
1024 if (__result
.native().empty())
1030 class _LIBCPP_EXPORTED_FROM_ABI iterator
;
1031 typedef iterator const_iterator
;
1033 iterator
begin() const;
1034 iterator
end() const;
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());
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
>());
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
);
1063 #endif // !_LIBCPP_HAS_NO_LOCALIZATION
1066 inline _LIBCPP_HIDE_FROM_ABI path
& __assign_view(__string_view
const& __s
) {
1067 __pn_
= string_type(__s
);
1073 inline _LIBCPP_HIDE_FROM_ABI
void swap(path
& __lhs
, path
& __rhs
) noexcept
{
1077 _LIBCPP_EXPORTED_FROM_ABI
size_t hash_value(const path
& __p
) noexcept
;
1079 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
1081 _LIBCPP_END_NAMESPACE_FILESYSTEM
1083 _LIBCPP_BEGIN_NAMESPACE_STD
1086 struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash
<_VSTD_FS::path
> : __unary_function
<_VSTD_FS::path
, size_t> {
1087 _LIBCPP_HIDE_FROM_ABI
size_t operator()(_VSTD_FS::path
const& __p
) const noexcept
{
1088 return _VSTD_FS::hash_value(__p
);
1092 _LIBCPP_END_NAMESPACE_STD
1094 #endif // _LIBCPP_CXX03_LANG
1096 #endif // _LIBCPP___FILESYSTEM_PATH_H