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