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>
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>
26 #include <string_view>
28 #if _LIBCPP_HAS_LOCALIZATION
29 # include <iomanip> // for quoted
33 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
34 # pragma GCC system_header
38 #include <__undef_macros>
40 #if _LIBCPP_STD_VER >= 17
42 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
44 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
47 struct __can_convert_char
{
48 static const bool value
= false;
51 struct __can_convert_char
<const _Tp
> : public __can_convert_char
<_Tp
> {};
53 struct __can_convert_char
<char> {
54 static const bool value
= true;
55 using __char_type
= char;
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
64 struct __can_convert_char
<char8_t
> {
65 static const bool value
= true;
66 using __char_type
= char8_t
;
70 struct __can_convert_char
<char16_t
> {
71 static const bool value
= true;
72 using __char_type
= char16_t
;
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('\\');
85 return __e
== _ECharT('/');
89 # if _LIBCPP_HAS_CHAR8_T
90 typedef u8string __u8_string
;
92 typedef string __u8_string
;
95 struct _NullSentinel
{};
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
{};
143 for (; *__e
!= __sentinel
; ++__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
<
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
; }
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");
178 struct __is_pathable
<_Tp
, true, false, false> : __is_pathable_string
<_Tp
> {};
181 struct __is_pathable
<_Tp
, false, true, false> : __is_pathable_char_array
<_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
;
190 typedef string __path_string
;
191 typedef char __path_value
;
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);
199 template <class _ECharT
>
202 # if _LIBCPP_HAS_LOCALIZATION
203 template <class _ECharT
>
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
;
212 _LIBCPP_HIDE_FROM_ABI
static void __append_range(__path_string
& __dest
, _ECharT
const* __b
, _ECharT
const* __e
) {
213 # if defined(_LIBCPP_WIN32API)
215 _Narrower()(back_inserter(__utf8
), __b
, __e
);
216 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
218 _Narrower()(back_inserter(__dest
), __b
, __e
);
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");
227 basic_string
<_ECharT
> __tmp(__b
, __e
);
228 # if defined(_LIBCPP_WIN32API)
230 _Narrower()(back_inserter(__utf8
), __tmp
.data(), __tmp
.data() + __tmp
.length());
231 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
233 _Narrower()(back_inserter(__dest
), __tmp
.data(), __tmp
.data() + __tmp
.length());
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
)
243 basic_string
<_ECharT
> __tmp
;
244 for (; *__b
!= __sentinel
; ++__b
)
245 __tmp
.push_back(*__b
);
246 # if defined(_LIBCPP_WIN32API)
248 _Narrower()(back_inserter(__utf8
), __tmp
.data(), __tmp
.data() + __tmp
.length());
249 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
251 _Narrower()(back_inserter(__dest
), __tmp
.data(), __tmp
.data() + __tmp
.length());
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
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)
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
>
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
) {
336 _Narrower()(back_inserter(__utf8
), __src
.data(), __src
.data() + __src
.size());
337 _Widener()(back_inserter(__dest
), __utf8
.data(), __utf8
.data() + __utf8
.size());
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
);
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());
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
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
>;
386 using _SourceChar
= typename __is_pathable
<_Tp
>::__char_type
;
389 using _SourceCVT
= _PathCVT
<_SourceChar
<_Tp
> >;
392 # if defined(_LIBCPP_WIN32API)
393 typedef wchar_t value_type
;
394 static constexpr value_type preferred_separator
= L
'\\';
396 typedef char value_type
;
397 static constexpr value_type preferred_separator
= '/';
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);
433 _LIBCPP_HIDE_FROM_ABI
~path() = default;
436 _LIBCPP_HIDE_FROM_ABI path
& operator=(const path
& __p
) {
441 _LIBCPP_HIDE_FROM_ABI path
& operator=(path
&& __p
) noexcept
{
442 __pn_
= std::move(__p
.__pn_
);
446 _LIBCPP_HIDE_FROM_ABI path
& operator=(string_type
&& __s
) noexcept
{
447 __pn_
= std::move(__s
);
451 _LIBCPP_HIDE_FROM_ABI path
& assign(string_type
&& __s
) noexcept
{
452 __pn_
= std::move(__s
);
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
) {
464 _SourceCVT
<_Source
>::__append_source(__pn_
, __src
);
468 template <class _InputIt
>
469 _LIBCPP_HIDE_FROM_ABI path
& assign(_InputIt __first
, _InputIt __last
) {
470 typedef typename iterator_traits
<_InputIt
>::value_type _ItVal
;
472 _PathCVT
<_ItVal
>::__append_range(__pn_
, __first
, __last
);
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_
))) {
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
);
492 if (has_filename() || (!has_root_directory() && is_absolute()))
493 __pn_
+= preferred_separator
;
494 __pn_
+= __string_view(__p
.__pn_
).substr(__p_root_name_size
);
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
));
512 _LIBCPP_HIDE_FROM_ABI path
& operator/=(const path
& __p
) {
513 if (__p
.is_absolute()) {
518 __pn_
+= preferred_separator
;
519 __pn_
+= __p
.native();
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
)
538 else if (has_filename())
539 __pn_
+= preferred_separator
;
540 _CVT::__append_source(__pn_
, __src
);
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
))
551 else if (has_filename())
552 __pn_
+= preferred_separator
;
553 _CVT::__append_range(__pn_
, __first
, __last
);
559 _LIBCPP_HIDE_FROM_ABI path
& operator+=(const path
& __x
) {
564 _LIBCPP_HIDE_FROM_ABI path
& operator+=(const string_type
& __x
) {
569 _LIBCPP_HIDE_FROM_ABI path
& operator+=(__string_view __x
) {
574 _LIBCPP_HIDE_FROM_ABI path
& operator+=(const value_type
* __x
) {
579 _LIBCPP_HIDE_FROM_ABI path
& operator+=(value_type __x
) {
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));
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
);
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
);
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
'\\');
618 _LIBCPP_HIDE_FROM_ABI path
& remove_filename() {
619 auto __fname
= __filename();
620 if (!__fname
.empty())
621 __pn_
.erase(__fname
.data() - __pn_
.data());
625 _LIBCPP_HIDE_FROM_ABI path
& replace_filename(const path
& __replacement
) {
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
);
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 {
680 __s
.resize(__pn_
.size());
681 std::replace_copy(__pn_
.begin(), __pn_
.end(), __s
.begin(), '\\', '/');
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
>;
690 __s
.reserve(__pn_
.size());
691 _PathExport
<_ECharT
>::__append(__s
, __pn_
);
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__
>;
699 __s
.reserve(__pn_
.size());
700 _CVT()(back_inserter(__s
), __pn_
.data(), __pn_
.data() + __pn_
.size());
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
>('/'));
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(), '\\', '/');
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()); }
735 _LIBCPP_HIDE_FROM_ABI
std::string
u8string() const { return __pn_
; }
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
>;
744 __s
.reserve(__pn_
.size());
745 _CVT()(std::back_inserter(__s
), __pn_
.data(), __pn_
.data() + __pn_
.size());
749 # if _LIBCPP_HAS_WIDE_CHARACTERS
750 _LIBCPP_HIDE_FROM_ABI
std::wstring
wstring() const { return string
<wchar_t>(); }
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()); }
761 _LIBCPP_HIDE_FROM_ABI
std::string
generic_u8string() const { return __pn_
; }
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>(); }
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 */
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;
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
); }
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());
804 return root_name().append(string_type(__root_directory()));
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()); }
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())
836 if (__root_name_str
.size() < 3)
838 // A server root name, like \\server, is always absolute
839 if (__root_name_str
[0] != '/' && __root_name_str
[0] != '\\')
841 if (__root_name_str
[1] != '/' && __root_name_str
[1] != '\\')
843 // Seems to be a server root name
846 return has_root_directory();
849 _LIBCPP_HIDE_FROM_ABI
bool is_relative() const { return !is_absolute(); }
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())
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
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());
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
>());
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
);
898 # endif // _LIBCPP_HAS_LOCALIZATION
901 inline _LIBCPP_HIDE_FROM_ABI path
& __assign_view(__string_view
const& __s
) {
902 __pn_
= string_type(__s
);
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
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
931 #endif // _LIBCPP___FILESYSTEM_PATH_H