30 #ifndef _GLIBCXX_FS_PATH_H
31 #define _GLIBCXX_FS_PATH_H 1
33 #if __cplusplus >= 201703L
36 #include <type_traits>
41 #include <string_view>
42 #include <system_error>
46 #include <bits/shared_ptr.h>
49 #if defined(_WIN32) && !defined(__CYGWIN__)
50 # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1
54 namespace std _GLIBCXX_VISIBILITY(default)
56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
60 _GLIBCXX_BEGIN_NAMESPACE_CXX11
71 template<
typename _CharT>
72 using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
74 #ifdef _GLIBCXX_USE_CHAR8_T
77 #if _GLIBCXX_USE_WCHAR_T
82 template<
typename _Iter,
84 using __is_path_iter_src
85 = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
87 typename _Iter_traits::iterator_category>>;
89 template<
typename _Iter>
90 static __is_path_iter_src<_Iter>
91 __is_path_src(_Iter,
int);
93 template<
typename _CharT,
typename _Traits,
typename _Alloc>
94 static __is_encoded_char<_CharT>
95 __is_path_src(
const basic_string<_CharT, _Traits, _Alloc>&,
int);
97 template<
typename _CharT,
typename _Traits>
98 static __is_encoded_char<_CharT>
99 __is_path_src(
const basic_string_view<_CharT, _Traits>&,
int);
101 template<
typename _Unknown>
103 __is_path_src(
const _Unknown&, ...);
105 template<
typename _Tp1,
typename _Tp2>
106 struct __constructible_from;
108 template<
typename _Iter>
109 struct __constructible_from<_Iter, _Iter>
110 : __is_path_iter_src<_Iter>
113 template<
typename _Source>
114 struct __constructible_from<_Source, void>
115 : decltype(__is_path_src(std::declval<_Source>(), 0))
118 template<
typename _Tp1,
typename _Tp2 =
void>
119 using _Path =
typename
121 __not_<is_void<remove_pointer_t<_Tp1>>>,
122 __constructible_from<_Tp1, _Tp2>>::value,
125 template<
typename _Source>
127 _S_range_begin(_Source __begin) {
return __begin; }
129 struct __null_terminated { };
131 template<
typename _Source>
132 static __null_terminated
133 _S_range_end(_Source) {
return {}; }
135 template<
typename _CharT,
typename _Traits,
typename _Alloc>
137 _S_range_begin(
const basic_string<_CharT, _Traits, _Alloc>& __str)
138 {
return __str.data(); }
140 template<
typename _CharT,
typename _Traits,
typename _Alloc>
142 _S_range_end(
const basic_string<_CharT, _Traits, _Alloc>& __str)
143 {
return __str.data() + __str.size(); }
145 template<
typename _CharT,
typename _Traits>
147 _S_range_begin(
const basic_string_view<_CharT, _Traits>& __str)
148 {
return __str.data(); }
150 template<
typename _CharT,
typename _Traits>
152 _S_range_end(
const basic_string_view<_CharT, _Traits>& __str)
153 {
return __str.data() + __str.size(); }
155 template<
typename _Tp,
156 typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
159 using __value_type_is_char
163 template<
typename _Tp,
164 typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
167 using __value_type_is_char_or_char8_t
170 #ifdef _GLIBCXX_USE_CHAR8_T
183 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
184 using value_type = wchar_t;
185 static constexpr value_type preferred_separator = L
'\\';
187 # ifdef _GLIBCXX_DOXYGEN
189 using value_type = __os_dependent__;
191 using value_type = char;
193 static constexpr value_type preferred_separator =
'/';
198 enum format :
unsigned char { native_format, generic_format, auto_format };
204 path(
const path& __p) =
default;
207 #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_FULLY_DYNAMIC_STRING == 0
210 : _M_pathname(
std::move(__p._M_pathname)),
214 path(string_type&& __source, format = auto_format)
215 : _M_pathname(
std::
move(__source))
216 { _M_split_cmpts(); }
218 template<
typename _Source,
219 typename _Require = __detail::_Path<_Source>>
220 path(_Source
const& __source, format = auto_format)
221 : _M_pathname(_S_convert(__detail::_S_range_begin(__source),
222 __detail::_S_range_end(__source)))
223 { _M_split_cmpts(); }
225 template<
typename _InputIterator,
226 typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
227 path(_InputIterator __first, _InputIterator __last, format = auto_format)
228 : _M_pathname(_S_convert(__first, __last))
229 { _M_split_cmpts(); }
231 template<
typename _Source,
232 typename _Require = __detail::_Path<_Source>,
233 typename _Require2 = __detail::__value_type_is_char<_Source>>
234 path(_Source
const& __source,
const locale& __loc, format = auto_format)
235 : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
236 __detail::_S_range_end(__source), __loc))
237 { _M_split_cmpts(); }
239 template<
typename _InputIterator,
240 typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
241 typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
242 path(_InputIterator __first, _InputIterator __last,
const locale& __loc,
243 format = auto_format)
244 : _M_pathname(_S_convert_loc(__first, __last, __loc))
245 { _M_split_cmpts(); }
251 path& operator=(
const path&);
252 path& operator=(path&&) noexcept;
253 path& operator=(string_type&& __source);
254 path& assign(string_type&& __source);
256 template<typename _Source>
257 __detail::_Path<_Source>&
258 operator=(_Source const& __source)
259 {
return *
this = path(__source); }
261 template<
typename _Source>
262 __detail::_Path<_Source>&
263 assign(_Source
const& __source)
264 {
return *
this = path(__source); }
266 template<
typename _InputIterator>
267 __detail::_Path<_InputIterator, _InputIterator>&
268 assign(_InputIterator __first, _InputIterator __last)
269 {
return *
this = path(__first, __last); }
273 path& operator/=(
const path& __p);
275 template<
typename _Source>
276 __detail::_Path<_Source>&
277 operator/=(_Source
const& __source)
279 _M_append(_S_convert(__detail::_S_range_begin(__source),
280 __detail::_S_range_end(__source)));
284 template<
typename _Source>
285 __detail::_Path<_Source>&
286 append(_Source
const& __source)
288 _M_append(_S_convert(__detail::_S_range_begin(__source),
289 __detail::_S_range_end(__source)));
293 template<
typename _InputIterator>
294 __detail::_Path<_InputIterator, _InputIterator>&
295 append(_InputIterator __first, _InputIterator __last)
297 _M_append(_S_convert(__first, __last));
303 path& operator+=(
const path& __x);
304 path& operator+=(
const string_type& __x);
305 path& operator+=(
const value_type* __x);
306 path& operator+=(value_type __x);
307 path& operator+=(basic_string_view<value_type> __x);
309 template<
typename _Source>
310 __detail::_Path<_Source>&
311 operator+=(_Source
const& __x) {
return concat(__x); }
313 template<
typename _CharT>
314 __detail::_Path<_CharT*, _CharT*>&
315 operator+=(_CharT __x);
317 template<
typename _Source>
318 __detail::_Path<_Source>&
319 concat(_Source
const& __x)
321 _M_concat(_S_convert(__detail::_S_range_begin(__x),
322 __detail::_S_range_end(__x)));
326 template<
typename _InputIterator>
327 __detail::_Path<_InputIterator, _InputIterator>&
328 concat(_InputIterator __first, _InputIterator __last)
330 _M_concat(_S_convert(__first, __last));
336 void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
338 path& make_preferred();
339 path& remove_filename();
340 path& replace_filename(
const path& __replacement);
341 path& replace_extension(
const path& __replacement = path());
343 void swap(path& __rhs) noexcept;
347 const string_type& native() const noexcept {
return _M_pathname; }
348 const value_type* c_str() const noexcept {
return _M_pathname.c_str(); }
349 operator string_type()
const {
return _M_pathname; }
351 template<
typename _CharT,
typename _Traits = std::
char_traits<_CharT>,
352 typename _Allocator = std::allocator<_CharT>>
354 string(
const _Allocator& __a = _Allocator())
const;
357 #if _GLIBCXX_USE_WCHAR_T
360 #ifdef _GLIBCXX_USE_CHAR8_T
361 __attribute__((__abi_tag__(
"__u8")))
362 std::u8string u8string() const;
365 #endif // _GLIBCXX_USE_CHAR8_T
370 template<
typename _CharT,
typename _Traits = std::
char_traits<_CharT>,
371 typename _Allocator = std::allocator<_CharT>>
373 generic_string(
const _Allocator& __a = _Allocator())
const;
376 #if _GLIBCXX_USE_WCHAR_T
379 #ifdef _GLIBCXX_USE_CHAR8_T
380 __attribute__((__abi_tag__(
"__u8")))
381 std::u8string generic_u8string() const;
384 #endif // _GLIBCXX_USE_CHAR8_T
390 int compare(
const path& __p)
const noexcept;
391 int compare(
const string_type& __s)
const noexcept;
392 int compare(
const value_type* __s)
const noexcept;
393 int compare(basic_string_view<value_type> __s)
const noexcept;
397 path root_name()
const;
398 path root_directory()
const;
399 path root_path()
const;
400 path relative_path()
const;
401 path parent_path()
const;
402 path filename()
const;
404 path extension()
const;
408 [[nodiscard]]
bool empty() const noexcept {
return _M_pathname.empty(); }
409 bool has_root_name() const noexcept;
410 bool has_root_directory() const noexcept;
411 bool has_root_path() const noexcept;
412 bool has_relative_path() const noexcept;
413 bool has_parent_path() const noexcept;
414 bool has_filename() const noexcept;
415 bool has_stem() const noexcept;
416 bool has_extension() const noexcept;
417 bool is_absolute() const noexcept;
418 bool is_relative() const noexcept {
return !is_absolute(); }
421 path lexically_normal()
const;
422 path lexically_relative(
const path& base)
const;
423 path lexically_proximate(
const path& base)
const;
427 using const_iterator = iterator;
429 iterator
begin()
const;
430 iterator
end()
const;
433 template<
typename _CharT,
typename _Traits>
437 __os <<
std::quoted(__p.string<_CharT, _Traits>());
442 template<
typename _CharT,
typename _Traits>
455 friend bool operator<(
const path& __lhs,
const path& __rhs) noexcept
456 {
return __lhs.compare(__rhs) < 0; }
459 friend bool operator<=(
const path& __lhs,
const path& __rhs) noexcept
460 {
return !(__rhs < __lhs); }
463 friend bool operator>(
const path& __lhs,
const path& __rhs) noexcept
464 {
return __rhs < __lhs; }
467 friend bool operator>=(
const path& __lhs,
const path& __rhs) noexcept
468 {
return !(__lhs < __rhs); }
471 friend bool operator==(
const path& __lhs,
const path& __rhs) noexcept
472 {
return __lhs.compare(__rhs) == 0; }
475 friend bool operator!=(
const path& __lhs,
const path& __rhs) noexcept
476 {
return !(__lhs == __rhs); }
479 friend path
operator/(
const path& __lhs,
const path& __rhs)
481 path __result(__lhs);
488 template<
typename _InputIterator,
493 _S_string_from_iter(_InputIterator __source)
496 for (_CharT __ch = *__source; __ch != _CharT(); __ch = *++__source)
503 enum class _Type : unsigned char {
504 _Multi = 0, _Root_name, _Root_dir, _Filename
507 path(basic_string_view<value_type> __str, _Type __type)
510 __glibcxx_assert(__type != _Type::_Multi);
511 _M_cmpts.type(__type);
514 enum class _Split { _Stem, _Extension };
516 void _M_append(basic_string_view<value_type>);
517 void _M_concat(basic_string_view<value_type>);
519 pair<const string_type*, size_t> _M_find_extension() const noexcept;
521 template<typename _CharT>
524 static basic_string_view<value_type>
525 _S_convert(value_type* __src, __detail::__null_terminated)
528 static basic_string_view<value_type>
529 _S_convert(
const value_type* __src, __detail::__null_terminated)
532 static basic_string_view<value_type>
533 _S_convert(value_type* __first, value_type* __last)
534 {
return {__first, __last - __first}; }
536 static basic_string_view<value_type>
537 _S_convert(
const value_type* __first,
const value_type* __last)
538 {
return {__first, __last - __first}; }
540 template<
typename _Iter>
542 _S_convert(_Iter __first, _Iter __last)
545 return _Cvt<typename remove_cv<__value_type>::type>::
546 _S_convert(__first, __last);
549 template<
typename _InputIterator>
551 _S_convert(_InputIterator __src, __detail::__null_terminated)
554 auto __s = _S_string_from_iter(__src);
556 return string_type(_S_convert(__s.data(), __s.data() + __s.size()));
560 _S_convert_loc(
const char* __first,
const char* __last,
563 template<
typename _Iter>
565 _S_convert_loc(_Iter __first, _Iter __last,
const std::locale& __loc)
568 return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc);
571 template<
typename _InputIterator>
573 _S_convert_loc(_InputIterator __src, __detail::__null_terminated,
576 const std::string __s = _S_string_from_iter(__src);
577 return _S_convert_loc(__s.
data(), __s.
data() + __s.
size(), __loc);
580 template<
typename _CharT,
typename _Traits,
typename _Allocator>
581 static basic_string<_CharT, _Traits, _Allocator>
582 _S_str_convert(basic_string_view<value_type>,
const _Allocator&);
584 void _M_split_cmpts();
586 _Type _M_type() const noexcept {
return _M_cmpts.type(); }
588 string_type _M_pathname;
594 using value_type = _Cmpt;
595 using iterator = value_type*;
596 using const_iterator =
const value_type*;
600 _List(_List&&) =
default;
601 _List& operator=(
const _List&);
602 _List& operator=(_List&&) =
default;
605 _Type type() const noexcept
606 {
return _Type{
reinterpret_cast<uintptr_t
>(_M_impl.get()) & 0x3}; }
608 void type(_Type) noexcept;
610 int size() const noexcept;
611 bool empty() const noexcept;
613 void swap(_List& __l) noexcept { _M_impl.swap(__l._M_impl); }
614 int capacity() const noexcept;
615 void reserve(
int,
bool);
622 const_iterator
begin() const;
623 const_iterator
end() const;
625 value_type& front() noexcept;
626 value_type& back() noexcept;
627 const value_type& front() const noexcept;
628 const value_type& back() const noexcept;
631 void _M_erase_from(const_iterator __pos);
636 void operator()(_Impl*)
const noexcept;
638 unique_ptr<_Impl, _Impl_deleter> _M_impl;
647 inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
649 size_t hash_value(
const path& __p) noexcept;
657 filesystem_error(
const string& __what_arg, error_code __ec);
659 filesystem_error(
const string& __what_arg,
const path& __p1,
662 filesystem_error(
const string& __what_arg,
const path& __p1,
663 const path& __p2, error_code __ec);
665 filesystem_error(
const filesystem_error&) =
default;
666 filesystem_error& operator=(
const filesystem_error&) =
default;
673 const path& path1() const noexcept;
674 const path& path2() const noexcept;
675 const
char* what() const noexcept;
679 std::__shared_ptr<const _Impl> _M_impl;
686 template<typename _InputIterator,
687 typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
689 = __detail::__value_type_is_char_or_char8_t<_InputIterator>>
691 u8path(_InputIterator __first, _InputIterator __last)
693 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
694 if constexpr (is_same_v<_CharT, char>)
697 std::codecvt_utf8_utf16<path::value_type> __cvt;
698 path::string_type __tmp;
699 if constexpr (is_pointer_v<_InputIterator>)
701 if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
702 return path{ __tmp };
707 const char*
const __p = __u8str.data();
708 if (__str_codecvt_in_all(__p, __p + __u8str.size(), __tmp, __cvt))
709 return path{ __tmp };
711 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
712 "Cannot convert character sequence",
713 std::make_error_code(errc::illegal_byte_sequence)));
716 return path{ __first, __last };
719 return path{ __first, __last };
727 template<
typename _Source,
728 typename _Require = __detail::_Path<_Source>,
729 typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
731 u8path(
const _Source& __source)
733 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
734 if constexpr (is_same_v<_CharT, char>)
736 if constexpr (is_convertible_v<const _Source&, std::string_view>)
738 const std::string_view __s = __source;
739 return filesystem::u8path(__s.data(), __s.data() + __s.size());
743 std::string __s = path::_S_string_from_iter(__source);
744 return filesystem::u8path(__s.
data(), __s.
data() + __s.
size());
748 return path{ __source };
750 return path{ __source };
756 struct path::_Cmpt : path
758 _Cmpt(basic_string_view<value_type> __s, _Type __t,
size_t __pos)
759 : path(__s, __t), _M_pos(__pos) { }
761 _Cmpt() : _M_pos(-1) { }
768 struct path::_Cvt<path::value_type>
770 template<
typename _Iter>
772 _S_convert(_Iter __first, _Iter __last)
773 {
return string_type{__first, __last}; }
776 #if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS && defined _GLIBCXX_USE_CHAR8_T
779 struct path::_Cvt<char8_t>
781 template<
typename _Iter>
783 _S_convert(_Iter __first, _Iter __last)
784 {
return string_type(__first, __last); }
788 template<
typename _CharT>
792 _S_convert(
const _CharT* __f,
const _CharT* __l)
794 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
796 if constexpr (is_same_v<_CharT, char>)
798 struct _UCvt :
std::codecvt<wchar_t, char, std::mbstate_t>
800 if (__str_codecvt_in_all(__f, __l, __wstr, __cvt))
803 #ifdef _GLIBCXX_USE_CHAR8_T
804 else if constexpr (is_same_v<_CharT, char8_t>)
806 const char* __f2 = (
const char*)__f;
807 const char* __l2 = (
const char*)__l;
808 std::codecvt_utf8_utf16<wchar_t> __wcvt;
809 if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
815 struct _UCvt :
std::codecvt<_CharT, char, std::mbstate_t>
818 if (__str_codecvt_out_all(__f, __l, __str, __cvt))
820 const char* __f2 = __str.
data();
821 const char* __l2 = __f2 + __str.
size();
822 std::codecvt_utf8_utf16<wchar_t> __wcvt;
823 if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
828 struct _UCvt :
std::codecvt<_CharT, char, std::mbstate_t>
831 if (__str_codecvt_out_all(__f, __l, __str, __cvt))
834 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
835 "Cannot convert character sequence",
836 std::make_error_code(errc::illegal_byte_sequence)));
840 _S_convert(_CharT* __f, _CharT* __l)
842 return _S_convert(
const_cast<const _CharT*
>(__f),
843 const_cast<const _CharT*
>(__l));
846 template<
typename _Iter>
848 _S_convert(_Iter __first, _Iter __last)
851 return _S_convert(__str.
data(), __str.
data() + __str.
size());
854 template<
typename _Iter,
typename _Cont>
856 _S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first,
857 __gnu_cxx::__normal_iterator<_Iter, _Cont> __last)
858 {
return _S_convert(__first.base(), __last.base()); }
867 using difference_type = std::ptrdiff_t;
868 using value_type = path;
869 using reference =
const path&;
870 using pointer =
const path*;
873 iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { }
875 iterator(
const iterator&) =
default;
876 iterator& operator=(
const iterator&) =
default;
881 iterator& operator++();
882 iterator operator++(
int) {
auto __tmp = *
this; ++*
this;
return __tmp; }
884 iterator& operator--();
885 iterator operator--(
int) {
auto __tmp = *
this; --*
this;
return __tmp; }
887 friend bool operator==(
const iterator& __lhs,
const iterator& __rhs)
888 {
return __lhs._M_equals(__rhs); }
890 friend bool operator!=(
const iterator& __lhs,
const iterator& __rhs)
891 {
return !__lhs._M_equals(__rhs); }
896 bool _M_is_multi()
const {
return _M_path->_M_type() == _Type::_Multi; }
898 friend difference_type
899 __path_iter_distance(
const iterator& __first,
const iterator& __last)
901 __glibcxx_assert(__first._M_path !=
nullptr);
902 __glibcxx_assert(__first._M_path == __last._M_path);
903 if (__first._M_is_multi())
905 else if (__first._M_at_end == __last._M_at_end)
908 return __first._M_at_end ? -1 : 1;
912 __path_iter_advance(iterator& __i, difference_type __n)
920 __glibcxx_assert(__i._M_path !=
nullptr);
921 __glibcxx_assert(__i._M_is_multi());
927 iterator(
const path* __path, path::_List::const_iterator __iter)
928 : _M_path(__path), _M_cur(__iter), _M_at_end()
931 iterator(
const path* __path,
bool __at_end)
932 : _M_path(__path), _M_cur(), _M_at_end(__at_end)
935 bool _M_equals(iterator)
const;
938 path::_List::const_iterator _M_cur;
944 path::operator=(path&& __p) noexcept
946 if (&__p ==
this) [[__unlikely__]]
949 _M_pathname =
std::move(__p._M_pathname);
956 path::operator=(string_type&& __source)
957 {
return *
this = path(
std::move(__source)); }
960 path::assign(string_type&& __source)
961 {
return *
this = path(
std::move(__source)); }
964 path::operator+=(
const string_type& __x)
971 path::operator+=(
const value_type* __x)
978 path::operator+=(value_type __x)
980 _M_concat(basic_string_view<value_type>(&__x, 1));
985 path::operator+=(basic_string_view<value_type> __x)
991 template<
typename _CharT>
992 inline __detail::_Path<_CharT*, _CharT*>&
993 path::operator+=(_CharT __x)
996 return concat(__addr, __addr + 1);
1000 path::make_preferred()
1002 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1003 std::replace(_M_pathname.begin(), _M_pathname.end(), L
'/',
1004 preferred_separator);
1009 inline void path::swap(path& __rhs) noexcept
1011 _M_pathname.swap(__rhs._M_pathname);
1012 _M_cmpts.swap(__rhs._M_cmpts);
1016 template<
typename _CharT,
typename _Traits,
typename _Allocator>
1018 path::_S_str_convert(basic_string_view<value_type> __str,
1019 const _Allocator& __a)
1021 static_assert(!is_same_v<_CharT, value_type>);
1023 using _WString = basic_string<_CharT, _Traits, _Allocator>;
1025 if (__str.size() == 0)
1026 return _WString(__a);
1028 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1031 std::codecvt_utf8_utf16<value_type> __cvt;
1033 using _CharAlloc = __alloc_rebind<_Allocator, char>;
1034 using _String = basic_string<char, char_traits<char>, _CharAlloc>;
1035 _String __u8str{_CharAlloc{__a}};
1036 const value_type* __wfirst = __str.data();
1037 const value_type* __wlast = __wfirst + __str.size();
1038 if (__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt)) {
1039 if constexpr (is_same_v<_CharT, char>)
1043 const char* __first = __u8str.data();
1044 const char* __last = __first + __u8str.size();
1046 const value_type* __first = __str.data();
1047 const value_type* __last = __first + __str.size();
1051 #ifdef _GLIBCXX_USE_CHAR8_T
1052 if constexpr (is_same_v<_CharT, char8_t>)
1053 return _WString(__first, __last, __a);
1058 _WString __wstr(__a);
1059 struct _UCvt :
std::codecvt<_CharT, char, std::mbstate_t> { } __cvt;
1060 if (__str_codecvt_in_all(__first, __last, __wstr, __cvt))
1064 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1067 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1068 "Cannot convert character sequence",
1069 std::make_error_code(errc::illegal_byte_sequence)));
1073 template<
typename _CharT,
typename _Traits,
typename _Allocator>
1074 inline basic_string<_CharT, _Traits, _Allocator>
1077 if constexpr (is_same_v<_CharT, value_type>)
1078 return { _M_pathname.
c_str(), _M_pathname.length(), __a };
1080 return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);
1086 #if _GLIBCXX_USE_WCHAR_T
1091 #ifdef _GLIBCXX_USE_CHAR8_T
1092 inline std::u8string
1093 path::u8string()
const {
return string<char8_t>(); }
1096 path::u8string()
const
1098 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1101 std::codecvt_utf8_utf16<value_type> __cvt;
1102 const value_type* __first = _M_pathname.data();
1103 const value_type* __last = __first + _M_pathname.size();
1104 if (__str_codecvt_out_all(__first, __last, __str, __cvt))
1106 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1107 "Cannot convert character sequence",
1108 std::make_error_code(errc::illegal_byte_sequence)));
1113 #endif // _GLIBCXX_USE_CHAR8_T
1121 template<
typename _CharT,
typename _Traits,
typename _Allocator>
1123 path::generic_string(
const _Allocator& __a)
const
1125 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1126 const value_type __slash = L
'/';
1128 const value_type __slash =
'/';
1130 using _Alloc2 =
typename allocator_traits<_Allocator>::template
1131 rebind_alloc<value_type>;
1132 basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a);
1134 if (_M_type() == _Type::_Root_dir)
1135 __str.
assign(1, __slash);
1138 __str.
reserve(_M_pathname.size());
1139 bool __add_slash =
false;
1140 for (
auto& __elem : *
this)
1142 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1143 if (__elem._M_type() == _Type::_Root_dir)
1151 __str += basic_string_view<value_type>(__elem._M_pathname);
1152 __add_slash = __elem._M_type() == _Type::_Filename;
1156 if constexpr (is_same_v<_CharT, value_type>)
1159 return _S_str_convert<_CharT, _Traits>(__str, __a);
1163 path::generic_string()
const
1164 {
return generic_string<char>(); }
1166 #if _GLIBCXX_USE_WCHAR_T
1168 path::generic_wstring()
const
1169 {
return generic_string<wchar_t>(); }
1172 #ifdef _GLIBCXX_USE_CHAR8_T
1173 inline std::u8string
1174 path::generic_u8string()
const
1175 {
return generic_string<char8_t>(); }
1178 path::generic_u8string()
const
1179 {
return generic_string(); }
1183 path::generic_u16string()
const
1184 {
return generic_string<char16_t>(); }
1187 path::generic_u32string()
const
1188 {
return generic_string<char32_t>(); }
1191 path::compare(
const string_type& __s)
const noexcept
1192 {
return compare(basic_string_view<value_type>(__s)); }
1195 path::compare(
const value_type* __s)
const noexcept
1196 {
return compare(basic_string_view<value_type>(__s)); }
1199 path::filename()
const
1203 else if (_M_type() == _Type::_Filename)
1205 else if (_M_type() == _Type::_Multi)
1207 if (_M_pathname.back() == preferred_separator)
1209 auto& __last = *--
end();
1210 if (__last._M_type() == _Type::_Filename)
1219 auto ext = _M_find_extension();
1220 if (ext.first && ext.second != 0)
1221 return path{ext.first->substr(0, ext.second)};
1226 path::extension()
const
1228 auto ext = _M_find_extension();
1229 if (ext.first && ext.second != string_type::npos)
1230 return path{ext.first->substr(ext.second)};
1235 path::has_stem() const noexcept
1237 auto ext = _M_find_extension();
1238 return ext.first && ext.second != 0;
1242 path::has_extension() const noexcept
1244 auto ext = _M_find_extension();
1245 return ext.first && ext.second != string_type::npos;
1249 path::is_absolute() const noexcept
1251 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1252 return has_root_name() && has_root_directory();
1254 return has_root_directory();
1258 inline path::iterator
1261 if (_M_type() == _Type::_Multi)
1262 return iterator(
this, _M_cmpts.begin());
1263 return iterator(
this, empty());
1266 inline path::iterator
1269 if (_M_type() == _Type::_Multi)
1270 return iterator(
this, _M_cmpts.end());
1271 return iterator(
this,
true);
1274 inline path::iterator&
1275 path::iterator::operator++()
1277 __glibcxx_assert(_M_path !=
nullptr);
1278 if (_M_path->_M_type() == _Type::_Multi)
1280 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1285 __glibcxx_assert(!_M_at_end);
1291 inline path::iterator&
1292 path::iterator::operator--()
1294 __glibcxx_assert(_M_path !=
nullptr);
1295 if (_M_path->_M_type() == _Type::_Multi)
1297 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
1302 __glibcxx_assert(_M_at_end);
1308 inline path::iterator::reference
1311 __glibcxx_assert(_M_path !=
nullptr);
1312 if (_M_path->_M_type() == _Type::_Multi)
1314 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1321 path::iterator::_M_equals(iterator __rhs)
const
1323 if (_M_path != __rhs._M_path)
1325 if (_M_path ==
nullptr)
1327 if (_M_path->_M_type() == path::_Type::_Multi)
1328 return _M_cur == __rhs._M_cur;
1329 return _M_at_end == __rhs._M_at_end;
1333 _GLIBCXX_END_NAMESPACE_CXX11
1337 distance(filesystem::path::iterator __first, filesystem::path::iterator __last)
1338 {
return __path_iter_distance(__first, __last); }
1340 template<
typename _InputIterator,
typename _Distance>
1342 advance(filesystem::path::iterator& __i, _Distance __n)
1343 { __path_iter_advance(__i,
static_cast<ptrdiff_t
>(__n)); }
1345 extern template class __shared_ptr<const filesystem::filesystem_error::_Impl>;
1347 _GLIBCXX_END_NAMESPACE_VERSION
1352 #endif // _GLIBCXX_FS_PATH_H