xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/fs_path.h (revision 4ac76180e904e771b9d522c7e57296d371f06499)
1cef8759bSmrg // Class filesystem::path -*- C++ -*-
2cef8759bSmrg 
34c3eb207Smrg // Copyright (C) 2014-2020 Free Software Foundation, Inc.
4cef8759bSmrg //
5cef8759bSmrg // This file is part of the GNU ISO C++ Library.  This library is free
6cef8759bSmrg // software; you can redistribute it and/or modify it under the
7cef8759bSmrg // terms of the GNU General Public License as published by the
8cef8759bSmrg // Free Software Foundation; either version 3, or (at your option)
9cef8759bSmrg // any later version.
10cef8759bSmrg 
11cef8759bSmrg // This library is distributed in the hope that it will be useful,
12cef8759bSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
13cef8759bSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14cef8759bSmrg // GNU General Public License for more details.
15cef8759bSmrg 
16cef8759bSmrg // Under Section 7 of GPL version 3, you are granted additional
17cef8759bSmrg // permissions described in the GCC Runtime Library Exception, version
18cef8759bSmrg // 3.1, as published by the Free Software Foundation.
19cef8759bSmrg 
20cef8759bSmrg // You should have received a copy of the GNU General Public License and
21cef8759bSmrg // a copy of the GCC Runtime Library Exception along with this program;
22cef8759bSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23cef8759bSmrg // <http://www.gnu.org/licenses/>.
24cef8759bSmrg 
25cef8759bSmrg /** @file include/bits/fs_path.h
26cef8759bSmrg  *  This is an internal header file, included by other library headers.
27cef8759bSmrg  *  Do not attempt to use it directly. @headername{filesystem}
28cef8759bSmrg  */
29cef8759bSmrg 
30cef8759bSmrg #ifndef _GLIBCXX_FS_PATH_H
31cef8759bSmrg #define _GLIBCXX_FS_PATH_H 1
32cef8759bSmrg 
33cef8759bSmrg #if __cplusplus >= 201703L
34cef8759bSmrg 
35cef8759bSmrg #include <utility>
36cef8759bSmrg #include <type_traits>
37cef8759bSmrg #include <locale>
38cef8759bSmrg #include <iosfwd>
39627f7eb2Smrg #include <iomanip>
40cef8759bSmrg #include <codecvt>
41cef8759bSmrg #include <string_view>
42cef8759bSmrg #include <system_error>
43cef8759bSmrg #include <bits/stl_algobase.h>
44cef8759bSmrg #include <bits/locale_conv.h>
45627f7eb2Smrg #include <ext/concurrence.h>
46627f7eb2Smrg #include <bits/shared_ptr.h>
47627f7eb2Smrg #include <bits/unique_ptr.h>
48cef8759bSmrg 
494c3eb207Smrg #if __cplusplus > 201703L
504c3eb207Smrg # include <compare>
514c3eb207Smrg #endif
524c3eb207Smrg 
53cef8759bSmrg #if defined(_WIN32) && !defined(__CYGWIN__)
54cef8759bSmrg # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1
55cef8759bSmrg # include <algorithm>
56cef8759bSmrg #endif
57cef8759bSmrg 
_GLIBCXX_VISIBILITY(default)58cef8759bSmrg namespace std _GLIBCXX_VISIBILITY(default)
59cef8759bSmrg {
60cef8759bSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
61cef8759bSmrg 
62cef8759bSmrg namespace filesystem
63cef8759bSmrg {
64cef8759bSmrg _GLIBCXX_BEGIN_NAMESPACE_CXX11
65cef8759bSmrg 
664c3eb207Smrg   /** @addtogroup filesystem
67cef8759bSmrg    *  @{
68cef8759bSmrg    */
69cef8759bSmrg 
704c3eb207Smrg   class path;
714c3eb207Smrg 
724c3eb207Smrg   /// @cond undocumented
734c3eb207Smrg namespace __detail
74cef8759bSmrg {
754c3eb207Smrg   template<typename _CharT>
764c3eb207Smrg     using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
774c3eb207Smrg 	  char,
78627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
794c3eb207Smrg 	  char8_t,
80627f7eb2Smrg #endif
814c3eb207Smrg #if _GLIBCXX_USE_WCHAR_T
824c3eb207Smrg 	  wchar_t,
834c3eb207Smrg #endif
844c3eb207Smrg 	  char16_t, char32_t>;
85cef8759bSmrg 
86cef8759bSmrg   template<typename _Iter,
87cef8759bSmrg 	   typename _Iter_traits = std::iterator_traits<_Iter>>
88cef8759bSmrg     using __is_path_iter_src
89cef8759bSmrg       = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
90cef8759bSmrg 	       std::is_base_of<std::input_iterator_tag,
91cef8759bSmrg 			       typename _Iter_traits::iterator_category>>;
92cef8759bSmrg 
93cef8759bSmrg   template<typename _Iter>
94cef8759bSmrg     static __is_path_iter_src<_Iter>
95cef8759bSmrg     __is_path_src(_Iter, int);
96cef8759bSmrg 
97cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
98cef8759bSmrg     static __is_encoded_char<_CharT>
99cef8759bSmrg     __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
100cef8759bSmrg 
101cef8759bSmrg   template<typename _CharT, typename _Traits>
102cef8759bSmrg     static __is_encoded_char<_CharT>
103cef8759bSmrg     __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
104cef8759bSmrg 
105cef8759bSmrg   template<typename _Unknown>
106cef8759bSmrg     static std::false_type
107cef8759bSmrg     __is_path_src(const _Unknown&, ...);
108cef8759bSmrg 
109cef8759bSmrg   template<typename _Tp1, typename _Tp2>
110cef8759bSmrg     struct __constructible_from;
111cef8759bSmrg 
112cef8759bSmrg   template<typename _Iter>
113cef8759bSmrg     struct __constructible_from<_Iter, _Iter>
114cef8759bSmrg     : __is_path_iter_src<_Iter>
115cef8759bSmrg     { };
116cef8759bSmrg 
117cef8759bSmrg   template<typename _Source>
118cef8759bSmrg     struct __constructible_from<_Source, void>
1194c3eb207Smrg     : decltype(__is_path_src(std::declval<const _Source&>(), 0))
120cef8759bSmrg     { };
121cef8759bSmrg 
122cef8759bSmrg   template<typename _Tp1, typename _Tp2 = void>
123cef8759bSmrg     using _Path = typename
124cef8759bSmrg       std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
125cef8759bSmrg 			    __not_<is_void<remove_pointer_t<_Tp1>>>,
126cef8759bSmrg 			    __constructible_from<_Tp1, _Tp2>>::value,
127cef8759bSmrg 		     path>::type;
128cef8759bSmrg 
129cef8759bSmrg   template<typename _Source>
1304c3eb207Smrg     _Source
131cef8759bSmrg     _S_range_begin(_Source __begin) { return __begin; }
132cef8759bSmrg 
133*4ac76180Smrg   struct __nul_terminated { };
134cef8759bSmrg 
135cef8759bSmrg   template<typename _Source>
136*4ac76180Smrg     __nul_terminated
137cef8759bSmrg     _S_range_end(_Source) { return {}; }
138cef8759bSmrg 
139cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
1404c3eb207Smrg     inline const _CharT*
141cef8759bSmrg     _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
142cef8759bSmrg     { return __str.data(); }
143cef8759bSmrg 
144cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
1454c3eb207Smrg     inline const _CharT*
146cef8759bSmrg     _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
147cef8759bSmrg     { return __str.data() + __str.size(); }
148cef8759bSmrg 
149cef8759bSmrg   template<typename _CharT, typename _Traits>
1504c3eb207Smrg     inline const _CharT*
151cef8759bSmrg     _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
152cef8759bSmrg     { return __str.data(); }
153cef8759bSmrg 
154cef8759bSmrg   template<typename _CharT, typename _Traits>
1554c3eb207Smrg     inline const _CharT*
156cef8759bSmrg     _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
157cef8759bSmrg     { return __str.data() + __str.size(); }
158cef8759bSmrg 
159cef8759bSmrg   template<typename _Tp,
160cef8759bSmrg 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
1614c3eb207Smrg 	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
1624c3eb207Smrg 	   typename _UnqualVal = std::remove_const_t<_Val>>
163cef8759bSmrg     using __value_type_is_char
1644c3eb207Smrg       = std::enable_if_t<std::is_same_v<_UnqualVal, char>,
1654c3eb207Smrg 			 _UnqualVal>;
166cef8759bSmrg 
1674c3eb207Smrg   template<typename _Tp,
1684c3eb207Smrg 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
1694c3eb207Smrg 	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
1704c3eb207Smrg 	   typename _UnqualVal = std::remove_const_t<_Val>>
1714c3eb207Smrg     using __value_type_is_char_or_char8_t
1724c3eb207Smrg       = std::enable_if_t<__or_v<
1734c3eb207Smrg 			   std::is_same<_UnqualVal, char>
1744c3eb207Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1754c3eb207Smrg 			   , std::is_same<_UnqualVal, char8_t>
1764c3eb207Smrg #endif
1774c3eb207Smrg 			   >,
1784c3eb207Smrg 			 _UnqualVal>;
1794c3eb207Smrg 
1804c3eb207Smrg } // namespace __detail
1814c3eb207Smrg   /// @endcond
1824c3eb207Smrg 
1834c3eb207Smrg   /// A filesystem path.
1844c3eb207Smrg   class path
1854c3eb207Smrg   {
186cef8759bSmrg   public:
187cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1884c3eb207Smrg     using value_type = wchar_t;
189cef8759bSmrg     static constexpr value_type preferred_separator = L'\\';
190cef8759bSmrg #else
1914c3eb207Smrg # ifdef _GLIBCXX_DOXYGEN
1924c3eb207Smrg     /// Windows uses wchar_t for path::value_type, POSIX uses char.
1934c3eb207Smrg     using value_type = __os_dependent__;
1944c3eb207Smrg # else
1954c3eb207Smrg     using value_type =  char;
1964c3eb207Smrg # endif
197cef8759bSmrg     static constexpr value_type preferred_separator = '/';
198cef8759bSmrg #endif
1994c3eb207Smrg     using string_type = std::basic_string<value_type>;
200cef8759bSmrg 
2014c3eb207Smrg     /// path::format is ignored in this implementation
202627f7eb2Smrg     enum format : unsigned char { native_format, generic_format, auto_format };
203cef8759bSmrg 
204cef8759bSmrg     // constructors and destructor
205cef8759bSmrg 
206cef8759bSmrg     path() noexcept { }
207cef8759bSmrg 
208cef8759bSmrg     path(const path& __p) = default;
209cef8759bSmrg 
210627f7eb2Smrg     path(path&& __p)
211627f7eb2Smrg #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_FULLY_DYNAMIC_STRING == 0
212627f7eb2Smrg       noexcept
213627f7eb2Smrg #endif
214627f7eb2Smrg     : _M_pathname(std::move(__p._M_pathname)),
215627f7eb2Smrg       _M_cmpts(std::move(__p._M_cmpts))
216627f7eb2Smrg     { __p.clear(); }
217cef8759bSmrg 
218cef8759bSmrg     path(string_type&& __source, format = auto_format)
219cef8759bSmrg     : _M_pathname(std::move(__source))
220cef8759bSmrg     { _M_split_cmpts(); }
221cef8759bSmrg 
222cef8759bSmrg     template<typename _Source,
2234c3eb207Smrg 	     typename _Require = __detail::_Path<_Source>>
224cef8759bSmrg       path(_Source const& __source, format = auto_format)
2254c3eb207Smrg       : _M_pathname(_S_convert(__detail::_S_range_begin(__source),
2264c3eb207Smrg 			       __detail::_S_range_end(__source)))
227cef8759bSmrg       { _M_split_cmpts(); }
228cef8759bSmrg 
229cef8759bSmrg     template<typename _InputIterator,
2304c3eb207Smrg 	     typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
231cef8759bSmrg       path(_InputIterator __first, _InputIterator __last, format = auto_format)
232cef8759bSmrg       : _M_pathname(_S_convert(__first, __last))
233cef8759bSmrg       { _M_split_cmpts(); }
234cef8759bSmrg 
235cef8759bSmrg     template<typename _Source,
2364c3eb207Smrg 	     typename _Require = __detail::_Path<_Source>,
2374c3eb207Smrg 	     typename _Require2 = __detail::__value_type_is_char<_Source>>
238cef8759bSmrg       path(_Source const& __source, const locale& __loc, format = auto_format)
2394c3eb207Smrg       : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
2404c3eb207Smrg 				   __detail::_S_range_end(__source), __loc))
241cef8759bSmrg       { _M_split_cmpts(); }
242cef8759bSmrg 
243cef8759bSmrg     template<typename _InputIterator,
2444c3eb207Smrg 	     typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
2454c3eb207Smrg 	     typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
246cef8759bSmrg       path(_InputIterator __first, _InputIterator __last, const locale& __loc,
247cef8759bSmrg 	   format = auto_format)
248cef8759bSmrg       : _M_pathname(_S_convert_loc(__first, __last, __loc))
249cef8759bSmrg       { _M_split_cmpts(); }
250cef8759bSmrg 
251cef8759bSmrg     ~path() = default;
252cef8759bSmrg 
253cef8759bSmrg     // assignments
254cef8759bSmrg 
255627f7eb2Smrg     path& operator=(const path&);
256627f7eb2Smrg     path& operator=(path&&) noexcept;
257cef8759bSmrg     path& operator=(string_type&& __source);
258cef8759bSmrg     path& assign(string_type&& __source);
259cef8759bSmrg 
260cef8759bSmrg     template<typename _Source>
2614c3eb207Smrg       __detail::_Path<_Source>&
262cef8759bSmrg       operator=(_Source const& __source)
263cef8759bSmrg       { return *this = path(__source); }
264cef8759bSmrg 
265cef8759bSmrg     template<typename _Source>
2664c3eb207Smrg       __detail::_Path<_Source>&
267cef8759bSmrg       assign(_Source const& __source)
268cef8759bSmrg       { return *this = path(__source); }
269cef8759bSmrg 
270cef8759bSmrg     template<typename _InputIterator>
2714c3eb207Smrg       __detail::_Path<_InputIterator, _InputIterator>&
272cef8759bSmrg       assign(_InputIterator __first, _InputIterator __last)
273cef8759bSmrg       { return *this = path(__first, __last); }
274cef8759bSmrg 
275cef8759bSmrg     // appends
276cef8759bSmrg 
277627f7eb2Smrg     path& operator/=(const path& __p);
278cef8759bSmrg 
2794c3eb207Smrg     template<typename _Source>
2804c3eb207Smrg       __detail::_Path<_Source>&
281cef8759bSmrg       operator/=(_Source const& __source)
282627f7eb2Smrg       {
2834c3eb207Smrg 	_M_append(_S_convert(__detail::_S_range_begin(__source),
2844c3eb207Smrg 			     __detail::_S_range_end(__source)));
285627f7eb2Smrg 	return *this;
286627f7eb2Smrg       }
287cef8759bSmrg 
288cef8759bSmrg     template<typename _Source>
2894c3eb207Smrg       __detail::_Path<_Source>&
290cef8759bSmrg       append(_Source const& __source)
291627f7eb2Smrg       {
2924c3eb207Smrg 	_M_append(_S_convert(__detail::_S_range_begin(__source),
2934c3eb207Smrg 			     __detail::_S_range_end(__source)));
294627f7eb2Smrg 	return *this;
295627f7eb2Smrg       }
296cef8759bSmrg 
297cef8759bSmrg     template<typename _InputIterator>
2984c3eb207Smrg       __detail::_Path<_InputIterator, _InputIterator>&
299cef8759bSmrg       append(_InputIterator __first, _InputIterator __last)
300627f7eb2Smrg       {
301627f7eb2Smrg 	_M_append(_S_convert(__first, __last));
302627f7eb2Smrg 	return *this;
303627f7eb2Smrg       }
304cef8759bSmrg 
305cef8759bSmrg     // concatenation
306cef8759bSmrg 
307cef8759bSmrg     path& operator+=(const path& __x);
308cef8759bSmrg     path& operator+=(const string_type& __x);
309cef8759bSmrg     path& operator+=(const value_type* __x);
310cef8759bSmrg     path& operator+=(value_type __x);
311cef8759bSmrg     path& operator+=(basic_string_view<value_type> __x);
312cef8759bSmrg 
313cef8759bSmrg     template<typename _Source>
3144c3eb207Smrg       __detail::_Path<_Source>&
315cef8759bSmrg       operator+=(_Source const& __x) { return concat(__x); }
316cef8759bSmrg 
317cef8759bSmrg     template<typename _CharT>
3184c3eb207Smrg       __detail::_Path<_CharT*, _CharT*>&
319cef8759bSmrg       operator+=(_CharT __x);
320cef8759bSmrg 
321cef8759bSmrg     template<typename _Source>
3224c3eb207Smrg       __detail::_Path<_Source>&
323cef8759bSmrg       concat(_Source const& __x)
324627f7eb2Smrg       {
3254c3eb207Smrg 	_M_concat(_S_convert(__detail::_S_range_begin(__x),
3264c3eb207Smrg 			     __detail::_S_range_end(__x)));
327627f7eb2Smrg 	return *this;
328627f7eb2Smrg       }
329cef8759bSmrg 
330cef8759bSmrg     template<typename _InputIterator>
3314c3eb207Smrg       __detail::_Path<_InputIterator, _InputIterator>&
332cef8759bSmrg       concat(_InputIterator __first, _InputIterator __last)
333627f7eb2Smrg       {
334627f7eb2Smrg 	_M_concat(_S_convert(__first, __last));
335627f7eb2Smrg 	return *this;
336627f7eb2Smrg       }
337cef8759bSmrg 
338cef8759bSmrg     // modifiers
339cef8759bSmrg 
340cef8759bSmrg     void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
341cef8759bSmrg 
342cef8759bSmrg     path& make_preferred();
343cef8759bSmrg     path& remove_filename();
344cef8759bSmrg     path& replace_filename(const path& __replacement);
345cef8759bSmrg     path& replace_extension(const path& __replacement = path());
346cef8759bSmrg 
347cef8759bSmrg     void swap(path& __rhs) noexcept;
348cef8759bSmrg 
349cef8759bSmrg     // native format observers
350cef8759bSmrg 
351cef8759bSmrg     const string_type&  native() const noexcept { return _M_pathname; }
352cef8759bSmrg     const value_type*   c_str() const noexcept { return _M_pathname.c_str(); }
353cef8759bSmrg     operator string_type() const { return _M_pathname; }
354cef8759bSmrg 
355cef8759bSmrg     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
356cef8759bSmrg 	     typename _Allocator = std::allocator<_CharT>>
357cef8759bSmrg       std::basic_string<_CharT, _Traits, _Allocator>
358cef8759bSmrg       string(const _Allocator& __a = _Allocator()) const;
359cef8759bSmrg 
360cef8759bSmrg     std::string    string() const;
361cef8759bSmrg #if _GLIBCXX_USE_WCHAR_T
362cef8759bSmrg     std::wstring   wstring() const;
363cef8759bSmrg #endif
364627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
365627f7eb2Smrg     __attribute__((__abi_tag__("__u8")))
366627f7eb2Smrg     std::u8string  u8string() const;
367627f7eb2Smrg #else
368cef8759bSmrg     std::string    u8string() const;
369627f7eb2Smrg #endif // _GLIBCXX_USE_CHAR8_T
370cef8759bSmrg     std::u16string u16string() const;
371cef8759bSmrg     std::u32string u32string() const;
372cef8759bSmrg 
373cef8759bSmrg     // generic format observers
374cef8759bSmrg     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
375cef8759bSmrg 	     typename _Allocator = std::allocator<_CharT>>
376cef8759bSmrg       std::basic_string<_CharT, _Traits, _Allocator>
377cef8759bSmrg       generic_string(const _Allocator& __a = _Allocator()) const;
378cef8759bSmrg 
379cef8759bSmrg     std::string    generic_string() const;
380cef8759bSmrg #if _GLIBCXX_USE_WCHAR_T
381cef8759bSmrg     std::wstring   generic_wstring() const;
382cef8759bSmrg #endif
383627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
384627f7eb2Smrg     __attribute__((__abi_tag__("__u8")))
385627f7eb2Smrg     std::u8string  generic_u8string() const;
386627f7eb2Smrg #else
387cef8759bSmrg     std::string    generic_u8string() const;
388627f7eb2Smrg #endif // _GLIBCXX_USE_CHAR8_T
389cef8759bSmrg     std::u16string generic_u16string() const;
390cef8759bSmrg     std::u32string generic_u32string() const;
391cef8759bSmrg 
392cef8759bSmrg     // compare
393cef8759bSmrg 
394cef8759bSmrg     int compare(const path& __p) const noexcept;
395627f7eb2Smrg     int compare(const string_type& __s) const noexcept;
396627f7eb2Smrg     int compare(const value_type* __s) const noexcept;
397627f7eb2Smrg     int compare(basic_string_view<value_type> __s) const noexcept;
398cef8759bSmrg 
399cef8759bSmrg     // decomposition
400cef8759bSmrg 
401cef8759bSmrg     path root_name() const;
402cef8759bSmrg     path root_directory() const;
403cef8759bSmrg     path root_path() const;
404cef8759bSmrg     path relative_path() const;
405cef8759bSmrg     path parent_path() const;
406cef8759bSmrg     path filename() const;
407cef8759bSmrg     path stem() const;
408cef8759bSmrg     path extension() const;
409cef8759bSmrg 
410cef8759bSmrg     // query
411cef8759bSmrg 
412cef8759bSmrg     [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); }
413627f7eb2Smrg     bool has_root_name() const noexcept;
414627f7eb2Smrg     bool has_root_directory() const noexcept;
415627f7eb2Smrg     bool has_root_path() const noexcept;
416627f7eb2Smrg     bool has_relative_path() const noexcept;
417627f7eb2Smrg     bool has_parent_path() const noexcept;
418627f7eb2Smrg     bool has_filename() const noexcept;
419627f7eb2Smrg     bool has_stem() const noexcept;
420627f7eb2Smrg     bool has_extension() const noexcept;
421627f7eb2Smrg     bool is_absolute() const noexcept;
422627f7eb2Smrg     bool is_relative() const noexcept { return !is_absolute(); }
423cef8759bSmrg 
424cef8759bSmrg     // generation
425cef8759bSmrg     path lexically_normal() const;
426cef8759bSmrg     path lexically_relative(const path& base) const;
427cef8759bSmrg     path lexically_proximate(const path& base) const;
428cef8759bSmrg 
429cef8759bSmrg     // iterators
430cef8759bSmrg     class iterator;
4314c3eb207Smrg     using const_iterator = iterator;
432cef8759bSmrg 
433cef8759bSmrg     iterator begin() const;
434cef8759bSmrg     iterator end() const;
435cef8759bSmrg 
436627f7eb2Smrg     /// Write a path to a stream
437627f7eb2Smrg     template<typename _CharT, typename _Traits>
438627f7eb2Smrg       friend std::basic_ostream<_CharT, _Traits>&
439627f7eb2Smrg       operator<<(std::basic_ostream<_CharT, _Traits>& __os, const path& __p)
440627f7eb2Smrg       {
441627f7eb2Smrg 	__os << std::quoted(__p.string<_CharT, _Traits>());
442627f7eb2Smrg 	return __os;
443627f7eb2Smrg       }
444627f7eb2Smrg 
445627f7eb2Smrg     /// Read a path from a stream
446627f7eb2Smrg     template<typename _CharT, typename _Traits>
447627f7eb2Smrg       friend std::basic_istream<_CharT, _Traits>&
448627f7eb2Smrg       operator>>(std::basic_istream<_CharT, _Traits>& __is, path& __p)
449627f7eb2Smrg       {
450627f7eb2Smrg 	std::basic_string<_CharT, _Traits> __tmp;
451627f7eb2Smrg 	if (__is >> std::quoted(__tmp))
452627f7eb2Smrg 	  __p = std::move(__tmp);
453627f7eb2Smrg 	return __is;
454627f7eb2Smrg       }
455627f7eb2Smrg 
456627f7eb2Smrg     // non-member operators
457627f7eb2Smrg 
458627f7eb2Smrg     /// Compare paths
4594c3eb207Smrg     friend bool operator==(const path& __lhs, const path& __rhs) noexcept
4604c3eb207Smrg     { return __lhs.compare(__rhs) == 0; }
4614c3eb207Smrg 
4624c3eb207Smrg #if __cpp_lib_three_way_comparison
4634c3eb207Smrg     /// Compare paths
4644c3eb207Smrg     friend strong_ordering
4654c3eb207Smrg     operator<=>(const path& __lhs, const path& __rhs) noexcept
4664c3eb207Smrg     { return __lhs.compare(__rhs) <=> 0; }
4674c3eb207Smrg #else
4684c3eb207Smrg     /// Compare paths
4694c3eb207Smrg     friend bool operator!=(const path& __lhs, const path& __rhs) noexcept
4704c3eb207Smrg     { return !(__lhs == __rhs); }
4714c3eb207Smrg 
4724c3eb207Smrg     /// Compare paths
473627f7eb2Smrg     friend bool operator<(const path& __lhs, const path& __rhs) noexcept
474627f7eb2Smrg     { return __lhs.compare(__rhs) < 0; }
475627f7eb2Smrg 
476627f7eb2Smrg     /// Compare paths
477627f7eb2Smrg     friend bool operator<=(const path& __lhs, const path& __rhs) noexcept
478627f7eb2Smrg     { return !(__rhs < __lhs); }
479627f7eb2Smrg 
480627f7eb2Smrg     /// Compare paths
481627f7eb2Smrg     friend bool operator>(const path& __lhs, const path& __rhs) noexcept
482627f7eb2Smrg     { return __rhs < __lhs; }
483627f7eb2Smrg 
484627f7eb2Smrg     /// Compare paths
485627f7eb2Smrg     friend bool operator>=(const path& __lhs, const path& __rhs) noexcept
486627f7eb2Smrg     { return !(__lhs < __rhs); }
4874c3eb207Smrg #endif
488627f7eb2Smrg 
489627f7eb2Smrg     /// Append one path to another
490627f7eb2Smrg     friend path operator/(const path& __lhs, const path& __rhs)
491627f7eb2Smrg     {
492627f7eb2Smrg       path __result(__lhs);
493627f7eb2Smrg       __result /= __rhs;
494627f7eb2Smrg       return __result;
495627f7eb2Smrg     }
496627f7eb2Smrg 
4974c3eb207Smrg     /// @cond undocumented
498627f7eb2Smrg     // Create a basic_string by reading until a null character.
499627f7eb2Smrg     template<typename _InputIterator,
500627f7eb2Smrg 	     typename _Traits = std::iterator_traits<_InputIterator>,
501627f7eb2Smrg 	     typename _CharT
502627f7eb2Smrg 	       = typename std::remove_cv_t<typename _Traits::value_type>>
503627f7eb2Smrg       static std::basic_string<_CharT>
504627f7eb2Smrg       _S_string_from_iter(_InputIterator __source)
505627f7eb2Smrg       {
506627f7eb2Smrg 	std::basic_string<_CharT> __str;
507627f7eb2Smrg 	for (_CharT __ch = *__source; __ch != _CharT(); __ch = *++__source)
508627f7eb2Smrg 	  __str.push_back(__ch);
509627f7eb2Smrg 	return __str;
510627f7eb2Smrg       }
5114c3eb207Smrg     /// @endcond
512627f7eb2Smrg 
513cef8759bSmrg   private:
514cef8759bSmrg     enum class _Type : unsigned char {
515627f7eb2Smrg       _Multi = 0, _Root_name, _Root_dir, _Filename
516cef8759bSmrg     };
517cef8759bSmrg 
518*4ac76180Smrg     path(basic_string_view<value_type> __str, _Type __type);
519cef8759bSmrg 
520cef8759bSmrg     enum class _Split { _Stem, _Extension };
521cef8759bSmrg 
522627f7eb2Smrg     void _M_append(basic_string_view<value_type>);
523627f7eb2Smrg     void _M_concat(basic_string_view<value_type>);
524cef8759bSmrg 
525627f7eb2Smrg     pair<const string_type*, size_t> _M_find_extension() const noexcept;
526cef8759bSmrg 
527cef8759bSmrg     template<typename _CharT>
528cef8759bSmrg       struct _Cvt;
529cef8759bSmrg 
530627f7eb2Smrg     static basic_string_view<value_type>
531*4ac76180Smrg     _S_convert(value_type* __src, __detail::__nul_terminated)
532627f7eb2Smrg     { return __src; }
533cef8759bSmrg 
534627f7eb2Smrg     static basic_string_view<value_type>
535*4ac76180Smrg     _S_convert(const value_type* __src, __detail::__nul_terminated)
536627f7eb2Smrg     { return __src; }
537627f7eb2Smrg 
538627f7eb2Smrg     static basic_string_view<value_type>
539627f7eb2Smrg     _S_convert(value_type* __first, value_type* __last)
540627f7eb2Smrg     { return {__first, __last - __first}; }
541627f7eb2Smrg 
542627f7eb2Smrg     static basic_string_view<value_type>
543627f7eb2Smrg     _S_convert(const value_type* __first, const value_type* __last)
544627f7eb2Smrg     { return {__first, __last - __first}; }
545cef8759bSmrg 
546cef8759bSmrg     template<typename _Iter>
547cef8759bSmrg       static string_type
548cef8759bSmrg       _S_convert(_Iter __first, _Iter __last)
549cef8759bSmrg       {
550cef8759bSmrg 	using __value_type = typename std::iterator_traits<_Iter>::value_type;
551cef8759bSmrg 	return _Cvt<typename remove_cv<__value_type>::type>::
552cef8759bSmrg 	  _S_convert(__first, __last);
553cef8759bSmrg       }
554cef8759bSmrg 
555cef8759bSmrg     template<typename _InputIterator>
556cef8759bSmrg       static string_type
557*4ac76180Smrg       _S_convert(_InputIterator __src, __detail::__nul_terminated)
558cef8759bSmrg       {
559627f7eb2Smrg 	// Read from iterator into basic_string until a null value is seen:
560627f7eb2Smrg 	auto __s = _S_string_from_iter(__src);
561627f7eb2Smrg 	// Convert (if needed) from iterator's value type to path::value_type:
562627f7eb2Smrg 	return string_type(_S_convert(__s.data(), __s.data() + __s.size()));
563cef8759bSmrg       }
564cef8759bSmrg 
565cef8759bSmrg     static string_type
566cef8759bSmrg     _S_convert_loc(const char* __first, const char* __last,
567cef8759bSmrg 		   const std::locale& __loc);
568cef8759bSmrg 
569cef8759bSmrg     template<typename _Iter>
570cef8759bSmrg       static string_type
571cef8759bSmrg       _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc)
572cef8759bSmrg       {
573cef8759bSmrg 	const std::string __str(__first, __last);
574cef8759bSmrg 	return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc);
575cef8759bSmrg       }
576cef8759bSmrg 
577cef8759bSmrg     template<typename _InputIterator>
578cef8759bSmrg       static string_type
579*4ac76180Smrg       _S_convert_loc(_InputIterator __src, __detail::__nul_terminated,
580cef8759bSmrg 		     const std::locale& __loc)
581cef8759bSmrg       {
582627f7eb2Smrg 	const std::string __s = _S_string_from_iter(__src);
583627f7eb2Smrg 	return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);
584cef8759bSmrg       }
585cef8759bSmrg 
586cef8759bSmrg     template<typename _CharT, typename _Traits, typename _Allocator>
587cef8759bSmrg       static basic_string<_CharT, _Traits, _Allocator>
5884c3eb207Smrg       _S_str_convert(basic_string_view<value_type>, const _Allocator&);
589cef8759bSmrg 
590cef8759bSmrg     void _M_split_cmpts();
591627f7eb2Smrg 
592627f7eb2Smrg     _Type _M_type() const noexcept { return _M_cmpts.type(); }
593cef8759bSmrg 
594cef8759bSmrg     string_type _M_pathname;
595cef8759bSmrg 
596cef8759bSmrg     struct _Cmpt;
597627f7eb2Smrg 
598627f7eb2Smrg     struct _List
599627f7eb2Smrg     {
600627f7eb2Smrg       using value_type = _Cmpt;
601627f7eb2Smrg       using iterator = value_type*;
602627f7eb2Smrg       using const_iterator = const value_type*;
603627f7eb2Smrg 
604627f7eb2Smrg       _List();
605627f7eb2Smrg       _List(const _List&);
606627f7eb2Smrg       _List(_List&&) = default;
607627f7eb2Smrg       _List& operator=(const _List&);
608627f7eb2Smrg       _List& operator=(_List&&) = default;
609627f7eb2Smrg       ~_List() = default;
610627f7eb2Smrg 
611627f7eb2Smrg       _Type type() const noexcept
6124c3eb207Smrg       { return _Type(reinterpret_cast<uintptr_t>(_M_impl.get()) & 0x3); }
613627f7eb2Smrg 
614627f7eb2Smrg       void type(_Type) noexcept;
615627f7eb2Smrg 
616627f7eb2Smrg       int size() const noexcept; // zero unless type() == _Type::_Multi
617627f7eb2Smrg       bool empty() const noexcept; // true unless type() == _Type::_Multi
618627f7eb2Smrg       void clear();
619627f7eb2Smrg       void swap(_List& __l) noexcept { _M_impl.swap(__l._M_impl); }
620627f7eb2Smrg       int capacity() const noexcept;
621627f7eb2Smrg       void reserve(int, bool); ///< @pre type() == _Type::_Multi
622627f7eb2Smrg 
623627f7eb2Smrg       // All the member functions below here have a precondition !empty()
624627f7eb2Smrg       // (and they should only be called from within the library).
625627f7eb2Smrg 
6264c3eb207Smrg       iterator begin() noexcept;
6274c3eb207Smrg       iterator end() noexcept;
6284c3eb207Smrg       const_iterator begin() const noexcept;
6294c3eb207Smrg       const_iterator end() const noexcept;
630627f7eb2Smrg 
631627f7eb2Smrg       value_type& front() noexcept;
632627f7eb2Smrg       value_type& back() noexcept;
633627f7eb2Smrg       const value_type& front() const noexcept;
634627f7eb2Smrg       const value_type& back() const noexcept;
635627f7eb2Smrg 
636627f7eb2Smrg       void pop_back();
637627f7eb2Smrg       void _M_erase_from(const_iterator __pos); // erases [__pos,end())
638627f7eb2Smrg 
639627f7eb2Smrg       struct _Impl;
640627f7eb2Smrg       struct _Impl_deleter
641627f7eb2Smrg       {
642627f7eb2Smrg 	void operator()(_Impl*) const noexcept;
643cef8759bSmrg       };
644627f7eb2Smrg       unique_ptr<_Impl, _Impl_deleter> _M_impl;
645627f7eb2Smrg     };
646627f7eb2Smrg     _List _M_cmpts;
647cef8759bSmrg 
648627f7eb2Smrg     struct _Parser;
649627f7eb2Smrg   };
650cef8759bSmrg 
6514c3eb207Smrg   /// @relates std::filesystem::path @{
6524c3eb207Smrg 
653cef8759bSmrg   inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
654cef8759bSmrg 
655cef8759bSmrg   size_t hash_value(const path& __p) noexcept;
656cef8759bSmrg 
6574c3eb207Smrg   /// @}
6584c3eb207Smrg 
659627f7eb2Smrg   /// Exception type thrown by the Filesystem library
660627f7eb2Smrg   class filesystem_error : public std::system_error
661cef8759bSmrg   {
662627f7eb2Smrg   public:
663627f7eb2Smrg     filesystem_error(const string& __what_arg, error_code __ec);
664cef8759bSmrg 
665627f7eb2Smrg     filesystem_error(const string& __what_arg, const path& __p1,
666627f7eb2Smrg 		     error_code __ec);
667cef8759bSmrg 
668627f7eb2Smrg     filesystem_error(const string& __what_arg, const path& __p1,
669627f7eb2Smrg 		     const path& __p2, error_code __ec);
670cef8759bSmrg 
671627f7eb2Smrg     filesystem_error(const filesystem_error&) = default;
672627f7eb2Smrg     filesystem_error& operator=(const filesystem_error&) = default;
673cef8759bSmrg 
674627f7eb2Smrg     // No move constructor or assignment operator.
675627f7eb2Smrg     // Copy rvalues instead, so that _M_impl is not left empty.
676627f7eb2Smrg 
677627f7eb2Smrg     ~filesystem_error();
678627f7eb2Smrg 
679627f7eb2Smrg     const path& path1() const noexcept;
680627f7eb2Smrg     const path& path2() const noexcept;
681627f7eb2Smrg     const char* what() const noexcept;
682627f7eb2Smrg 
683627f7eb2Smrg   private:
684627f7eb2Smrg     struct _Impl;
685627f7eb2Smrg     std::__shared_ptr<const _Impl> _M_impl;
686627f7eb2Smrg   };
687627f7eb2Smrg 
6884c3eb207Smrg   /** Create a path from a UTF-8-encoded sequence of char
6894c3eb207Smrg    *
6904c3eb207Smrg    * @relates std::filesystem::path
6914c3eb207Smrg    */
6924c3eb207Smrg   template<typename _InputIterator,
6934c3eb207Smrg 	   typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
6944c3eb207Smrg 	   typename _CharT
6954c3eb207Smrg 	     = __detail::__value_type_is_char_or_char8_t<_InputIterator>>
6964c3eb207Smrg     inline path
697cef8759bSmrg     u8path(_InputIterator __first, _InputIterator __last)
698cef8759bSmrg     {
699cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
7004c3eb207Smrg       if constexpr (is_same_v<_CharT, char>)
7014c3eb207Smrg 	{
702627f7eb2Smrg 	  // XXX This assumes native wide encoding is UTF-16.
703627f7eb2Smrg 	  std::codecvt_utf8_utf16<path::value_type> __cvt;
704627f7eb2Smrg 	  path::string_type __tmp;
705627f7eb2Smrg 	  if constexpr (is_pointer_v<_InputIterator>)
706627f7eb2Smrg 	    {
707627f7eb2Smrg 	      if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
708cef8759bSmrg 		return path{ __tmp };
709627f7eb2Smrg 	    }
710cef8759bSmrg 	  else
711627f7eb2Smrg 	    {
712627f7eb2Smrg 	      const std::string __u8str{__first, __last};
7134c3eb207Smrg 	      const char* const __p = __u8str.data();
7144c3eb207Smrg 	      if (__str_codecvt_in_all(__p, __p + __u8str.size(), __tmp, __cvt))
715627f7eb2Smrg 		return path{ __tmp };
716627f7eb2Smrg 	    }
717627f7eb2Smrg 	  _GLIBCXX_THROW_OR_ABORT(filesystem_error(
718627f7eb2Smrg 	      "Cannot convert character sequence",
719627f7eb2Smrg 	      std::make_error_code(errc::illegal_byte_sequence)));
7204c3eb207Smrg 	}
7214c3eb207Smrg       else
7224c3eb207Smrg 	return path{ __first, __last };
723cef8759bSmrg #else
724627f7eb2Smrg       // This assumes native normal encoding is UTF-8.
725cef8759bSmrg       return path{ __first, __last };
726cef8759bSmrg #endif
727cef8759bSmrg     }
728cef8759bSmrg 
7294c3eb207Smrg   /** Create a path from a UTF-8-encoded sequence of char
7304c3eb207Smrg    *
7314c3eb207Smrg    * @relates std::filesystem::path
7324c3eb207Smrg    */
7334c3eb207Smrg   template<typename _Source,
7344c3eb207Smrg 	   typename _Require = __detail::_Path<_Source>,
7354c3eb207Smrg 	   typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
7364c3eb207Smrg     inline path
737627f7eb2Smrg     u8path(const _Source& __source)
738cef8759bSmrg     {
739627f7eb2Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
7404c3eb207Smrg       if constexpr (is_same_v<_CharT, char>)
7414c3eb207Smrg 	{
742627f7eb2Smrg 	  if constexpr (is_convertible_v<const _Source&, std::string_view>)
743627f7eb2Smrg 	    {
744627f7eb2Smrg 	      const std::string_view __s = __source;
745627f7eb2Smrg 	      return filesystem::u8path(__s.data(), __s.data() + __s.size());
746627f7eb2Smrg 	    }
747627f7eb2Smrg 	  else
748627f7eb2Smrg 	    {
749627f7eb2Smrg 	      std::string __s = path::_S_string_from_iter(__source);
750627f7eb2Smrg 	      return filesystem::u8path(__s.data(), __s.data() + __s.size());
751627f7eb2Smrg 	    }
7524c3eb207Smrg 	}
7534c3eb207Smrg       else
7544c3eb207Smrg 	return path{ __source };
755627f7eb2Smrg #else
756627f7eb2Smrg       return path{ __source };
757627f7eb2Smrg #endif
758627f7eb2Smrg     }
759cef8759bSmrg 
7604c3eb207Smrg   /// @cond undocumented
7614c3eb207Smrg 
762cef8759bSmrg   struct path::_Cmpt : path
763cef8759bSmrg   {
764*4ac76180Smrg     _Cmpt(basic_string_view<value_type> __s, _Type __t, size_t __pos);
765cef8759bSmrg 
766cef8759bSmrg     _Cmpt() : _M_pos(-1) { }
767cef8759bSmrg 
768cef8759bSmrg     size_t _M_pos;
769cef8759bSmrg   };
770cef8759bSmrg 
771cef8759bSmrg   // specialize _Cvt for degenerate 'noconv' case
772cef8759bSmrg   template<>
773cef8759bSmrg     struct path::_Cvt<path::value_type>
774cef8759bSmrg     {
775cef8759bSmrg       template<typename _Iter>
776cef8759bSmrg 	static string_type
777cef8759bSmrg 	_S_convert(_Iter __first, _Iter __last)
778cef8759bSmrg 	{ return string_type{__first, __last}; }
779cef8759bSmrg     };
780cef8759bSmrg 
781627f7eb2Smrg #if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS  && defined _GLIBCXX_USE_CHAR8_T
782627f7eb2Smrg   // For POSIX converting from char8_t to char is also 'noconv'
783627f7eb2Smrg   template<>
784627f7eb2Smrg     struct path::_Cvt<char8_t>
785627f7eb2Smrg     {
786627f7eb2Smrg       template<typename _Iter>
787627f7eb2Smrg 	static string_type
788627f7eb2Smrg 	_S_convert(_Iter __first, _Iter __last)
789627f7eb2Smrg 	{ return string_type(__first, __last); }
790627f7eb2Smrg     };
791627f7eb2Smrg #endif
792627f7eb2Smrg 
793cef8759bSmrg   template<typename _CharT>
794cef8759bSmrg     struct path::_Cvt
795cef8759bSmrg     {
796627f7eb2Smrg       static string_type
797627f7eb2Smrg       _S_convert(const _CharT* __f, const _CharT* __l)
798627f7eb2Smrg       {
799cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
800cef8759bSmrg 	std::wstring __wstr;
801627f7eb2Smrg 	if constexpr (is_same_v<_CharT, char>)
802cef8759bSmrg 	  {
803627f7eb2Smrg 	    struct _UCvt : std::codecvt<wchar_t, char, std::mbstate_t>
804627f7eb2Smrg 	    { } __cvt;
805627f7eb2Smrg 	    if (__str_codecvt_in_all(__f, __l, __wstr, __cvt))
806627f7eb2Smrg 	      return __wstr;
807627f7eb2Smrg 	  }
808627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
809627f7eb2Smrg 	else if constexpr (is_same_v<_CharT, char8_t>)
810627f7eb2Smrg 	  {
811627f7eb2Smrg 	    const char* __f2 = (const char*)__f;
812627f7eb2Smrg 	    const char* __l2 = (const char*)__l;
813627f7eb2Smrg 	    std::codecvt_utf8_utf16<wchar_t> __wcvt;
814627f7eb2Smrg 	    if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
815627f7eb2Smrg 	      return __wstr;
816627f7eb2Smrg 	  }
817627f7eb2Smrg #endif
818627f7eb2Smrg 	else // char16_t or char32_t
819627f7eb2Smrg 	  {
820627f7eb2Smrg 	    struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t>
821627f7eb2Smrg 	    { } __cvt;
822cef8759bSmrg 	    std::string __str;
823627f7eb2Smrg 	    if (__str_codecvt_out_all(__f, __l, __str, __cvt))
824cef8759bSmrg 	      {
825cef8759bSmrg 		const char* __f2 = __str.data();
826cef8759bSmrg 		const char* __l2 = __f2 + __str.size();
827627f7eb2Smrg 		std::codecvt_utf8_utf16<wchar_t> __wcvt;
828627f7eb2Smrg 		if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
829cef8759bSmrg 		  return __wstr;
830cef8759bSmrg 	      }
831cef8759bSmrg 	  }
832627f7eb2Smrg #else // ! windows
833627f7eb2Smrg 	struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t>
834627f7eb2Smrg 	{ } __cvt;
835cef8759bSmrg 	std::string __str;
836627f7eb2Smrg 	if (__str_codecvt_out_all(__f, __l, __str, __cvt))
837cef8759bSmrg 	  return __str;
838627f7eb2Smrg #endif
839cef8759bSmrg 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
840cef8759bSmrg 	      "Cannot convert character sequence",
841cef8759bSmrg 	      std::make_error_code(errc::illegal_byte_sequence)));
842cef8759bSmrg       }
843cef8759bSmrg 
844cef8759bSmrg       static string_type
845cef8759bSmrg       _S_convert(_CharT* __f, _CharT* __l)
846cef8759bSmrg       {
847cef8759bSmrg 	return _S_convert(const_cast<const _CharT*>(__f),
848cef8759bSmrg 			  const_cast<const _CharT*>(__l));
849cef8759bSmrg       }
850cef8759bSmrg 
851cef8759bSmrg       template<typename _Iter>
852cef8759bSmrg 	static string_type
853cef8759bSmrg 	_S_convert(_Iter __first, _Iter __last)
854cef8759bSmrg 	{
855cef8759bSmrg 	  const std::basic_string<_CharT> __str(__first, __last);
856cef8759bSmrg 	  return _S_convert(__str.data(), __str.data() + __str.size());
857cef8759bSmrg 	}
858cef8759bSmrg 
859cef8759bSmrg       template<typename _Iter, typename _Cont>
860cef8759bSmrg 	static string_type
861cef8759bSmrg 	_S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first,
862cef8759bSmrg 		  __gnu_cxx::__normal_iterator<_Iter, _Cont> __last)
863cef8759bSmrg 	{ return _S_convert(__first.base(), __last.base()); }
864cef8759bSmrg     };
865cef8759bSmrg 
8664c3eb207Smrg   /// @endcond
8674c3eb207Smrg 
868cef8759bSmrg   /// An iterator for the components of a path
869cef8759bSmrg   class path::iterator
870cef8759bSmrg   {
871cef8759bSmrg   public:
872cef8759bSmrg     using difference_type	= std::ptrdiff_t;
873cef8759bSmrg     using value_type		= path;
874cef8759bSmrg     using reference		= const path&;
875cef8759bSmrg     using pointer		= const path*;
876cef8759bSmrg     using iterator_category	= std::bidirectional_iterator_tag;
877cef8759bSmrg 
878cef8759bSmrg     iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { }
879cef8759bSmrg 
880cef8759bSmrg     iterator(const iterator&) = default;
881cef8759bSmrg     iterator& operator=(const iterator&) = default;
882cef8759bSmrg 
883cef8759bSmrg     reference operator*() const;
884cef8759bSmrg     pointer   operator->() const { return std::__addressof(**this); }
885cef8759bSmrg 
886cef8759bSmrg     iterator& operator++();
887cef8759bSmrg     iterator  operator++(int) { auto __tmp = *this; ++*this; return __tmp; }
888cef8759bSmrg 
889cef8759bSmrg     iterator& operator--();
890cef8759bSmrg     iterator  operator--(int) { auto __tmp = *this; --*this; return __tmp; }
891cef8759bSmrg 
892cef8759bSmrg     friend bool operator==(const iterator& __lhs, const iterator& __rhs)
893cef8759bSmrg     { return __lhs._M_equals(__rhs); }
894cef8759bSmrg 
895cef8759bSmrg     friend bool operator!=(const iterator& __lhs, const iterator& __rhs)
896cef8759bSmrg     { return !__lhs._M_equals(__rhs); }
897cef8759bSmrg 
898cef8759bSmrg   private:
899cef8759bSmrg     friend class path;
900cef8759bSmrg 
901627f7eb2Smrg     bool _M_is_multi() const { return _M_path->_M_type() == _Type::_Multi; }
902627f7eb2Smrg 
903627f7eb2Smrg     friend difference_type
904627f7eb2Smrg     __path_iter_distance(const iterator& __first, const iterator& __last)
905627f7eb2Smrg     {
906627f7eb2Smrg       __glibcxx_assert(__first._M_path != nullptr);
907627f7eb2Smrg       __glibcxx_assert(__first._M_path == __last._M_path);
908627f7eb2Smrg       if (__first._M_is_multi())
909627f7eb2Smrg 	return std::distance(__first._M_cur, __last._M_cur);
910627f7eb2Smrg       else if (__first._M_at_end == __last._M_at_end)
911627f7eb2Smrg 	return 0;
912627f7eb2Smrg       else
913627f7eb2Smrg 	return __first._M_at_end ? -1 : 1;
914627f7eb2Smrg     }
915627f7eb2Smrg 
916627f7eb2Smrg     friend void
917627f7eb2Smrg     __path_iter_advance(iterator& __i, difference_type __n)
918627f7eb2Smrg     {
919627f7eb2Smrg       if (__n == 1)
920627f7eb2Smrg 	++__i;
921627f7eb2Smrg       else if (__n == -1)
922627f7eb2Smrg 	--__i;
923627f7eb2Smrg       else if (__n != 0)
924627f7eb2Smrg 	{
925627f7eb2Smrg 	  __glibcxx_assert(__i._M_path != nullptr);
926627f7eb2Smrg 	  __glibcxx_assert(__i._M_is_multi());
927627f7eb2Smrg 	  // __glibcxx_assert(__i._M_path->_M_cmpts.end() - __i._M_cur >= __n);
928627f7eb2Smrg 	  __i._M_cur += __n;
929627f7eb2Smrg 	}
930627f7eb2Smrg     }
931627f7eb2Smrg 
932cef8759bSmrg     iterator(const path* __path, path::_List::const_iterator __iter)
933cef8759bSmrg     : _M_path(__path), _M_cur(__iter), _M_at_end()
934cef8759bSmrg     { }
935cef8759bSmrg 
936cef8759bSmrg     iterator(const path* __path, bool __at_end)
937cef8759bSmrg     : _M_path(__path), _M_cur(), _M_at_end(__at_end)
938cef8759bSmrg     { }
939cef8759bSmrg 
940cef8759bSmrg     bool _M_equals(iterator) const;
941cef8759bSmrg 
942cef8759bSmrg     const path* 		_M_path;
943cef8759bSmrg     path::_List::const_iterator _M_cur;
944cef8759bSmrg     bool			_M_at_end;  // only used when type != _Multi
945cef8759bSmrg   };
946cef8759bSmrg 
947cef8759bSmrg 
948cef8759bSmrg   inline path&
949cef8759bSmrg   path::operator=(path&& __p) noexcept
950cef8759bSmrg   {
951627f7eb2Smrg     if (&__p == this) [[__unlikely__]]
952cef8759bSmrg       return *this;
953cef8759bSmrg 
954cef8759bSmrg     _M_pathname = std::move(__p._M_pathname);
955cef8759bSmrg     _M_cmpts = std::move(__p._M_cmpts);
956cef8759bSmrg     __p.clear();
957cef8759bSmrg     return *this;
958cef8759bSmrg   }
959cef8759bSmrg 
960cef8759bSmrg   inline path&
961cef8759bSmrg   path::operator=(string_type&& __source)
962cef8759bSmrg   { return *this = path(std::move(__source)); }
963cef8759bSmrg 
964cef8759bSmrg   inline path&
965cef8759bSmrg   path::assign(string_type&& __source)
966cef8759bSmrg   { return *this = path(std::move(__source)); }
967cef8759bSmrg 
968cef8759bSmrg   inline path&
969cef8759bSmrg   path::operator+=(const string_type& __x)
970cef8759bSmrg   {
971627f7eb2Smrg     _M_concat(__x);
972cef8759bSmrg     return *this;
973cef8759bSmrg   }
974cef8759bSmrg 
975cef8759bSmrg   inline path&
976cef8759bSmrg   path::operator+=(const value_type* __x)
977cef8759bSmrg   {
978627f7eb2Smrg     _M_concat(__x);
979cef8759bSmrg     return *this;
980cef8759bSmrg   }
981cef8759bSmrg 
982cef8759bSmrg   inline path&
983cef8759bSmrg   path::operator+=(value_type __x)
984cef8759bSmrg   {
985627f7eb2Smrg     _M_concat(basic_string_view<value_type>(&__x, 1));
986cef8759bSmrg     return *this;
987cef8759bSmrg   }
988cef8759bSmrg 
989cef8759bSmrg   inline path&
990cef8759bSmrg   path::operator+=(basic_string_view<value_type> __x)
991cef8759bSmrg   {
992627f7eb2Smrg     _M_concat(__x);
993cef8759bSmrg     return *this;
994cef8759bSmrg   }
995cef8759bSmrg 
996cef8759bSmrg   template<typename _CharT>
9974c3eb207Smrg     inline __detail::_Path<_CharT*, _CharT*>&
998cef8759bSmrg     path::operator+=(_CharT __x)
999cef8759bSmrg     {
1000cef8759bSmrg       auto* __addr = std::__addressof(__x);
1001cef8759bSmrg       return concat(__addr, __addr + 1);
1002cef8759bSmrg     }
1003cef8759bSmrg 
1004cef8759bSmrg   inline path&
1005cef8759bSmrg   path::make_preferred()
1006cef8759bSmrg   {
1007cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1008cef8759bSmrg     std::replace(_M_pathname.begin(), _M_pathname.end(), L'/',
1009cef8759bSmrg 		 preferred_separator);
1010cef8759bSmrg #endif
1011cef8759bSmrg     return *this;
1012cef8759bSmrg   }
1013cef8759bSmrg 
1014cef8759bSmrg   inline void path::swap(path& __rhs) noexcept
1015cef8759bSmrg   {
1016cef8759bSmrg     _M_pathname.swap(__rhs._M_pathname);
1017cef8759bSmrg     _M_cmpts.swap(__rhs._M_cmpts);
1018cef8759bSmrg   }
1019cef8759bSmrg 
10204c3eb207Smrg   /// @cond undocumented
1021cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Allocator>
1022cef8759bSmrg     std::basic_string<_CharT, _Traits, _Allocator>
10234c3eb207Smrg     path::_S_str_convert(basic_string_view<value_type> __str,
10244c3eb207Smrg 			 const _Allocator& __a)
1025cef8759bSmrg     {
1026627f7eb2Smrg       static_assert(!is_same_v<_CharT, value_type>);
1027cef8759bSmrg 
1028cef8759bSmrg       using _WString = basic_string<_CharT, _Traits, _Allocator>;
1029cef8759bSmrg 
1030627f7eb2Smrg       if (__str.size() == 0)
1031627f7eb2Smrg 	return _WString(__a);
1032627f7eb2Smrg 
1033627f7eb2Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1034627f7eb2Smrg       // First convert native string from UTF-16 to to UTF-8.
1035627f7eb2Smrg       // XXX This assumes that the execution wide-character set is UTF-16.
1036627f7eb2Smrg       std::codecvt_utf8_utf16<value_type> __cvt;
1037627f7eb2Smrg 
1038627f7eb2Smrg       using _CharAlloc = __alloc_rebind<_Allocator, char>;
1039627f7eb2Smrg       using _String = basic_string<char, char_traits<char>, _CharAlloc>;
1040cef8759bSmrg       _String __u8str{_CharAlloc{__a}};
1041627f7eb2Smrg       const value_type* __wfirst = __str.data();
1042627f7eb2Smrg       const value_type* __wlast = __wfirst + __str.size();
1043627f7eb2Smrg       if (__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt)) {
1044cef8759bSmrg       if constexpr (is_same_v<_CharT, char>)
1045627f7eb2Smrg 	return __u8str; // XXX assumes native ordinary encoding is UTF-8.
1046627f7eb2Smrg       else {
1047627f7eb2Smrg 
1048627f7eb2Smrg       const char* __first = __u8str.data();
1049627f7eb2Smrg       const char* __last = __first + __u8str.size();
1050cef8759bSmrg #else
1051627f7eb2Smrg       const value_type* __first = __str.data();
1052627f7eb2Smrg       const value_type* __last = __first + __str.size();
1053627f7eb2Smrg #endif
1054627f7eb2Smrg 
1055627f7eb2Smrg       // Convert UTF-8 string to requested format.
1056627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1057627f7eb2Smrg       if constexpr (is_same_v<_CharT, char8_t>)
1058627f7eb2Smrg 	return _WString(__first, __last, __a);
1059627f7eb2Smrg       else
1060627f7eb2Smrg #endif
1061627f7eb2Smrg 	{
1062627f7eb2Smrg 	  // Convert UTF-8 to wide string.
1063627f7eb2Smrg 	  _WString __wstr(__a);
1064627f7eb2Smrg 	  struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> { } __cvt;
1065627f7eb2Smrg 	  if (__str_codecvt_in_all(__first, __last, __wstr, __cvt))
1066cef8759bSmrg 	    return __wstr;
1067627f7eb2Smrg 	}
1068627f7eb2Smrg 
1069627f7eb2Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1070627f7eb2Smrg       } }
1071cef8759bSmrg #endif
1072cef8759bSmrg       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1073cef8759bSmrg 	    "Cannot convert character sequence",
1074cef8759bSmrg 	    std::make_error_code(errc::illegal_byte_sequence)));
1075cef8759bSmrg     }
10764c3eb207Smrg   /// @endcond
1077cef8759bSmrg 
1078cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Allocator>
1079cef8759bSmrg     inline basic_string<_CharT, _Traits, _Allocator>
1080cef8759bSmrg     path::string(const _Allocator& __a) const
1081cef8759bSmrg     {
1082cef8759bSmrg       if constexpr (is_same_v<_CharT, value_type>)
1083627f7eb2Smrg 	return { _M_pathname.c_str(), _M_pathname.length(), __a };
1084cef8759bSmrg       else
1085cef8759bSmrg 	return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);
1086cef8759bSmrg     }
1087cef8759bSmrg 
1088cef8759bSmrg   inline std::string
1089cef8759bSmrg   path::string() const { return string<char>(); }
1090cef8759bSmrg 
1091cef8759bSmrg #if _GLIBCXX_USE_WCHAR_T
1092cef8759bSmrg   inline std::wstring
1093cef8759bSmrg   path::wstring() const { return string<wchar_t>(); }
1094cef8759bSmrg #endif
1095cef8759bSmrg 
1096627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1097627f7eb2Smrg   inline std::u8string
1098627f7eb2Smrg   path::u8string() const { return string<char8_t>(); }
1099627f7eb2Smrg #else
1100cef8759bSmrg   inline std::string
1101cef8759bSmrg   path::u8string() const
1102cef8759bSmrg   {
1103cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1104cef8759bSmrg     std::string __str;
1105627f7eb2Smrg     // convert from native wide encoding (assumed to be UTF-16) to UTF-8
1106627f7eb2Smrg     std::codecvt_utf8_utf16<value_type> __cvt;
1107cef8759bSmrg     const value_type* __first = _M_pathname.data();
1108cef8759bSmrg     const value_type* __last = __first + _M_pathname.size();
1109627f7eb2Smrg     if (__str_codecvt_out_all(__first, __last, __str, __cvt))
1110cef8759bSmrg       return __str;
1111cef8759bSmrg     _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1112cef8759bSmrg 	  "Cannot convert character sequence",
1113cef8759bSmrg 	  std::make_error_code(errc::illegal_byte_sequence)));
1114cef8759bSmrg #else
1115cef8759bSmrg     return _M_pathname;
1116cef8759bSmrg #endif
1117cef8759bSmrg   }
1118627f7eb2Smrg #endif // _GLIBCXX_USE_CHAR8_T
1119cef8759bSmrg 
1120cef8759bSmrg   inline std::u16string
1121cef8759bSmrg   path::u16string() const { return string<char16_t>(); }
1122cef8759bSmrg 
1123cef8759bSmrg   inline std::u32string
1124cef8759bSmrg   path::u32string() const { return string<char32_t>(); }
1125cef8759bSmrg 
1126cef8759bSmrg   template<typename _CharT, typename _Traits, typename _Allocator>
1127cef8759bSmrg     inline std::basic_string<_CharT, _Traits, _Allocator>
1128cef8759bSmrg     path::generic_string(const _Allocator& __a) const
1129cef8759bSmrg     {
1130cef8759bSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1131cef8759bSmrg       const value_type __slash = L'/';
1132cef8759bSmrg #else
1133cef8759bSmrg       const value_type __slash = '/';
1134cef8759bSmrg #endif
11354c3eb207Smrg       using _Alloc2 = typename allocator_traits<_Allocator>::template
11364c3eb207Smrg 	rebind_alloc<value_type>;
11374c3eb207Smrg       basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a);
1138cef8759bSmrg 
1139627f7eb2Smrg       if (_M_type() == _Type::_Root_dir)
1140cef8759bSmrg 	__str.assign(1, __slash);
1141cef8759bSmrg       else
1142cef8759bSmrg 	{
1143cef8759bSmrg 	  __str.reserve(_M_pathname.size());
1144cef8759bSmrg 	  bool __add_slash = false;
1145cef8759bSmrg 	  for (auto& __elem : *this)
1146cef8759bSmrg 	    {
11474c3eb207Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
11484c3eb207Smrg 	      if (__elem._M_type() == _Type::_Root_dir)
11494c3eb207Smrg 		{
11504c3eb207Smrg 		  __str += __slash;
11514c3eb207Smrg 		  continue;
11524c3eb207Smrg 		}
11534c3eb207Smrg #endif
1154cef8759bSmrg 	      if (__add_slash)
1155cef8759bSmrg 		__str += __slash;
11564c3eb207Smrg 	      __str += basic_string_view<value_type>(__elem._M_pathname);
1157627f7eb2Smrg 	      __add_slash = __elem._M_type() == _Type::_Filename;
1158cef8759bSmrg 	    }
1159cef8759bSmrg 	}
1160cef8759bSmrg 
1161cef8759bSmrg       if constexpr (is_same_v<_CharT, value_type>)
1162cef8759bSmrg 	return __str;
1163cef8759bSmrg       else
1164cef8759bSmrg 	return _S_str_convert<_CharT, _Traits>(__str, __a);
1165cef8759bSmrg     }
1166cef8759bSmrg 
1167cef8759bSmrg   inline std::string
1168cef8759bSmrg   path::generic_string() const
1169cef8759bSmrg   { return generic_string<char>(); }
1170cef8759bSmrg 
1171cef8759bSmrg #if _GLIBCXX_USE_WCHAR_T
1172cef8759bSmrg   inline std::wstring
1173cef8759bSmrg   path::generic_wstring() const
1174cef8759bSmrg   { return generic_string<wchar_t>(); }
1175cef8759bSmrg #endif
1176cef8759bSmrg 
1177627f7eb2Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1178627f7eb2Smrg   inline std::u8string
1179627f7eb2Smrg   path::generic_u8string() const
1180627f7eb2Smrg   { return generic_string<char8_t>(); }
1181627f7eb2Smrg #else
1182cef8759bSmrg   inline std::string
1183cef8759bSmrg   path::generic_u8string() const
1184cef8759bSmrg   { return generic_string(); }
1185627f7eb2Smrg #endif
1186cef8759bSmrg 
1187cef8759bSmrg   inline std::u16string
1188cef8759bSmrg   path::generic_u16string() const
1189cef8759bSmrg   { return generic_string<char16_t>(); }
1190cef8759bSmrg 
1191cef8759bSmrg   inline std::u32string
1192cef8759bSmrg   path::generic_u32string() const
1193cef8759bSmrg   { return generic_string<char32_t>(); }
1194cef8759bSmrg 
1195cef8759bSmrg   inline int
1196627f7eb2Smrg   path::compare(const string_type& __s) const noexcept
1197627f7eb2Smrg   { return compare(basic_string_view<value_type>(__s)); }
1198cef8759bSmrg 
1199cef8759bSmrg   inline int
1200627f7eb2Smrg   path::compare(const value_type* __s) const noexcept
1201627f7eb2Smrg   { return compare(basic_string_view<value_type>(__s)); }
1202cef8759bSmrg 
1203cef8759bSmrg   inline path
1204cef8759bSmrg   path::filename() const
1205cef8759bSmrg   {
1206cef8759bSmrg     if (empty())
1207cef8759bSmrg       return {};
1208627f7eb2Smrg     else if (_M_type() == _Type::_Filename)
1209cef8759bSmrg       return *this;
1210627f7eb2Smrg     else if (_M_type() == _Type::_Multi)
1211cef8759bSmrg       {
1212cef8759bSmrg 	if (_M_pathname.back() == preferred_separator)
1213cef8759bSmrg 	  return {};
1214*4ac76180Smrg 	auto __last = --end();
1215*4ac76180Smrg 	if (__last->_M_type() == _Type::_Filename)
1216*4ac76180Smrg 	  return *__last;
1217cef8759bSmrg       }
1218cef8759bSmrg     return {};
1219cef8759bSmrg   }
1220cef8759bSmrg 
1221cef8759bSmrg   inline path
1222cef8759bSmrg   path::stem() const
1223cef8759bSmrg   {
1224cef8759bSmrg     auto ext = _M_find_extension();
1225cef8759bSmrg     if (ext.first && ext.second != 0)
1226cef8759bSmrg       return path{ext.first->substr(0, ext.second)};
1227cef8759bSmrg     return {};
1228cef8759bSmrg   }
1229cef8759bSmrg 
1230cef8759bSmrg   inline path
1231cef8759bSmrg   path::extension() const
1232cef8759bSmrg   {
1233cef8759bSmrg     auto ext = _M_find_extension();
1234cef8759bSmrg     if (ext.first && ext.second != string_type::npos)
1235cef8759bSmrg       return path{ext.first->substr(ext.second)};
1236cef8759bSmrg     return {};
1237cef8759bSmrg   }
1238cef8759bSmrg 
1239cef8759bSmrg   inline bool
1240627f7eb2Smrg   path::has_stem() const noexcept
1241cef8759bSmrg   {
1242cef8759bSmrg     auto ext = _M_find_extension();
1243cef8759bSmrg     return ext.first && ext.second != 0;
1244cef8759bSmrg   }
1245cef8759bSmrg 
1246cef8759bSmrg   inline bool
1247627f7eb2Smrg   path::has_extension() const noexcept
1248cef8759bSmrg   {
1249cef8759bSmrg     auto ext = _M_find_extension();
1250cef8759bSmrg     return ext.first && ext.second != string_type::npos;
1251cef8759bSmrg   }
1252cef8759bSmrg 
1253627f7eb2Smrg   inline bool
1254627f7eb2Smrg   path::is_absolute() const noexcept
1255627f7eb2Smrg   {
1256627f7eb2Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1257627f7eb2Smrg     return has_root_name() && has_root_directory();
1258627f7eb2Smrg #else
1259627f7eb2Smrg     return has_root_directory();
1260627f7eb2Smrg #endif
1261627f7eb2Smrg   }
1262627f7eb2Smrg 
1263cef8759bSmrg   inline path::iterator
1264cef8759bSmrg   path::begin() const
1265cef8759bSmrg   {
1266627f7eb2Smrg     if (_M_type() == _Type::_Multi)
1267cef8759bSmrg       return iterator(this, _M_cmpts.begin());
1268cef8759bSmrg     return iterator(this, empty());
1269cef8759bSmrg   }
1270cef8759bSmrg 
1271cef8759bSmrg   inline path::iterator
1272cef8759bSmrg   path::end() const
1273cef8759bSmrg   {
1274627f7eb2Smrg     if (_M_type() == _Type::_Multi)
1275cef8759bSmrg       return iterator(this, _M_cmpts.end());
1276cef8759bSmrg     return iterator(this, true);
1277cef8759bSmrg   }
1278cef8759bSmrg 
1279cef8759bSmrg   inline path::iterator&
1280cef8759bSmrg   path::iterator::operator++()
1281cef8759bSmrg   {
1282cef8759bSmrg     __glibcxx_assert(_M_path != nullptr);
1283627f7eb2Smrg     if (_M_path->_M_type() == _Type::_Multi)
1284cef8759bSmrg       {
1285cef8759bSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1286cef8759bSmrg 	++_M_cur;
1287cef8759bSmrg       }
1288cef8759bSmrg     else
1289cef8759bSmrg       {
1290cef8759bSmrg 	__glibcxx_assert(!_M_at_end);
1291cef8759bSmrg 	_M_at_end = true;
1292cef8759bSmrg       }
1293cef8759bSmrg     return *this;
1294cef8759bSmrg   }
1295cef8759bSmrg 
1296cef8759bSmrg   inline path::iterator&
1297cef8759bSmrg   path::iterator::operator--()
1298cef8759bSmrg   {
1299cef8759bSmrg     __glibcxx_assert(_M_path != nullptr);
1300627f7eb2Smrg     if (_M_path->_M_type() == _Type::_Multi)
1301cef8759bSmrg       {
1302cef8759bSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
1303cef8759bSmrg 	--_M_cur;
1304cef8759bSmrg       }
1305cef8759bSmrg     else
1306cef8759bSmrg       {
1307cef8759bSmrg 	__glibcxx_assert(_M_at_end);
1308cef8759bSmrg 	_M_at_end = false;
1309cef8759bSmrg       }
1310cef8759bSmrg     return *this;
1311cef8759bSmrg   }
1312cef8759bSmrg 
1313cef8759bSmrg   inline path::iterator::reference
1314cef8759bSmrg   path::iterator::operator*() const
1315cef8759bSmrg   {
1316cef8759bSmrg     __glibcxx_assert(_M_path != nullptr);
1317627f7eb2Smrg     if (_M_path->_M_type() == _Type::_Multi)
1318cef8759bSmrg       {
1319cef8759bSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1320cef8759bSmrg 	return *_M_cur;
1321cef8759bSmrg       }
1322cef8759bSmrg     return *_M_path;
1323cef8759bSmrg   }
1324cef8759bSmrg 
1325cef8759bSmrg   inline bool
1326cef8759bSmrg   path::iterator::_M_equals(iterator __rhs) const
1327cef8759bSmrg   {
1328cef8759bSmrg     if (_M_path != __rhs._M_path)
1329cef8759bSmrg       return false;
1330cef8759bSmrg     if (_M_path == nullptr)
1331cef8759bSmrg       return true;
1332627f7eb2Smrg     if (_M_path->_M_type() == path::_Type::_Multi)
1333cef8759bSmrg       return _M_cur == __rhs._M_cur;
1334cef8759bSmrg     return _M_at_end == __rhs._M_at_end;
1335cef8759bSmrg   }
1336cef8759bSmrg 
13374c3eb207Smrg   /// @} group filesystem
1338cef8759bSmrg _GLIBCXX_END_NAMESPACE_CXX11
1339cef8759bSmrg } // namespace filesystem
1340cef8759bSmrg 
1341627f7eb2Smrg inline ptrdiff_t
1342627f7eb2Smrg distance(filesystem::path::iterator __first, filesystem::path::iterator __last)
1343627f7eb2Smrg { return __path_iter_distance(__first, __last); }
1344627f7eb2Smrg 
13454c3eb207Smrg template<typename _Distance>
1346627f7eb2Smrg   void
1347627f7eb2Smrg   advance(filesystem::path::iterator& __i, _Distance __n)
1348627f7eb2Smrg   { __path_iter_advance(__i, static_cast<ptrdiff_t>(__n)); }
1349627f7eb2Smrg 
1350627f7eb2Smrg extern template class __shared_ptr<const filesystem::filesystem_error::_Impl>;
1351627f7eb2Smrg 
1352cef8759bSmrg _GLIBCXX_END_NAMESPACE_VERSION
1353cef8759bSmrg } // namespace std
1354cef8759bSmrg 
1355cef8759bSmrg #endif // C++17
1356cef8759bSmrg 
1357cef8759bSmrg #endif // _GLIBCXX_FS_PATH_H
1358