1// Class filesystem::path -*- C++ -*- 
2 
3// Copyright (C) 2014-2021 Free Software Foundation, Inc. 
4// 
5// This file is part of the GNU ISO C++ Library. This library is free 
6// software; you can redistribute it and/or modify it under the 
7// terms of the GNU General Public License as published by the 
8// Free Software Foundation; either version 3, or (at your option) 
9// any later version. 
10 
11// This library is distributed in the hope that it will be useful, 
12// but WITHOUT ANY WARRANTY; without even the implied warranty of 
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
14// GNU General Public License for more details. 
15 
16// Under Section 7 of GPL version 3, you are granted additional 
17// permissions described in the GCC Runtime Library Exception, version 
18// 3.1, as published by the Free Software Foundation. 
19 
20// You should have received a copy of the GNU General Public License and 
21// a copy of the GCC Runtime Library Exception along with this program; 
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 
23// <http://www.gnu.org/licenses/>. 
24 
25/** @file include/bits/fs_path.h 
26 * This is an internal header file, included by other library headers. 
27 * Do not attempt to use it directly. @headername{filesystem} 
28 */ 
29 
30#ifndef _GLIBCXX_FS_PATH_H 
31#define _GLIBCXX_FS_PATH_H 1 
32 
33#if __cplusplus >= 201703L 
34 
35#include <utility> 
36#include <type_traits> 
37#include <locale> 
38#include <iosfwd> 
39#include <iomanip> 
40#include <codecvt> 
41#include <string_view> 
42#include <system_error> 
43#include <bits/stl_algobase.h> 
44#include <bits/locale_conv.h> 
45#include <ext/concurrence.h> 
46#include <bits/shared_ptr.h> 
47#include <bits/unique_ptr.h> 
48 
49#if __cplusplus > 201703L 
50# include <compare> 
51#endif 
52 
53#if defined(_WIN32) && !defined(__CYGWIN__) 
54# define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 
55# include <algorithm> 
56#endif 
57 
58namespace std _GLIBCXX_VISIBILITY(default
59
60_GLIBCXX_BEGIN_NAMESPACE_VERSION 
61 
62namespace filesystem 
63
64_GLIBCXX_BEGIN_NAMESPACE_CXX11 
65 
66 class path
67 
68 /// @cond undocumented 
69namespace __detail 
70
71 /// @addtogroup filesystem 
72 /// @{ 
73 template<typename _CharT> 
74 inline constexpr bool __is_encoded_char = false
75 template<> 
76 inline constexpr bool __is_encoded_char<char> = true
77#ifdef _GLIBCXX_USE_CHAR8_T 
78 template<> 
79 inline constexpr bool __is_encoded_char<char8_t> = true
80#endif 
81#if _GLIBCXX_USE_WCHAR_T 
82 template<> 
83 inline constexpr bool __is_encoded_char<wchar_t> = true
84#endif 
85 template<> 
86 inline constexpr bool __is_encoded_char<char16_t> = true
87 template<> 
88 inline constexpr bool __is_encoded_char<char32_t> = true
89 
90#if __cpp_concepts >= 201907L 
91 template<typename _Iter> 
92 using __safe_iterator_traits = std::iterator_traits<_Iter>; 
93#else 
94 template<typename _Iter> 
95 struct __safe_iterator_traits : std::iterator_traits<_Iter> 
96 { }; 
97 
98 // Protect against ill-formed iterator_traits specializations in C++17 
99 template<> struct __safe_iterator_traits<void*> { }; 
100 template<> struct __safe_iterator_traits<const void*> { }; 
101 template<> struct __safe_iterator_traits<volatile void*> { }; 
102 template<> struct __safe_iterator_traits<const volatile void*> { }; 
103#endif 
104 
105 template<typename _Iter_traits, typename = void
106 struct __is_path_iter_src 
107 : false_type 
108 { }; 
109 
110 template<typename _Iter_traits> 
111 struct __is_path_iter_src<_Iter_traits, 
112 void_t<typename _Iter_traits::value_type>> 
113 : bool_constant<__is_encoded_char<typename _Iter_traits::value_type>> 
114 { }; 
115 
116 template<typename _Source> 
117 inline constexpr bool __is_path_src 
118 = __is_path_iter_src<iterator_traits<decay_t<_Source>>>::value; 
119 
120 template<> 
121 inline constexpr bool __is_path_src<path> = false
122 
123 template<> 
124 inline constexpr bool __is_path_src<volatile path> = false
125 
126 template<> 
127 inline constexpr bool __is_path_src<void*> = false
128 
129 template<> 
130 inline constexpr bool __is_path_src<const void*> = false
131 
132 template<> 
133 inline constexpr bool __is_path_src<volatile void*> = false
134 
135 template<> 
136 inline constexpr bool __is_path_src<const volatile void*> = false
137 
138 template<typename _CharT, typename _Traits, typename _Alloc> 
139 inline constexpr bool 
140 __is_path_src<basic_string<_CharT, _Traits, _Alloc>> 
141 = __is_encoded_char<_CharT>; 
142 
143 template<typename _CharT, typename _Traits> 
144 inline constexpr bool 
145 __is_path_src<basic_string_view<_CharT, _Traits>> 
146 = __is_encoded_char<_CharT>; 
147 
148 // SFINAE constraint for Source parameters as required by [fs.path.req]. 
149 template<typename _Tp> 
150 using _Path = enable_if_t<__is_path_src<_Tp>, path>; 
151 
152 // SFINAE constraint for InputIterator parameters as required by [fs.req]. 
153 template<typename _Iter, typename _Tr = __safe_iterator_traits<_Iter>> 
154 using _Path2 = enable_if_t<__is_path_iter_src<_Tr>::value, path>; 
155 
156 // The __effective_range overloads convert a Source parameter into 
157 // either a basic_string_view or basic_string containing the 
158 // effective range of the Source, as defined in [fs.path.req]. 
159 
160 template<typename _CharT, typename _Traits, typename _Alloc> 
161 inline basic_string_view<_CharT, _Traits> 
162 __effective_range(const basic_string<_CharT, _Traits, _Alloc>& __source
163 { return __source; } 
164 
165 template<typename _CharT, typename _Traits> 
166 inline const basic_string_view<_CharT, _Traits>& 
167 __effective_range(const basic_string_view<_CharT, _Traits>& __source
168 { return __source; } 
169 
170 template<typename _Source> 
171 inline auto 
172 __effective_range(const _Source& __source
173
174 if constexpr (is_pointer_v<decay_t<_Source>>) 
175 return basic_string_view{&*__source}; 
176 else 
177
178 // _Source is an input iterator that iterates over an NTCTS. 
179 // Create a basic_string by reading until the null character. 
180 using value_type 
181 = typename iterator_traits<_Source>::value_type; 
182 basic_string<value_type> __str
183 _Source __it = __source
184 for (value_type __ch = *__it; __ch != value_type(); __ch = *++__it
185 __str.push_back(__ch); 
186 return __str
187
188
189 
190 // The value type of a Source parameter's effective range. 
191 template<typename _Tp> 
192 using __value_t = typename remove_reference_t
193 decltype(__detail::__effective_range(std::declval<_Tp>()))>::value_type; 
194 
195 // SFINAE helper to check that an effective range has value_type char, 
196 // as required by path constructors taking a std::locale parameter. 
197 // The type _Tp must have already been checked by _Path<Tp> or _Path2<_Tp>. 
198 template<typename _Tp, typename _Val = __value_t<_Tp>> 
199 using __value_type_is_char 
200 = std::enable_if_t<std::is_same_v<_Val, char>, _Val>; 
201 
202 // As above, but also allows char8_t, as required by u8path 
203 // C++20 [depr.fs.path.factory] 
204 template<typename _Tp, typename _Val = __value_t<_Tp>> 
205 using __value_type_is_char_or_char8_t 
206 = std::enable_if_t<std::is_same_v<_Val, char
207#ifdef _GLIBCXX_USE_CHAR8_T 
208 || std::is_same_v<_Val, char8_t
209#endif 
210 , _Val>; 
211 
212 // Create a string or string view from an iterator range. 
213 template<typename _InputIterator> 
214 inline auto 
215 __string_from_range(_InputIterator __first, _InputIterator __last
216
217 using _EcharT 
218 = typename std::iterator_traits<_InputIterator>::value_type; 
219 static_assert(__is_encoded_char<_EcharT>); 
220 
221#if __cpp_lib_concepts 
222 constexpr bool __contiguous = std::contiguous_iterator<_InputIterator>; 
223#else 
224 constexpr bool __contiguous 
225 = is_pointer_v<decltype(std::__niter_base(__first))>; 
226#endif 
227 if constexpr (__contiguous
228
229 // For contiguous iterators we can just return a string view. 
230 const auto* __f = std::__to_address(std::__niter_base(__first)); 
231 const auto* __l = std::__to_address(std::__niter_base(__last)); 
232 return basic_string_view<_EcharT>(__f, __l - __f); 
233
234 else 
235 // Conversion requires contiguous characters, so create a string. 
236 return basic_string<_EcharT>(__first, __last); 
237
238 
239 /// @} group filesystem 
240} // namespace __detail 
241 /// @endcond 
242 
243 /// @addtogroup filesystem 
244 /// @{ 
245 
246 /// A filesystem path 
247 /// @ingroup filesystem 
248 class path 
249
250 public
251#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
252 using value_type = wchar_t
253 static constexpr value_type preferred_separator = L'\\'
254#else 
255# ifdef _GLIBCXX_DOXYGEN 
256 /// Windows uses wchar_t for path::value_type, POSIX uses char. 
257 using value_type = __os_dependent__; 
258# else 
259 using value_type = char
260# endif 
261 static constexpr value_type preferred_separator = '/'
262#endif 
263 using string_type = std::basic_string<value_type>; 
264 
265 /// path::format is ignored in this implementation 
266 enum format : unsigned char { native_format, generic_format, auto_format }; 
267 
268 // constructors and destructor 
269 
270 path() noexcept { } 
271 
272 path(const path& __p) = default
273 
274 path(path&& __p
275#if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_FULLY_DYNAMIC_STRING == 0 
276 noexcept 
277#endif 
278 : _M_pathname(std::move(__p._M_pathname)), 
279 _M_cmpts(std::move(__p._M_cmpts)) 
280 { __p.clear(); } 
281 
282 path(string_type&& __source, format = auto_format
283 : _M_pathname(std::move(__source)) 
284 { _M_split_cmpts(); } 
285 
286 template<typename _Source, 
287 typename _Require = __detail::_Path<_Source>> 
288 path(_Source const& __source, format = auto_format
289 : _M_pathname(_S_convert(__detail::__effective_range(__source))) 
290 { _M_split_cmpts(); } 
291 
292 template<typename _InputIterator, 
293 typename _Require = __detail::_Path2<_InputIterator>> 
294 path(_InputIterator __first, _InputIterator __last, format = auto_format
295 : _M_pathname(_S_convert(__detail::__string_from_range(__first, __last))) 
296 { _M_split_cmpts(); } 
297 
298 template<typename _Source, 
299 typename _Require = __detail::_Path<_Source>, 
300 typename _Require2 = __detail::__value_type_is_char<_Source>> 
301 path(_Source const& __src, const locale& __loc, format = auto_format
302 : _M_pathname(_S_convert_loc(__detail::__effective_range(__src), __loc)) 
303 { _M_split_cmpts(); } 
304 
305 template<typename _InputIterator, 
306 typename _Require = __detail::_Path2<_InputIterator>, 
307 typename _Req2 = __detail::__value_type_is_char<_InputIterator>> 
308 path(_InputIterator __first, _InputIterator __last, const locale& __loc
309 format = auto_format
310 : _M_pathname(_S_convert_loc(__first, __last, __loc)) 
311 { _M_split_cmpts(); } 
312 
313 ~path() = default
314 
315 // assignments 
316 
317 path& operator=(const path&); 
318 path& operator=(path&&) noexcept
319 path& operator=(string_type&& __source); 
320 path& assign(string_type&& __source); 
321 
322 template<typename _Source> 
323 __detail::_Path<_Source>& 
324 operator=(_Source const& __source
325 { return *this = path(__source); } 
326 
327 template<typename _Source> 
328 __detail::_Path<_Source>& 
329 assign(_Source const& __source
330 { return *this = path(__source); } 
331 
332 template<typename _InputIterator> 
333 __detail::_Path2<_InputIterator>& 
334 assign(_InputIterator __first, _InputIterator __last
335 { return *this = path(__first, __last); } 
336 
337 // appends 
338 
339 path& operator/=(const path& __p); 
340 
341 template<typename _Source> 
342 __detail::_Path<_Source>& 
343 operator/=(_Source const& __source
344
345 _M_append(_S_convert(__detail::__effective_range(__source))); 
346 return *this
347
348 
349 template<typename _Source> 
350 __detail::_Path<_Source>& 
351 append(_Source const& __source
352
353 _M_append(_S_convert(__detail::__effective_range(__source))); 
354 return *this
355
356 
357 template<typename _InputIterator> 
358 __detail::_Path2<_InputIterator>& 
359 append(_InputIterator __first, _InputIterator __last
360
361 _M_append(_S_convert(__detail::__string_from_range(__first, __last))); 
362 return *this
363
364 
365 // concatenation 
366 
367 path& operator+=(const path& __x); 
368 path& operator+=(const string_type& __x); 
369 path& operator+=(const value_type* __x); 
370 path& operator+=(value_type __x); 
371 path& operator+=(basic_string_view<value_type> __x); 
372 
373 template<typename _Source> 
374 __detail::_Path<_Source>& 
375 operator+=(_Source const& __x) { return concat(__x); } 
376 
377 template<typename _CharT> 
378 __detail::_Path2<_CharT*>& 
379 operator+=(_CharT __x); 
380 
381 template<typename _Source> 
382 __detail::_Path<_Source>& 
383 concat(_Source const& __x
384
385 _M_concat(_S_convert(__detail::__effective_range(__x))); 
386 return *this
387
388 
389 template<typename _InputIterator> 
390 __detail::_Path2<_InputIterator>& 
391 concat(_InputIterator __first, _InputIterator __last
392
393 _M_concat(_S_convert(__detail::__string_from_range(__first, __last))); 
394 return *this
395
396 
397 // modifiers 
398 
399 void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); } 
400 
401 path& make_preferred(); 
402 path& remove_filename(); 
403 path& replace_filename(const path& __replacement); 
404 path& replace_extension(const path& __replacement = path()); 
405 
406 void swap(path& __rhs) noexcept
407 
408 // native format observers 
409 
410 const string_type& native() const noexcept { return _M_pathname; } 
411 const value_type* c_str() const noexcept { return _M_pathname.c_str(); } 
412 operator string_type() const { return _M_pathname; } 
413 
414 template<typename _CharT, typename _Traits = std::char_traits<_CharT>, 
415 typename _Allocator = std::allocator<_CharT>> 
416 std::basic_string<_CharT, _Traits, _Allocator> 
417 string(const _Allocator& __a = _Allocator()) const
418 
419 std::string string() const
420#if _GLIBCXX_USE_WCHAR_T 
421 std::wstring wstring() const
422#endif 
423#ifdef _GLIBCXX_USE_CHAR8_T 
424 __attribute__((__abi_tag__("__u8"))) 
425 std::u8string u8string() const
426#else 
427 std::string u8string() const
428#endif // _GLIBCXX_USE_CHAR8_T 
429 std::u16string u16string() const
430 std::u32string u32string() const
431 
432 // generic format observers 
433 template<typename _CharT, typename _Traits = std::char_traits<_CharT>, 
434 typename _Allocator = std::allocator<_CharT>> 
435 std::basic_string<_CharT, _Traits, _Allocator> 
436 generic_string(const _Allocator& __a = _Allocator()) const
437 
438 std::string generic_string() const
439#if _GLIBCXX_USE_WCHAR_T 
440 std::wstring generic_wstring() const
441#endif 
442#ifdef _GLIBCXX_USE_CHAR8_T 
443 __attribute__((__abi_tag__("__u8"))) 
444 std::u8string generic_u8string() const
445#else 
446 std::string generic_u8string() const
447#endif // _GLIBCXX_USE_CHAR8_T 
448 std::u16string generic_u16string() const
449 std::u32string generic_u32string() const
450 
451 // compare 
452 
453 int compare(const path& __p) const noexcept
454 int compare(const string_type& __s) const noexcept
455 int compare(const value_type* __s) const noexcept
456 int compare(basic_string_view<value_type> __s) const noexcept
457 
458 // decomposition 
459 
460 path root_name() const
461 path root_directory() const
462 path root_path() const
463 path relative_path() const
464 path parent_path() const
465 path filename() const
466 path stem() const
467 path extension() const
468 
469 // query 
470 
471 [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); } 
472 bool has_root_name() const noexcept
473 bool has_root_directory() const noexcept
474 bool has_root_path() const noexcept
475 bool has_relative_path() const noexcept
476 bool has_parent_path() const noexcept
477 bool has_filename() const noexcept
478 bool has_stem() const noexcept
479 bool has_extension() const noexcept
480 bool is_absolute() const noexcept
481 bool is_relative() const noexcept { return !is_absolute(); } 
482 
483 // generation 
484 path lexically_normal() const
485 path lexically_relative(const path& base) const
486 path lexically_proximate(const path& base) const
487 
488 // iterators 
489 class iterator
490 using const_iterator = iterator
491 
492 iterator begin() const
493 iterator end() const
494 
495 /// Write a path to a stream 
496 template<typename _CharT, typename _Traits> 
497 friend std::basic_ostream<_CharT, _Traits>& 
498 operator<<(std::basic_ostream<_CharT, _Traits>& __os, const path& __p
499
500 __os << std::quoted(__p.string<_CharT, _Traits>()); 
501 return __os
502
503 
504 /// Read a path from a stream 
505 template<typename _CharT, typename _Traits> 
506 friend std::basic_istream<_CharT, _Traits>& 
507 operator>>(std::basic_istream<_CharT, _Traits>& __is, path& __p
508
509 std::basic_string<_CharT, _Traits> __tmp
510 if (__is >> std::quoted(__tmp)) 
511 __p = std::move(__tmp); 
512 return __is
513
514 
515 // non-member operators 
516 
517 /// Compare paths 
518 friend bool operator==(const path& __lhs, const path& __rhs) noexcept 
519 { return path::_S_compare(__lhs, __rhs) == 0; } 
520 
521#if __cpp_lib_three_way_comparison 
522 /// Compare paths 
523 friend strong_ordering 
524 operator<=>(const path& __lhs, const path& __rhs) noexcept 
525 { return path::_S_compare(__lhs, __rhs) <=> 0; } 
526#else 
527 /// Compare paths 
528 friend bool operator!=(const path& __lhs, const path& __rhs) noexcept 
529 { return !(__lhs == __rhs); } 
530 
531 /// Compare paths 
532 friend bool operator<(const path& __lhs, const path& __rhs) noexcept 
533 { return __lhs.compare(__rhs) < 0; } 
534 
535 /// Compare paths 
536 friend bool operator<=(const path& __lhs, const path& __rhs) noexcept 
537 { return !(__rhs < __lhs); } 
538 
539 /// Compare paths 
540 friend bool operator>(const path& __lhs, const path& __rhs) noexcept 
541 { return __rhs < __lhs; } 
542 
543 /// Compare paths 
544 friend bool operator>=(const path& __lhs, const path& __rhs) noexcept 
545 { return !(__lhs < __rhs); } 
546#endif 
547 
548 /// Append one path to another 
549 friend path operator/(const path& __lhs, const path& __rhs
550
551 path __result(__lhs); 
552 __result /= __rhs
553 return __result
554
555 
556 private
557 enum class _Type : unsigned char
558 _Multi = 0, _Root_name, _Root_dir, _Filename 
559 }; 
560 
561 path(basic_string_view<value_type> __str, _Type __type); 
562 
563 enum class _Split { _Stem, _Extension }; 
564 
565 void _M_append(basic_string_view<value_type>); 
566 void _M_concat(basic_string_view<value_type>); 
567 
568 pair<const string_type*, size_t> _M_find_extension() const noexcept
569 
570 // path::_S_convert creates a basic_string<value_type> or 
571 // basic_string_view<value_type> from a range (either the effective 
572 // range of a Source parameter, or a pair of InputIterator parameters), 
573 // performing the conversions required by [fs.path.type.cvt]. 
574 // If the value_type of the range value type is path::value_type, 
575 // no encoding conversion is performed. If the range is contiguous 
576 // a string_view 
577 
578 static string_type 
579 _S_convert(string_type __str
580 { return __str; } 
581 
582 template<typename _Tp> 
583 static auto 
584 _S_convert(const _Tp& __str
585
586 if constexpr (is_same_v<_Tp, string_type>) 
587 return __str
588 else if constexpr (is_same_v<_Tp, basic_string_view<value_type>>) 
589 return __str
590 else if constexpr (is_same_v<typename _Tp::value_type, value_type>) 
591 return basic_string_view<value_type>(__str.data(), __str.size()); 
592 else 
593 return _S_convert(__str.data(), __str.data() + __str.size()); 
594
595 
596 template<typename _EcharT> 
597 static auto 
598 _S_convert(const _EcharT* __first, const _EcharT* __last); 
599 
600 static string_type 
601 _S_convert_loc(const char* __first, const char* __last
602 const std::locale& __loc); 
603 
604 template<typename _Iter> 
605 static string_type 
606 _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc
607
608 const auto __s = __detail::__string_from_range(__first, __last); 
609 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc); 
610
611 
612 template<typename _Tp> 
613 static string_type 
614 _S_convert_loc(const _Tp& __s, const std::locale& __loc
615
616 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc); 
617
618 
619 template<typename _CharT, typename _Traits, typename _Allocator> 
620 static basic_string<_CharT, _Traits, _Allocator> 
621 _S_str_convert(basic_string_view<value_type>, const _Allocator&); 
622 
623 // Returns lhs.compare(rhs), but defined after path::iterator is complete. 
624 __attribute__((__always_inline__)) 
625 static int 
626 _S_compare(const path& __lhs, const path& __rhs) noexcept
627 
628 void _M_split_cmpts(); 
629 
630 _Type _M_type() const noexcept { return _M_cmpts.type(); } 
631 
632 string_type _M_pathname
633 
634 struct _Cmpt
635 
636 struct _List 
637
638 using value_type = _Cmpt
639 using iterator = value_type*; 
640 using const_iterator = const value_type*; 
641 
642 _List(); 
643 _List(const _List&); 
644 _List(_List&&) = default
645 _List& operator=(const _List&); 
646 _List& operator=(_List&&) = default
647 ~_List() = default
648 
649 _Type type() const noexcept 
650 { return _Type(reinterpret_cast<uintptr_t>(_M_impl.get()) & 0x3); } 
651 
652 void type(_Type) noexcept
653 
654 int size() const noexcept; // zero unless type() == _Type::_Multi 
655 bool empty() const noexcept; // true unless type() == _Type::_Multi 
656 void clear(); 
657 void swap(_List& __l) noexcept { _M_impl.swap(u&: __l._M_impl); } 
658 int capacity() const noexcept
659 void reserve(int, bool); ///< @pre type() == _Type::_Multi 
660 
661 // All the member functions below here have a precondition !empty() 
662 // (and they should only be called from within the library). 
663 
664 iterator begin() noexcept
665 iterator end() noexcept
666 const_iterator begin() const noexcept
667 const_iterator end() const noexcept
668 
669 value_type& front() noexcept
670 value_type& back() noexcept
671 const value_type& front() const noexcept
672 const value_type& back() const noexcept
673 
674 void pop_back(); 
675 void _M_erase_from(const_iterator __pos); // erases [__pos,end()) 
676 
677 struct _Impl
678 struct _Impl_deleter 
679
680 void operator()(_Impl*) const noexcept
681 }; 
682 unique_ptr<_Impl, _Impl_deleter> _M_impl
683 }; 
684 _List _M_cmpts
685 
686 struct _Parser
687 }; 
688 
689 /// @{ 
690 /// @relates std::filesystem::path 
691 
692 inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } 
693 
694 size_t hash_value(const path& __p) noexcept
695 
696 /// @} 
697 
698 /// Exception type thrown by the Filesystem library 
699 class filesystem_error : public std::system_error 
700
701 public
702 filesystem_error(const string& __what_arg, error_code __ec); 
703 
704 filesystem_error(const string& __what_arg, const path& __p1
705 error_code __ec); 
706 
707 filesystem_error(const string& __what_arg, const path& __p1
708 const path& __p2, error_code __ec); 
709 
710 filesystem_error(const filesystem_error&) = default
711 filesystem_error& operator=(const filesystem_error&) = default
712 
713 // No move constructor or assignment operator. 
714 // Copy rvalues instead, so that _M_impl is not left empty. 
715 
716 ~filesystem_error(); 
717 
718 const path& path1() const noexcept
719 const path& path2() const noexcept
720 const char* what() const noexcept
721 
722 private
723 struct _Impl
724 std::__shared_ptr<const _Impl> _M_impl
725 }; 
726 
727 /// @cond undocumented 
728namespace __detail 
729
730 [[noreturn]] inline void 
731 __throw_conversion_error() 
732
733 _GLIBCXX_THROW_OR_ABORT(filesystem_error( 
734 "Cannot convert character sequence"
735 std::make_error_code(errc::illegal_byte_sequence))); 
736
737 
738#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
739 template<typename _Tp> 
740 inline std::wstring 
741 __wstr_from_utf8(const _Tp& __str) 
742
743 static_assert(std::is_same_v<typename _Tp::value_type, char>); 
744 std::wstring __wstr; 
745 // XXX This assumes native wide encoding is UTF-16. 
746 std::codecvt_utf8_utf16<wchar_t> __wcvt; 
747 const auto __p = __str.data(); 
748 if (!__str_codecvt_in_all(__p, __p + __str.size(), __wstr, __wcvt)) 
749 __detail::__throw_conversion_error(); 
750 return __wstr; 
751
752#endif 
753 
754} // namespace __detail 
755 /// @endcond 
756 
757 
758 /** Create a path from a UTF-8-encoded sequence of char 
759 * 
760 * @relates std::filesystem::path 
761 */ 
762 template<typename _InputIterator, 
763 typename _Require = __detail::_Path2<_InputIterator>, 
764 typename _CharT 
765 = __detail::__value_type_is_char_or_char8_t<_InputIterator>> 
766 inline path 
767 u8path(_InputIterator __first, _InputIterator __last
768
769#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
770 if constexpr (is_same_v<_CharT, char>) 
771 return path{ __detail::__wstr_from_utf8( 
772 __detail::__string_from_range(__first, __last)) }; 
773 else 
774 return path{ __first, __last }; // constructor handles char8_t 
775#else 
776 // This assumes native normal encoding is UTF-8. 
777 return path{ __first, __last }; 
778#endif 
779
780 
781 /** Create a path from a UTF-8-encoded sequence of char 
782 * 
783 * @relates std::filesystem::path 
784 */ 
785 template<typename _Source, 
786 typename _Require = __detail::_Path<_Source>, 
787 typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>> 
788 inline path 
789 u8path(const _Source& __source
790
791#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
792 if constexpr (is_same_v<_CharT, char>) 
793 return path{ __detail::__wstr_from_utf8( 
794 __detail::__effective_range(__source)) }; 
795 else 
796 return path{ __source }; // constructor handles char8_t 
797#else 
798 // This assumes native normal encoding is UTF-8. 
799 return path{ __source }; 
800#endif 
801
802 
803 /// @cond undocumented 
804 
805 struct path::_Cmpt : path 
806
807 _Cmpt(basic_string_view<value_type> __s, _Type __t, size_t __pos); 
808 
809 _Cmpt() : _M_pos(-1) { } 
810 
811 size_t _M_pos
812 }; 
813 
814 template<typename _EcharT> 
815 auto 
816 path::_S_convert(const _EcharT* __f, const _EcharT* __l
817
818 static_assert(__detail::__is_encoded_char<_EcharT>); 
819 
820 if constexpr (is_same_v<_EcharT, value_type>) 
821 return basic_string_view<value_type>(__f, __l - __f); 
822#if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS && defined _GLIBCXX_USE_CHAR8_T 
823 else if constexpr (is_same_v<_EcharT, char8_t>) 
824 // For POSIX converting from char8_t to char is also 'noconv' 
825 return string_view(reinterpret_cast<const char*>(__f), __l - __f); 
826#endif 
827 else 
828
829#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
830 std::wstring __wstr; 
831 if constexpr (is_same_v<_EcharT, char>) 
832
833 struct _UCvt : std::codecvt<wchar_t, char, std::mbstate_t> 
834 { } __cvt; 
835 if (__str_codecvt_in_all(__f, __l, __wstr, __cvt)) 
836 return __wstr; 
837
838#ifdef _GLIBCXX_USE_CHAR8_T 
839 else if constexpr (is_same_v<_EcharT, char8_t>) 
840
841 const auto __f2 = reinterpret_cast<const char*>(__f); 
842 return __detail::__wstr_from_utf8(string_view(__f2, __l - __f)); 
843
844#endif 
845 else // char16_t or char32_t 
846
847 struct _UCvt : std::codecvt<_EcharT, char, std::mbstate_t> 
848 { } __cvt; 
849 std::string __str; 
850 if (__str_codecvt_out_all(__f, __l, __str, __cvt)) 
851 return __detail::__wstr_from_utf8(__str); 
852
853#else // ! windows 
854 struct _UCvt : std::codecvt<_EcharT, char, std::mbstate_t> 
855 { } __cvt
856 std::string __str
857 if (__str_codecvt_out_all(__f, __l, __str, __cvt)) 
858 return __str
859#endif 
860 __detail::__throw_conversion_error(); 
861
862
863 
864 /// @endcond 
865 
866 /// An iterator for the components of a path 
867 class path::iterator 
868
869 public
870 using difference_type = std::ptrdiff_t
871 using value_type = path
872 using reference = const path&; 
873 using pointer = const path*; 
874 using iterator_category = std::bidirectional_iterator_tag
875 
876 iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { } 
877 
878 iterator(const iterator&) = default
879 iterator& operator=(const iterator&) = default
880 
881 reference operator*() const
882 pointer operator->() const { return std::__addressof(r: **this); } 
883 
884 iterator& operator++(); 
885 iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } 
886 
887 iterator& operator--(); 
888 iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; } 
889 
890 friend bool operator==(const iterator& __lhs, const iterator& __rhs
891 { return __lhs._M_equals(__rhs); } 
892 
893 friend bool operator!=(const iterator& __lhs, const iterator& __rhs
894 { return !__lhs._M_equals(__rhs); } 
895 
896 private
897 friend class path
898 
899 bool _M_is_multi() const { return _M_path->_M_type() == _Type::_Multi; } 
900 
901 friend difference_type 
902 __path_iter_distance(const iterator& __first, const iterator& __last
903
904 __glibcxx_assert(__first._M_path != nullptr); 
905 __glibcxx_assert(__first._M_path == __last._M_path); 
906 if (__first._M_is_multi()) 
907 return std::distance(first: __first._M_cur, last: __last._M_cur); 
908 else if (__first._M_at_end == __last._M_at_end
909 return 0
910 else 
911 return __first._M_at_end ? -1 : 1
912
913 
914 friend void 
915 __path_iter_advance(iterator& __i, difference_type __n
916
917 if (__n == 1
918 ++__i
919 else if (__n == -1
920 --__i
921 else if (__n != 0
922
923 __glibcxx_assert(__i._M_path != nullptr); 
924 __glibcxx_assert(__i._M_is_multi()); 
925 // __glibcxx_assert(__i._M_path->_M_cmpts.end() - __i._M_cur >= __n); 
926 __i._M_cur += __n
927
928
929 
930 iterator(const path* __path, path::_List::const_iterator __iter
931 : _M_path(__path), _M_cur(__iter), _M_at_end() 
932 { } 
933 
934 iterator(const path* __path, bool __at_end
935 : _M_path(__path), _M_cur(), _M_at_end(__at_end
936 { } 
937 
938 bool _M_equals(iterator) const
939 
940 const path* _M_path
941 path::_List::const_iterator _M_cur
942 bool _M_at_end; // only used when type != _Multi 
943 }; 
944 
945 
946 inline path
947 path::operator=(path&& __p) noexcept 
948
949 if (&__p == this) [[__unlikely__]] 
950 return *this
951 
952 _M_pathname = std::move(__p._M_pathname); 
953 _M_cmpts = std::move(__p._M_cmpts); 
954 __p.clear(); 
955 return *this
956
957 
958 inline path
959 path::operator=(string_type&& __source
960 { return *this = path(std::move(__source)); } 
961 
962 inline path
963 path::assign(string_type&& __source
964 { return *this = path(std::move(__source)); } 
965 
966 inline path
967 path::operator+=(const string_type& __x
968
969 _M_concat(__x); 
970 return *this
971
972 
973 inline path
974 path::operator+=(const value_type* __x
975
976 _M_concat(__x); 
977 return *this
978
979 
980 inline path
981 path::operator+=(value_type __x
982
983 _M_concat(basic_string_view<value_type>(&__x, 1)); 
984 return *this
985
986 
987 inline path
988 path::operator+=(basic_string_view<value_type> __x
989
990 _M_concat(__x); 
991 return *this
992
993 
994 template<typename _CharT> 
995 inline __detail::_Path2<_CharT*>& 
996 path::operator+=(const _CharT __x
997
998 _M_concat(_S_convert(&__x, &__x + 1)); 
999 return *this
1000
1001 
1002 inline path
1003 path::make_preferred() 
1004
1005#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1006 std::replace(_M_pathname.begin(), _M_pathname.end(), L'/'
1007 preferred_separator); 
1008#endif 
1009 return *this
1010
1011 
1012 inline void path::swap(path& __rhs) noexcept 
1013
1014 _M_pathname.swap(s&: __rhs._M_pathname); 
1015 _M_cmpts.swap(l&: __rhs._M_cmpts); 
1016
1017 
1018 /// @cond undocumented 
1019 template<typename _CharT, typename _Traits, typename _Allocator> 
1020 std::basic_string<_CharT, _Traits, _Allocator> 
1021 path::_S_str_convert(basic_string_view<value_type> __str
1022 const _Allocator& __a
1023
1024 static_assert(!is_same_v<_CharT, value_type>); 
1025 
1026 using _WString = basic_string<_CharT, _Traits, _Allocator>; 
1027 
1028 if (__str.size() == 0
1029 return _WString(__a); 
1030 
1031#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1032 // First convert native string from UTF-16 to to UTF-8. 
1033 // XXX This assumes that the execution wide-character set is UTF-16. 
1034 std::codecvt_utf8_utf16<value_type> __cvt; 
1035 
1036 using _CharAlloc = __alloc_rebind<_Allocator, char>; 
1037 using _String = basic_string<char, char_traits<char>, _CharAlloc>; 
1038 _String __u8str{_CharAlloc{__a}}; 
1039 const value_type* __wfirst = __str.data(); 
1040 const value_type* __wlast = __wfirst + __str.size(); 
1041 if (__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt)) { 
1042 if constexpr (is_same_v<_CharT, char>) 
1043 return __u8str; // XXX assumes native ordinary encoding is UTF-8. 
1044 else
1045 
1046 const char* __first = __u8str.data(); 
1047 const char* __last = __first + __u8str.size(); 
1048#else 
1049 const value_type* __first = __str.data(); 
1050 const value_type* __last = __first + __str.size(); 
1051#endif 
1052 
1053 // Convert UTF-8 string to requested format. 
1054#ifdef _GLIBCXX_USE_CHAR8_T 
1055 if constexpr (is_same_v<_CharT, char8_t>) 
1056 return _WString(__first, __last, __a); 
1057 else 
1058#endif 
1059
1060 // Convert UTF-8 to wide string. 
1061 _WString __wstr(__a); 
1062 struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> { } __cvt
1063 if (__str_codecvt_in_all(__first, __last, __wstr, __cvt)) 
1064 return __wstr
1065
1066 
1067#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1068 } } 
1069#endif 
1070 __detail::__throw_conversion_error(); 
1071
1072 /// @endcond 
1073 
1074 template<typename _CharT, typename _Traits, typename _Allocator> 
1075 inline basic_string<_CharT, _Traits, _Allocator> 
1076 path::string(const _Allocator& __a) const 
1077
1078 if constexpr (is_same_v<_CharT, value_type>) 
1079 return { _M_pathname.c_str(), _M_pathname.length(), __a }; 
1080 else 
1081 return _S_str_convert<_CharT, _Traits>(_M_pathname, __a); 
1082
1083 
1084 inline std::string 
1085 path::string() const { return string<char>(); } 
1086 
1087#if _GLIBCXX_USE_WCHAR_T 
1088 inline std::wstring 
1089 path::wstring() const { return string<wchar_t>(); } 
1090#endif 
1091 
1092#ifdef _GLIBCXX_USE_CHAR8_T 
1093 inline std::u8string 
1094 path::u8string() const { return string<char8_t>(); } 
1095#else 
1096 inline std::string 
1097 path::u8string() const 
1098
1099#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1100 std::string __str; 
1101 // convert from native wide encoding (assumed to be UTF-16) to UTF-8 
1102 std::codecvt_utf8_utf16<value_type> __cvt; 
1103 const value_type* __first = _M_pathname.data(); 
1104 const value_type* __last = __first + _M_pathname.size(); 
1105 if (__str_codecvt_out_all(__first, __last, __str, __cvt)) 
1106 return __str; 
1107 __detail::__throw_conversion_error(); 
1108#else 
1109 return _M_pathname; 
1110#endif 
1111
1112#endif // _GLIBCXX_USE_CHAR8_T 
1113 
1114 inline std::u16string 
1115 path::u16string() const { return string<char16_t>(); } 
1116 
1117 inline std::u32string 
1118 path::u32string() const { return string<char32_t>(); } 
1119 
1120 template<typename _CharT, typename _Traits, typename _Allocator> 
1121 inline std::basic_string<_CharT, _Traits, _Allocator> 
1122 path::generic_string(const _Allocator& __a) const 
1123
1124#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1125 const value_type __slash = L'/'
1126#else 
1127 const value_type __slash = '/'
1128#endif 
1129 using _Alloc2 = typename allocator_traits<_Allocator>::template 
1130 rebind_alloc<value_type>; 
1131 basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a); 
1132 
1133 if (_M_type() == _Type::_Root_dir
1134 __str.assign(1, __slash); 
1135 else 
1136
1137 __str.reserve(_M_pathname.size()); 
1138 bool __add_slash = false
1139 for (auto& __elem : *this
1140
1141#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1142 if (__elem._M_type() == _Type::_Root_dir) 
1143
1144 __str += __slash; 
1145 continue
1146
1147#endif 
1148 if (__add_slash
1149 __str += __slash
1150 __str += basic_string_view<value_type>(__elem._M_pathname); 
1151 __add_slash = __elem._M_type() == _Type::_Filename
1152
1153
1154 
1155 if constexpr (is_same_v<_CharT, value_type>) 
1156 return __str
1157 else 
1158 return _S_str_convert<_CharT, _Traits>(__str, __a); 
1159
1160 
1161 inline std::string 
1162 path::generic_string() const 
1163 { return generic_string<char>(); } 
1164 
1165#if _GLIBCXX_USE_WCHAR_T 
1166 inline std::wstring 
1167 path::generic_wstring() const 
1168 { return generic_string<wchar_t>(); } 
1169#endif 
1170 
1171#ifdef _GLIBCXX_USE_CHAR8_T 
1172 inline std::u8string 
1173 path::generic_u8string() const 
1174 { return generic_string<char8_t>(); } 
1175#else 
1176 inline std::string 
1177 path::generic_u8string() const 
1178 { return generic_string(); } 
1179#endif 
1180 
1181 inline std::u16string 
1182 path::generic_u16string() const 
1183 { return generic_string<char16_t>(); } 
1184 
1185 inline std::u32string 
1186 path::generic_u32string() const 
1187 { return generic_string<char32_t>(); } 
1188 
1189 inline int 
1190 path::compare(const string_type& __s) const noexcept 
1191 { return compare(s: basic_string_view<value_type>(__s)); } 
1192 
1193 inline int 
1194 path::compare(const value_type* __s) const noexcept 
1195 { return compare(s: basic_string_view<value_type>(__s)); } 
1196 
1197 inline path 
1198 path::filename() const 
1199
1200 if (empty()) 
1201 return {}; 
1202 else if (_M_type() == _Type::_Filename
1203 return *this
1204 else if (_M_type() == _Type::_Multi
1205
1206 if (_M_pathname.back() == preferred_separator
1207 return {}; 
1208 auto __last = --end(); 
1209 if (__last->_M_type() == _Type::_Filename
1210 return *__last
1211
1212 return {}; 
1213
1214 
1215 inline path 
1216 path::stem() const 
1217
1218 auto ext = _M_find_extension(); 
1219 if (ext.first && ext.second != 0
1220 return path{ext.first->substr(pos: 0, n: ext.second)}; 
1221 return {}; 
1222
1223 
1224 inline path 
1225 path::extension() const 
1226
1227 auto ext = _M_find_extension(); 
1228 if (ext.first && ext.second != string_type::npos
1229 return path{ext.first->substr(pos: ext.second)}; 
1230 return {}; 
1231
1232 
1233 inline bool 
1234 path::has_stem() const noexcept 
1235
1236 auto ext = _M_find_extension(); 
1237 return ext.first && ext.second != 0
1238
1239 
1240 inline bool 
1241 path::has_extension() const noexcept 
1242
1243 auto ext = _M_find_extension(); 
1244 return ext.first && ext.second != string_type::npos
1245
1246 
1247 inline bool 
1248 path::is_absolute() const noexcept 
1249
1250#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 
1251 return has_root_name() && has_root_directory(); 
1252#else 
1253 return has_root_directory(); 
1254#endif 
1255
1256 
1257 inline path::iterator 
1258 path::begin() const 
1259
1260 if (_M_type() == _Type::_Multi
1261 return iterator(this, _M_cmpts.begin()); 
1262 return iterator(this, empty()); 
1263
1264 
1265 inline path::iterator 
1266 path::end() const 
1267
1268 if (_M_type() == _Type::_Multi
1269 return iterator(this, _M_cmpts.end()); 
1270 return iterator(this, true); 
1271
1272 
1273 inline path::iterator
1274 path::iterator::operator++() 
1275
1276 __glibcxx_assert(_M_path != nullptr); 
1277 if (_M_path->_M_type() == _Type::_Multi
1278
1279 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 
1280 ++_M_cur
1281
1282 else 
1283
1284 __glibcxx_assert(!_M_at_end); 
1285 _M_at_end = true
1286
1287 return *this
1288
1289 
1290 inline path::iterator
1291 path::iterator::operator--() 
1292
1293 __glibcxx_assert(_M_path != nullptr); 
1294 if (_M_path->_M_type() == _Type::_Multi
1295
1296 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin()); 
1297 --_M_cur
1298
1299 else 
1300
1301 __glibcxx_assert(_M_at_end); 
1302 _M_at_end = false
1303
1304 return *this
1305
1306 
1307 inline path::iterator::reference 
1308 path::iterator::operator*() const 
1309
1310 __glibcxx_assert(_M_path != nullptr); 
1311 if (_M_path->_M_type() == _Type::_Multi
1312
1313 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 
1314 return *_M_cur
1315
1316 return *_M_path
1317
1318 
1319 inline bool 
1320 path::iterator::_M_equals(iterator __rhs) const 
1321
1322 if (_M_path != __rhs._M_path
1323 return false
1324 if (_M_path == nullptr
1325 return true
1326 if (_M_path->_M_type() == path::_Type::_Multi
1327 return _M_cur == __rhs._M_cur
1328 return _M_at_end == __rhs._M_at_end
1329
1330 
1331 // Define this now that path and path::iterator are complete. 
1332 // It needs to consider the string_view(Range&&) constructor during 
1333 // overload resolution, which depends on whether range<path> is satisfied, 
1334 // which depends on whether path::iterator is complete. 
1335 inline int 
1336 path::_S_compare(const path& __lhs, const path& __rhs) noexcept 
1337 { return __lhs.compare(p: __rhs); } 
1338 
1339 /// @} group filesystem 
1340_GLIBCXX_END_NAMESPACE_CXX11 
1341} // namespace filesystem 
1342 
1343/// @cond undocumented 
1344 
1345inline ptrdiff_t 
1346distance(filesystem::path::iterator __first, filesystem::path::iterator __last
1347{ return __path_iter_distance(__first, __last); } 
1348 
1349template<typename _Distance> 
1350 void 
1351 advance(filesystem::path::iterator& __i, _Distance __n
1352 { __path_iter_advance(__i, n: static_cast<ptrdiff_t>(__n)); } 
1353 
1354extern template class __shared_ptr<const filesystem::filesystem_error::_Impl>; 
1355 
1356/// @endcond 
1357 
1358// _GLIBCXX_RESOLVE_LIB_DEFECTS 
1359// 3657. std::hash<std::filesystem::path> is not enabled 
1360template<> 
1361 struct hash<filesystem::path
1362
1363 size_t 
1364 operator()(const filesystem::path& __p) const noexcept 
1365 { return filesystem::hash_value(__p); } 
1366 }; 
1367 
1368_GLIBCXX_END_NAMESPACE_VERSION 
1369} // namespace std 
1370 
1371#endif // C++17 
1372 
1373#endif // _GLIBCXX_FS_PATH_H 
1374