xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/experimental/bits/fs_path.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1f9a78e0eSmrg // Class filesystem::path -*- C++ -*-
2f9a78e0eSmrg 
3b1e83836Smrg // Copyright (C) 2014-2022 Free Software Foundation, Inc.
4f9a78e0eSmrg //
5f9a78e0eSmrg // This file is part of the GNU ISO C++ Library.  This library is free
6f9a78e0eSmrg // software; you can redistribute it and/or modify it under the
7f9a78e0eSmrg // terms of the GNU General Public License as published by the
8f9a78e0eSmrg // Free Software Foundation; either version 3, or (at your option)
9f9a78e0eSmrg // any later version.
10f9a78e0eSmrg 
11f9a78e0eSmrg // This library is distributed in the hope that it will be useful,
12f9a78e0eSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
13f9a78e0eSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14f9a78e0eSmrg // GNU General Public License for more details.
15f9a78e0eSmrg 
16f9a78e0eSmrg // Under Section 7 of GPL version 3, you are granted additional
17f9a78e0eSmrg // permissions described in the GCC Runtime Library Exception, version
18f9a78e0eSmrg // 3.1, as published by the Free Software Foundation.
19f9a78e0eSmrg 
20f9a78e0eSmrg // You should have received a copy of the GNU General Public License and
21f9a78e0eSmrg // a copy of the GCC Runtime Library Exception along with this program;
22f9a78e0eSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23f9a78e0eSmrg // <http://www.gnu.org/licenses/>.
24f9a78e0eSmrg 
25f9a78e0eSmrg /** @file experimental/bits/fs_path.h
26f9a78e0eSmrg  *  This is an internal header file, included by other library headers.
27f9a78e0eSmrg  *  Do not attempt to use it directly. @headername{experimental/filesystem}
28f9a78e0eSmrg  */
29f9a78e0eSmrg 
30f9a78e0eSmrg #ifndef _GLIBCXX_EXPERIMENTAL_FS_PATH_H
31f9a78e0eSmrg #define _GLIBCXX_EXPERIMENTAL_FS_PATH_H 1
32f9a78e0eSmrg 
33f9a78e0eSmrg #if __cplusplus < 201103L
34f9a78e0eSmrg # include <bits/c++0x_warning.h>
35f9a78e0eSmrg #else
36f9a78e0eSmrg 
37f9a78e0eSmrg #include <utility>
38f9a78e0eSmrg #include <type_traits>
39f9a78e0eSmrg #include <vector>
40f9a78e0eSmrg #include <locale>
41f9a78e0eSmrg #include <iosfwd>
42f9a78e0eSmrg #include <codecvt>
43f9a78e0eSmrg #include <system_error>
44f9a78e0eSmrg #include <bits/stl_algobase.h>
45f9a78e0eSmrg #include <bits/quoted_string.h>
46f9a78e0eSmrg #include <bits/locale_conv.h>
47b17d1066Smrg #if __cplusplus == 201402L
48f9a78e0eSmrg # include <experimental/string_view>
49f9a78e0eSmrg #endif
50f9a78e0eSmrg 
51f9a78e0eSmrg #if defined(_WIN32) && !defined(__CYGWIN__)
52f9a78e0eSmrg # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1
53f9a78e0eSmrg # include <algorithm>
54f9a78e0eSmrg #endif
55f9a78e0eSmrg 
_GLIBCXX_VISIBILITY(default)56f9a78e0eSmrg namespace std _GLIBCXX_VISIBILITY(default)
57f9a78e0eSmrg {
58a3e9eb18Smrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
59a3e9eb18Smrg 
60f9a78e0eSmrg namespace experimental
61f9a78e0eSmrg {
62f9a78e0eSmrg namespace filesystem
63f9a78e0eSmrg {
64f9a78e0eSmrg inline namespace v1
65f9a78e0eSmrg {
66f9a78e0eSmrg _GLIBCXX_BEGIN_NAMESPACE_CXX11
67f9a78e0eSmrg 
68b17d1066Smrg #if __cplusplus == 201402L
69b17d1066Smrg   using std::experimental::basic_string_view;
70b17d1066Smrg #elif __cplusplus > 201402L
71b17d1066Smrg   using std::basic_string_view;
72f9a78e0eSmrg #endif
73f9a78e0eSmrg 
74b1e83836Smrg   /// @cond undocumented
75b1e83836Smrg namespace __detail
76b1e83836Smrg {
77fb8a8121Smrg   /** @addtogroup filesystem-ts
78f9a78e0eSmrg    *  @{
79f9a78e0eSmrg    */
80f9a78e0eSmrg 
81181254a7Smrg   template<typename _CharT,
82181254a7Smrg 	   typename _Ch = typename remove_const<_CharT>::type>
83181254a7Smrg     using __is_encoded_char
84181254a7Smrg       = __or_<is_same<_Ch, char>,
85181254a7Smrg 	      is_same<_Ch, wchar_t>,
86181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
87181254a7Smrg 	      is_same<_Ch, char8_t>,
88181254a7Smrg #endif
89181254a7Smrg 	      is_same<_Ch, char16_t>,
90181254a7Smrg 	      is_same<_Ch, char32_t>>;
91f9a78e0eSmrg 
92f9a78e0eSmrg   template<typename _Iter,
93f9a78e0eSmrg 	   typename _Iter_traits = std::iterator_traits<_Iter>>
94f9a78e0eSmrg     using __is_path_iter_src
95f9a78e0eSmrg       = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
96f9a78e0eSmrg 	       std::is_base_of<std::input_iterator_tag,
97f9a78e0eSmrg 			       typename _Iter_traits::iterator_category>>;
98f9a78e0eSmrg 
99f9a78e0eSmrg   template<typename _Iter>
100f9a78e0eSmrg     static __is_path_iter_src<_Iter>
101f9a78e0eSmrg     __is_path_src(_Iter, int);
102f9a78e0eSmrg 
103f9a78e0eSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
104f9a78e0eSmrg     static __is_encoded_char<_CharT>
105f9a78e0eSmrg     __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
106f9a78e0eSmrg 
107f9a78e0eSmrg #if __cplusplus >= 201402L
108f9a78e0eSmrg   template<typename _CharT, typename _Traits>
109f9a78e0eSmrg     static __is_encoded_char<_CharT>
110b17d1066Smrg     __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
111f9a78e0eSmrg #endif
112f9a78e0eSmrg 
113f9a78e0eSmrg   template<typename _Unknown>
114f9a78e0eSmrg     static std::false_type
115f9a78e0eSmrg     __is_path_src(const _Unknown&, ...);
116f9a78e0eSmrg 
117f9a78e0eSmrg   template<typename _Tp1, typename _Tp2>
118f9a78e0eSmrg     struct __constructible_from;
119f9a78e0eSmrg 
120f9a78e0eSmrg   template<typename _Iter>
121f9a78e0eSmrg     struct __constructible_from<_Iter, _Iter>
122f9a78e0eSmrg     : __is_path_iter_src<_Iter>
123f9a78e0eSmrg     { };
124f9a78e0eSmrg 
125f9a78e0eSmrg   template<typename _Source>
126f9a78e0eSmrg     struct __constructible_from<_Source, void>
127a448f87cSmrg     : decltype(__is_path_src(std::declval<const _Source&>(), 0))
128f9a78e0eSmrg     { };
129f9a78e0eSmrg 
130a3e9eb18Smrg   template<typename _Tp1, typename _Tp2 = void,
131a3e9eb18Smrg 	   typename _Tp1_nocv = typename remove_cv<_Tp1>::type,
132a3e9eb18Smrg 	   typename _Tp1_noptr = typename remove_pointer<_Tp1>::type>
133f9a78e0eSmrg     using _Path = typename
134a3e9eb18Smrg       std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>,
135a3e9eb18Smrg 			    __not_<is_void<_Tp1_noptr>>,
136f9a78e0eSmrg 			    __constructible_from<_Tp1, _Tp2>>::value,
137f9a78e0eSmrg 		     path>::type;
138f9a78e0eSmrg 
139f9a78e0eSmrg   template<typename _Source>
140fb8a8121Smrg     inline _Source
141f9a78e0eSmrg     _S_range_begin(_Source __begin) { return __begin; }
142f9a78e0eSmrg 
143a448f87cSmrg   struct __nul_terminated { };
144f9a78e0eSmrg 
145f9a78e0eSmrg   template<typename _Source>
146a448f87cSmrg     inline __nul_terminated
147f9a78e0eSmrg     _S_range_end(_Source) { return {}; }
148f9a78e0eSmrg 
149f9a78e0eSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
150fb8a8121Smrg     inline const _CharT*
151f9a78e0eSmrg     _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
152f9a78e0eSmrg     { return __str.data(); }
153f9a78e0eSmrg 
154f9a78e0eSmrg   template<typename _CharT, typename _Traits, typename _Alloc>
155fb8a8121Smrg     inline const _CharT*
156f9a78e0eSmrg     _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
157f9a78e0eSmrg     { return __str.data() + __str.size(); }
158f9a78e0eSmrg 
159f9a78e0eSmrg #if __cplusplus >= 201402L
160f9a78e0eSmrg   template<typename _CharT, typename _Traits>
161fb8a8121Smrg     inline const _CharT*
162b17d1066Smrg     _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
163f9a78e0eSmrg     { return __str.data(); }
164f9a78e0eSmrg 
165f9a78e0eSmrg   template<typename _CharT, typename _Traits>
166fb8a8121Smrg     inline const _CharT*
167b17d1066Smrg     _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
168f9a78e0eSmrg     { return __str.data() + __str.size(); }
169f9a78e0eSmrg #endif
170f9a78e0eSmrg 
171f9a78e0eSmrg   template<typename _Tp,
172f9a78e0eSmrg 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
173fb8a8121Smrg 	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
174fb8a8121Smrg 	   typename _UnqualVal = typename std::remove_const<_Val>::type>
175181254a7Smrg     using __value_type_is_char = typename std::enable_if<
176fb8a8121Smrg       std::is_same<_UnqualVal, char>::value,
177fb8a8121Smrg       _UnqualVal>::type;
178f9a78e0eSmrg 
179fb8a8121Smrg   template<typename _Tp,
180fb8a8121Smrg 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
181fb8a8121Smrg 	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
182fb8a8121Smrg 	   typename _UnqualVal = typename std::remove_const<_Val>::type>
183fb8a8121Smrg     using __value_type_is_char_or_char8_t = typename std::enable_if<
184fb8a8121Smrg       __or_<
185fb8a8121Smrg 	std::is_same<_UnqualVal, char>
186fb8a8121Smrg #ifdef _GLIBCXX_USE_CHAR8_T
187fb8a8121Smrg 	,std::is_same<_UnqualVal, char8_t>
188fb8a8121Smrg #endif
189fb8a8121Smrg       >::value, _UnqualVal>::type;
190fb8a8121Smrg 
191b1e83836Smrg   /// @} group filesystem-ts
192fb8a8121Smrg } // namespace __detail
193fb8a8121Smrg   /// @endcond
194fb8a8121Smrg 
195b1e83836Smrg   /** @addtogroup filesystem-ts
196b1e83836Smrg    *  @{
197b1e83836Smrg    */
198b1e83836Smrg 
199fb8a8121Smrg   /// A filesystem path.
200b1e83836Smrg   /// @ingroup filesystem-ts
201fb8a8121Smrg   class path
202fb8a8121Smrg   {
203f9a78e0eSmrg   public:
204f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
205f9a78e0eSmrg     typedef wchar_t				value_type;
206f9a78e0eSmrg     static constexpr value_type			preferred_separator = L'\\';
207f9a78e0eSmrg #else
208f9a78e0eSmrg     typedef char				value_type;
209f9a78e0eSmrg     static constexpr value_type			preferred_separator = '/';
210f9a78e0eSmrg #endif
211f9a78e0eSmrg     typedef std::basic_string<value_type>	string_type;
212f9a78e0eSmrg 
213f9a78e0eSmrg     // constructors and destructor
214f9a78e0eSmrg 
215b1e83836Smrg     path() noexcept;
216b1e83836Smrg     path(const path& __p);
217b1e83836Smrg     path(path&& __p) noexcept;
218f9a78e0eSmrg 
219b1e83836Smrg     path(string_type&& __source);
220f9a78e0eSmrg 
221f9a78e0eSmrg     template<typename _Source,
222fb8a8121Smrg 	     typename _Require = __detail::_Path<_Source>>
223f9a78e0eSmrg       path(_Source const& __source)
224fb8a8121Smrg       : _M_pathname(_S_convert(__detail::_S_range_begin(__source),
225fb8a8121Smrg 			       __detail::_S_range_end(__source)))
226f9a78e0eSmrg       { _M_split_cmpts(); }
227f9a78e0eSmrg 
228f9a78e0eSmrg     template<typename _InputIterator,
229fb8a8121Smrg 	     typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
230f9a78e0eSmrg       path(_InputIterator __first, _InputIterator __last)
231f9a78e0eSmrg       : _M_pathname(_S_convert(__first, __last))
232f9a78e0eSmrg       { _M_split_cmpts(); }
233f9a78e0eSmrg 
234f9a78e0eSmrg     template<typename _Source,
235fb8a8121Smrg 	     typename _Require = __detail::_Path<_Source>,
236fb8a8121Smrg 	     typename _Require2 = __detail::__value_type_is_char<_Source>>
237f9a78e0eSmrg       path(_Source const& __source, const locale& __loc)
238fb8a8121Smrg       : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
239fb8a8121Smrg 				   __detail::_S_range_end(__source), __loc))
240f9a78e0eSmrg       { _M_split_cmpts(); }
241f9a78e0eSmrg 
242f9a78e0eSmrg     template<typename _InputIterator,
243fb8a8121Smrg 	     typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
244fb8a8121Smrg 	     typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
245f9a78e0eSmrg       path(_InputIterator __first, _InputIterator __last, const locale& __loc)
246f9a78e0eSmrg       : _M_pathname(_S_convert_loc(__first, __last, __loc))
247f9a78e0eSmrg       { _M_split_cmpts(); }
248f9a78e0eSmrg 
249b1e83836Smrg     ~path();
250f9a78e0eSmrg 
251f9a78e0eSmrg     // assignments
252f9a78e0eSmrg 
253b1e83836Smrg     path& operator=(const path& __p);
254f9a78e0eSmrg     path& operator=(path&& __p) noexcept;
255f9a78e0eSmrg     path& operator=(string_type&& __source);
256f9a78e0eSmrg     path& assign(string_type&& __source);
257f9a78e0eSmrg 
258f9a78e0eSmrg     template<typename _Source>
259fb8a8121Smrg       __detail::_Path<_Source>&
260f9a78e0eSmrg       operator=(_Source const& __source)
261f9a78e0eSmrg       { return *this = path(__source); }
262f9a78e0eSmrg 
263f9a78e0eSmrg     template<typename _Source>
264fb8a8121Smrg       __detail::_Path<_Source>&
265f9a78e0eSmrg       assign(_Source const& __source)
266f9a78e0eSmrg       { return *this = path(__source); }
267f9a78e0eSmrg 
268f9a78e0eSmrg     template<typename _InputIterator>
269fb8a8121Smrg       __detail::_Path<_InputIterator, _InputIterator>&
270f9a78e0eSmrg       assign(_InputIterator __first, _InputIterator __last)
271f9a78e0eSmrg       { return *this = path(__first, __last); }
272f9a78e0eSmrg 
273f9a78e0eSmrg     // appends
274f9a78e0eSmrg 
275f9a78e0eSmrg     path& operator/=(const path& __p) { return _M_append(__p._M_pathname); }
276f9a78e0eSmrg 
277fb8a8121Smrg     template<typename _Source>
278fb8a8121Smrg       __detail::_Path<_Source>&
279f9a78e0eSmrg       operator/=(_Source const& __source)
280f9a78e0eSmrg       { return append(__source); }
281f9a78e0eSmrg 
282f9a78e0eSmrg     template<typename _Source>
283fb8a8121Smrg       __detail::_Path<_Source>&
284f9a78e0eSmrg       append(_Source const& __source)
285f9a78e0eSmrg       {
286fb8a8121Smrg 	return _M_append(_S_convert(__detail::_S_range_begin(__source),
287fb8a8121Smrg 				    __detail::_S_range_end(__source)));
288f9a78e0eSmrg       }
289f9a78e0eSmrg 
290f9a78e0eSmrg     template<typename _InputIterator>
291fb8a8121Smrg       __detail::_Path<_InputIterator, _InputIterator>&
292f9a78e0eSmrg       append(_InputIterator __first, _InputIterator __last)
293f9a78e0eSmrg       { return _M_append(_S_convert(__first, __last)); }
294f9a78e0eSmrg 
295f9a78e0eSmrg     // concatenation
296f9a78e0eSmrg 
297f9a78e0eSmrg     path& operator+=(const path& __x);
298f9a78e0eSmrg     path& operator+=(const string_type& __x);
299f9a78e0eSmrg     path& operator+=(const value_type* __x);
300f9a78e0eSmrg     path& operator+=(value_type __x);
301f9a78e0eSmrg #if __cplusplus >= 201402L
302b17d1066Smrg     path& operator+=(basic_string_view<value_type> __x);
303f9a78e0eSmrg #endif
304f9a78e0eSmrg 
305f9a78e0eSmrg     template<typename _Source>
306fb8a8121Smrg       __detail::_Path<_Source>&
307f9a78e0eSmrg       operator+=(_Source const& __x) { return concat(__x); }
308f9a78e0eSmrg 
309f9a78e0eSmrg     template<typename _CharT>
310fb8a8121Smrg       __detail::_Path<_CharT*, _CharT*>&
311f9a78e0eSmrg       operator+=(_CharT __x);
312f9a78e0eSmrg 
313f9a78e0eSmrg     template<typename _Source>
314fb8a8121Smrg       __detail::_Path<_Source>&
315f9a78e0eSmrg       concat(_Source const& __x)
316fb8a8121Smrg       {
317fb8a8121Smrg 	return *this += _S_convert(__detail::_S_range_begin(__x),
318fb8a8121Smrg 				   __detail::_S_range_end(__x));
319fb8a8121Smrg       }
320f9a78e0eSmrg 
321f9a78e0eSmrg     template<typename _InputIterator>
322fb8a8121Smrg       __detail::_Path<_InputIterator, _InputIterator>&
323f9a78e0eSmrg       concat(_InputIterator __first, _InputIterator __last)
324f9a78e0eSmrg       { return *this += _S_convert(__first, __last); }
325f9a78e0eSmrg 
326f9a78e0eSmrg     // modifiers
327f9a78e0eSmrg 
328f9a78e0eSmrg     void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
329f9a78e0eSmrg 
330f9a78e0eSmrg     path& make_preferred();
331f9a78e0eSmrg     path& remove_filename();
332f9a78e0eSmrg     path& replace_filename(const path& __replacement);
333f9a78e0eSmrg     path& replace_extension(const path& __replacement = path());
334f9a78e0eSmrg 
335f9a78e0eSmrg     void swap(path& __rhs) noexcept;
336f9a78e0eSmrg 
337f9a78e0eSmrg     // native format observers
338f9a78e0eSmrg 
339f9a78e0eSmrg     const string_type&  native() const noexcept { return _M_pathname; }
340f9a78e0eSmrg     const value_type*   c_str() const noexcept { return _M_pathname.c_str(); }
341f9a78e0eSmrg     operator string_type() const { return _M_pathname; }
342f9a78e0eSmrg 
343f9a78e0eSmrg     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
344f9a78e0eSmrg 	     typename _Allocator = std::allocator<_CharT>>
345f9a78e0eSmrg       std::basic_string<_CharT, _Traits, _Allocator>
346f9a78e0eSmrg       string(const _Allocator& __a = _Allocator()) const;
347f9a78e0eSmrg 
348f9a78e0eSmrg     std::string    string() const;
349f9a78e0eSmrg #if _GLIBCXX_USE_WCHAR_T
350f9a78e0eSmrg     std::wstring   wstring() const;
351f9a78e0eSmrg #endif
352181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
353181254a7Smrg     __attribute__((__abi_tag__("__u8")))
354181254a7Smrg     std::u8string  u8string() const;
355181254a7Smrg #else
356f9a78e0eSmrg     std::string    u8string() const;
357181254a7Smrg #endif // _GLIBCXX_USE_CHAR8_T
358f9a78e0eSmrg     std::u16string u16string() const;
359f9a78e0eSmrg     std::u32string u32string() const;
360f9a78e0eSmrg 
361f9a78e0eSmrg     // generic format observers
362f9a78e0eSmrg     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
363f9a78e0eSmrg 	     typename _Allocator = std::allocator<_CharT>>
364f9a78e0eSmrg       std::basic_string<_CharT, _Traits, _Allocator>
365f9a78e0eSmrg       generic_string(const _Allocator& __a = _Allocator()) const;
366f9a78e0eSmrg 
367f9a78e0eSmrg     std::string    generic_string() const;
368f9a78e0eSmrg #if _GLIBCXX_USE_WCHAR_T
369f9a78e0eSmrg     std::wstring   generic_wstring() const;
370f9a78e0eSmrg #endif
371181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
372181254a7Smrg     __attribute__((__abi_tag__("__u8")))
373181254a7Smrg     std::u8string  generic_u8string() const;
374181254a7Smrg #else
375f9a78e0eSmrg     std::string    generic_u8string() const;
376181254a7Smrg #endif // _GLIBCXX_USE_CHAR8_T
377f9a78e0eSmrg     std::u16string generic_u16string() const;
378f9a78e0eSmrg     std::u32string generic_u32string() const;
379f9a78e0eSmrg 
380f9a78e0eSmrg     // compare
381f9a78e0eSmrg 
382f9a78e0eSmrg     int compare(const path& __p) const noexcept;
383f9a78e0eSmrg     int compare(const string_type& __s) const;
384f9a78e0eSmrg     int compare(const value_type* __s) const;
385f9a78e0eSmrg #if __cplusplus >= 201402L
386b17d1066Smrg     int compare(const basic_string_view<value_type> __s) const;
387f9a78e0eSmrg #endif
388f9a78e0eSmrg 
389f9a78e0eSmrg     // decomposition
390f9a78e0eSmrg 
391f9a78e0eSmrg     path root_name() const;
392f9a78e0eSmrg     path root_directory() const;
393f9a78e0eSmrg     path root_path() const;
394f9a78e0eSmrg     path relative_path() const;
395f9a78e0eSmrg     path parent_path() const;
396f9a78e0eSmrg     path filename() const;
397f9a78e0eSmrg     path stem() const;
398f9a78e0eSmrg     path extension() const;
399f9a78e0eSmrg 
400f9a78e0eSmrg     // query
401f9a78e0eSmrg 
402181254a7Smrg     _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_pathname.empty(); }
403f9a78e0eSmrg     bool has_root_name() const;
404f9a78e0eSmrg     bool has_root_directory() const;
405f9a78e0eSmrg     bool has_root_path() const;
406f9a78e0eSmrg     bool has_relative_path() const;
407f9a78e0eSmrg     bool has_parent_path() const;
408f9a78e0eSmrg     bool has_filename() const;
409f9a78e0eSmrg     bool has_stem() const;
410f9a78e0eSmrg     bool has_extension() const;
411181254a7Smrg     bool is_absolute() const;
412f9a78e0eSmrg     bool is_relative() const { return !is_absolute(); }
413f9a78e0eSmrg 
414f9a78e0eSmrg     // iterators
415f9a78e0eSmrg     class iterator;
416f9a78e0eSmrg     typedef iterator const_iterator;
417f9a78e0eSmrg 
418b1e83836Smrg     iterator begin() const noexcept;
419b1e83836Smrg     iterator end() const noexcept;
420f9a78e0eSmrg 
421fb8a8121Smrg     /// @cond undocumented
422181254a7Smrg     // Create a basic_string by reading until a null character.
423181254a7Smrg     template<typename _InputIterator,
424181254a7Smrg 	     typename _Traits = std::iterator_traits<_InputIterator>,
425181254a7Smrg 	     typename _CharT
426181254a7Smrg 	       = typename std::remove_cv<typename _Traits::value_type>::type>
427181254a7Smrg       static std::basic_string<_CharT>
428181254a7Smrg       _S_string_from_iter(_InputIterator __source)
429181254a7Smrg       {
430181254a7Smrg 	std::basic_string<_CharT> __str;
431181254a7Smrg 	for (_CharT __ch = *__source; __ch != _CharT(); __ch = *++__source)
432181254a7Smrg 	  __str.push_back(__ch);
433181254a7Smrg 	return __str;
434181254a7Smrg       }
435fb8a8121Smrg     /// @endcond
436181254a7Smrg 
437f9a78e0eSmrg   private:
438f9a78e0eSmrg     enum class _Type : unsigned char {
439f9a78e0eSmrg 	_Multi, _Root_name, _Root_dir, _Filename
440f9a78e0eSmrg     };
441f9a78e0eSmrg 
442b1e83836Smrg     path(string_type __str, _Type __type);
443f9a78e0eSmrg 
444f9a78e0eSmrg     enum class _Split { _Stem, _Extension };
445f9a78e0eSmrg 
446f9a78e0eSmrg     path& _M_append(const string_type& __str)
447f9a78e0eSmrg     {
448f9a78e0eSmrg       if (!_M_pathname.empty() && !_S_is_dir_sep(_M_pathname.back())
449f9a78e0eSmrg 	  && !__str.empty() && !_S_is_dir_sep(__str.front()))
450f9a78e0eSmrg 	_M_pathname += preferred_separator;
451f9a78e0eSmrg       _M_pathname += __str;
452f9a78e0eSmrg       _M_split_cmpts();
453f9a78e0eSmrg       return *this;
454f9a78e0eSmrg     }
455f9a78e0eSmrg 
456f9a78e0eSmrg     pair<const string_type*, size_t> _M_find_extension() const;
457f9a78e0eSmrg 
458f9a78e0eSmrg     template<typename _CharT>
459f9a78e0eSmrg       struct _Cvt;
460f9a78e0eSmrg 
461f9a78e0eSmrg     static string_type
462a448f87cSmrg     _S_convert(value_type* __src, __detail::__nul_terminated)
463f9a78e0eSmrg     { return string_type(__src); }
464f9a78e0eSmrg 
465f9a78e0eSmrg     static string_type
466a448f87cSmrg     _S_convert(const value_type* __src, __detail::__nul_terminated)
467f9a78e0eSmrg     { return string_type(__src); }
468f9a78e0eSmrg 
469f9a78e0eSmrg     template<typename _Iter>
470f9a78e0eSmrg       static string_type
471f9a78e0eSmrg       _S_convert(_Iter __first, _Iter __last)
472f9a78e0eSmrg       {
473f9a78e0eSmrg 	using __value_type = typename std::iterator_traits<_Iter>::value_type;
474f9a78e0eSmrg 	return _Cvt<typename remove_cv<__value_type>::type>::
475f9a78e0eSmrg 	  _S_convert(__first, __last);
476f9a78e0eSmrg       }
477f9a78e0eSmrg 
478f9a78e0eSmrg     template<typename _InputIterator>
479f9a78e0eSmrg       static string_type
480a448f87cSmrg       _S_convert(_InputIterator __src, __detail::__nul_terminated)
481f9a78e0eSmrg       {
482181254a7Smrg 	auto __s = _S_string_from_iter(__src);
483181254a7Smrg 	return _S_convert(__s.c_str(), __s.c_str() + __s.size());
484f9a78e0eSmrg       }
485f9a78e0eSmrg 
486f9a78e0eSmrg     static string_type
487f9a78e0eSmrg     _S_convert_loc(const char* __first, const char* __last,
488f9a78e0eSmrg 		   const std::locale& __loc);
489f9a78e0eSmrg 
490b1e83836Smrg     static string_type
491b1e83836Smrg     _S_convert_loc(char* __first, char* __last, const std::locale& __loc)
492b1e83836Smrg     {
493b1e83836Smrg       return _S_convert_loc(const_cast<const char*>(__first),
494b1e83836Smrg 			    const_cast<const char*>(__last), __loc);
495b1e83836Smrg     }
496b1e83836Smrg 
497f9a78e0eSmrg     template<typename _Iter>
498f9a78e0eSmrg       static string_type
499f9a78e0eSmrg       _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc)
500f9a78e0eSmrg       {
501f9a78e0eSmrg 	const std::string __str(__first, __last);
502f9a78e0eSmrg 	return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc);
503f9a78e0eSmrg       }
504f9a78e0eSmrg 
505f9a78e0eSmrg     template<typename _InputIterator>
506f9a78e0eSmrg       static string_type
507a448f87cSmrg       _S_convert_loc(_InputIterator __src, __detail::__nul_terminated,
508f9a78e0eSmrg 		     const std::locale& __loc)
509f9a78e0eSmrg       {
510181254a7Smrg 	const std::string __s = _S_string_from_iter(__src);
511181254a7Smrg 	return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);
512f9a78e0eSmrg       }
513f9a78e0eSmrg 
514003ba354Smrg     static bool _S_is_dir_sep(value_type __ch)
515f9a78e0eSmrg     {
516f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
517f9a78e0eSmrg       return __ch == L'/' || __ch == preferred_separator;
518f9a78e0eSmrg #else
519f9a78e0eSmrg       return __ch == '/';
520f9a78e0eSmrg #endif
521f9a78e0eSmrg     }
522f9a78e0eSmrg 
523f9a78e0eSmrg     void _M_split_cmpts();
524f9a78e0eSmrg     void _M_trim();
525f9a78e0eSmrg     void _M_add_root_name(size_t __n);
526f9a78e0eSmrg     void _M_add_root_dir(size_t __pos);
527f9a78e0eSmrg     void _M_add_filename(size_t __pos, size_t __n);
528f9a78e0eSmrg 
529f9a78e0eSmrg     string_type _M_pathname;
530f9a78e0eSmrg 
531f9a78e0eSmrg     struct _Cmpt;
532f9a78e0eSmrg     using _List = _GLIBCXX_STD_C::vector<_Cmpt>;
533f9a78e0eSmrg     _List _M_cmpts; // empty unless _M_type == _Type::_Multi
534f9a78e0eSmrg     _Type _M_type = _Type::_Multi;
535f9a78e0eSmrg   };
536f9a78e0eSmrg 
537fb8a8121Smrg   /// @relates std::experimental::filesystem::path @{
538fb8a8121Smrg 
539fb8a8121Smrg   /// Swap overload for paths
540b1e83836Smrg #if __cpp_concepts >= 201907L
541b1e83836Smrg   // Workaround for PR libstdc++/106201
542b1e83836Smrg   inline void
543b1e83836Smrg   swap(same_as<path> auto& __lhs, same_as<path> auto& __rhs) noexcept
544b1e83836Smrg   { __lhs.swap(__rhs); }
545b1e83836Smrg #else
546f9a78e0eSmrg    inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
547b1e83836Smrg #endif
548f9a78e0eSmrg 
549fb8a8121Smrg   /// Compute a hash value for a path
550f9a78e0eSmrg   size_t hash_value(const path& __p) noexcept;
551f9a78e0eSmrg 
552f9a78e0eSmrg   /// Compare paths
553b1e83836Smrg   inline bool operator<(const path& __lhs, const path& __rhs) noexcept;
554f9a78e0eSmrg 
555f9a78e0eSmrg   /// Compare paths
556f9a78e0eSmrg   inline bool operator<=(const path& __lhs, const path& __rhs) noexcept
557f9a78e0eSmrg   { return !(__rhs < __lhs); }
558f9a78e0eSmrg 
559f9a78e0eSmrg   /// Compare paths
560f9a78e0eSmrg   inline bool operator>(const path& __lhs, const path& __rhs) noexcept
561f9a78e0eSmrg   { return __rhs < __lhs; }
562f9a78e0eSmrg 
563f9a78e0eSmrg   /// Compare paths
564f9a78e0eSmrg   inline bool operator>=(const path& __lhs, const path& __rhs) noexcept
565f9a78e0eSmrg   { return !(__lhs < __rhs); }
566f9a78e0eSmrg 
567f9a78e0eSmrg   /// Compare paths
568b1e83836Smrg   inline bool operator==(const path& __lhs, const path& __rhs) noexcept;
569f9a78e0eSmrg 
570f9a78e0eSmrg   /// Compare paths
571f9a78e0eSmrg   inline bool operator!=(const path& __lhs, const path& __rhs) noexcept
572f9a78e0eSmrg   { return !(__lhs == __rhs); }
573f9a78e0eSmrg 
574f9a78e0eSmrg   /// Append one path to another
575f9a78e0eSmrg   inline path operator/(const path& __lhs, const path& __rhs)
576b17d1066Smrg   {
577b17d1066Smrg     path __result(__lhs);
578b17d1066Smrg     __result /= __rhs;
579b17d1066Smrg     return __result;
580b17d1066Smrg   }
581f9a78e0eSmrg 
582f9a78e0eSmrg   /// Write a path to a stream
583f9a78e0eSmrg   template<typename _CharT, typename _Traits>
584f9a78e0eSmrg     basic_ostream<_CharT, _Traits>&
585f9a78e0eSmrg     operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p)
586f9a78e0eSmrg     {
587f9a78e0eSmrg       auto __tmp = __p.string<_CharT, _Traits>();
588f9a78e0eSmrg       using __quoted_string
589f9a78e0eSmrg 	= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
590181254a7Smrg       __os << __quoted_string{__tmp, _CharT('"'), _CharT('\\')};
591f9a78e0eSmrg       return __os;
592f9a78e0eSmrg     }
593f9a78e0eSmrg 
594f9a78e0eSmrg   /// Read a path from a stream
595f9a78e0eSmrg   template<typename _CharT, typename _Traits>
596f9a78e0eSmrg     basic_istream<_CharT, _Traits>&
597f9a78e0eSmrg     operator>>(basic_istream<_CharT, _Traits>& __is, path& __p)
598f9a78e0eSmrg     {
599f9a78e0eSmrg       basic_string<_CharT, _Traits> __tmp;
600f9a78e0eSmrg       using __quoted_string
601f9a78e0eSmrg 	= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
602181254a7Smrg       if (__is >> __quoted_string{ __tmp, _CharT('"'), _CharT('\\') })
603f9a78e0eSmrg 	__p = std::move(__tmp);
604f9a78e0eSmrg       return __is;
605f9a78e0eSmrg     }
606f9a78e0eSmrg 
607181254a7Smrg   /// Create a path from a UTF-8-encoded sequence of char
608fb8a8121Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
609f9a78e0eSmrg   template<typename _InputIterator>
610f9a78e0eSmrg     inline path
611fb8a8121Smrg     __u8path(_InputIterator __first, _InputIterator __last, char)
612f9a78e0eSmrg     {
613181254a7Smrg       // XXX This assumes native wide encoding is UTF-16.
614181254a7Smrg       std::codecvt_utf8_utf16<path::value_type> __cvt;
615181254a7Smrg       path::string_type __tmp;
616181254a7Smrg       const std::string __u8str{__first, __last};
617181254a7Smrg       const char* const __ptr = __u8str.data();
618181254a7Smrg       if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
619181254a7Smrg 	return path{ __tmp };
620181254a7Smrg       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
621181254a7Smrg 	    "Cannot convert character sequence",
622181254a7Smrg 	    std::make_error_code(errc::illegal_byte_sequence)));
623fb8a8121Smrg     }
624fb8a8121Smrg 
625fb8a8121Smrg #ifdef _GLIBCXX_USE_CHAR8_T
626fb8a8121Smrg   template<typename _InputIterator>
627fb8a8121Smrg     inline path
628fb8a8121Smrg     __u8path(_InputIterator __first, _InputIterator __last, char8_t)
629fb8a8121Smrg     {
630fb8a8121Smrg       return path{ __first, __last };
631fb8a8121Smrg     }
632fb8a8121Smrg #endif // _GLIBCXX_USE_CHAR8_T
633fb8a8121Smrg #endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
634fb8a8121Smrg 
635fb8a8121Smrg   template<typename _InputIterator,
636fb8a8121Smrg 	   typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
637fb8a8121Smrg 	   typename _CharT =
638fb8a8121Smrg 	     __detail::__value_type_is_char_or_char8_t<_InputIterator>>
639fb8a8121Smrg     inline path
640fb8a8121Smrg     u8path(_InputIterator __first, _InputIterator __last)
641fb8a8121Smrg     {
642fb8a8121Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
643fb8a8121Smrg       return __u8path(__first, __last, _CharT{});
644f9a78e0eSmrg #else
645f9a78e0eSmrg       return path{ __first, __last };
646f9a78e0eSmrg #endif
647f9a78e0eSmrg     }
648f9a78e0eSmrg 
649181254a7Smrg   /// Create a path from a UTF-8-encoded sequence of char
650fb8a8121Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
651fb8a8121Smrg   inline path
652fb8a8121Smrg   __u8path(const string& __s, char)
653fb8a8121Smrg   {
654fb8a8121Smrg     return filesystem::u8path(__s.data(), __s.data() + __s.size());
655fb8a8121Smrg   }
656fb8a8121Smrg 
657181254a7Smrg   template<typename _Source>
658fb8a8121Smrg     inline __enable_if_t<is_convertible<const _Source&, string>::value, path>
659fb8a8121Smrg     __u8path(const _Source& __source, char)
660fb8a8121Smrg     {
661fb8a8121Smrg       std::string __s = __source;
662fb8a8121Smrg       return filesystem::u8path(__s.data(), __s.data() + __s.size());
663fb8a8121Smrg     }
664fb8a8121Smrg 
665fb8a8121Smrg   template<typename _Source>
666fb8a8121Smrg     inline __enable_if_t<!is_convertible<const _Source&, string>::value, path>
667fb8a8121Smrg     __u8path(const _Source& __source, char)
668fb8a8121Smrg     {
669fb8a8121Smrg       std::string __s = path::_S_string_from_iter(__source);
670fb8a8121Smrg       return filesystem::u8path(__s.data(), __s.data() + __s.size());
671fb8a8121Smrg     }
672fb8a8121Smrg 
673fb8a8121Smrg #ifdef _GLIBCXX_USE_CHAR8_T
674fb8a8121Smrg   template<typename _Source>
675fb8a8121Smrg     inline path
676fb8a8121Smrg     __u8path(const _Source& __source, char8_t)
677fb8a8121Smrg     {
678fb8a8121Smrg       return path{ __source };
679fb8a8121Smrg     }
680fb8a8121Smrg #endif // _GLIBCXX_USE_CHAR8_T
681fb8a8121Smrg #endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
682fb8a8121Smrg 
683fb8a8121Smrg   template<typename _Source,
684fb8a8121Smrg 	   typename _Require = __detail::_Path<_Source>,
685fb8a8121Smrg 	   typename _CharT =
686fb8a8121Smrg 	     __detail::__value_type_is_char_or_char8_t<_Source>>
687181254a7Smrg     inline path
688181254a7Smrg     u8path(const _Source& __source)
689181254a7Smrg     {
690181254a7Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
691fb8a8121Smrg       return __u8path(__source, _CharT{});
692181254a7Smrg #else
693181254a7Smrg       return path{ __source };
694181254a7Smrg #endif
695181254a7Smrg     }
696181254a7Smrg 
697fb8a8121Smrg   /// @}
698fb8a8121Smrg 
699fb8a8121Smrg   /// Exception type thrown by the Filesystem TS library
700f9a78e0eSmrg   class filesystem_error : public std::system_error
701f9a78e0eSmrg   {
702f9a78e0eSmrg   public:
703f9a78e0eSmrg     filesystem_error(const string& __what_arg, error_code __ec)
704f9a78e0eSmrg     : system_error(__ec, __what_arg) { }
705f9a78e0eSmrg 
706f9a78e0eSmrg     filesystem_error(const string& __what_arg, const path& __p1,
707f9a78e0eSmrg 		     error_code __ec)
708f9a78e0eSmrg     : system_error(__ec, __what_arg), _M_path1(__p1) { }
709f9a78e0eSmrg 
710f9a78e0eSmrg     filesystem_error(const string& __what_arg, const path& __p1,
711f9a78e0eSmrg 		     const path& __p2, error_code __ec)
712f9a78e0eSmrg     : system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2)
713f9a78e0eSmrg     { }
714f9a78e0eSmrg 
715f9a78e0eSmrg     ~filesystem_error();
716f9a78e0eSmrg 
717f9a78e0eSmrg     const path& path1() const noexcept { return _M_path1; }
718f9a78e0eSmrg     const path& path2() const noexcept { return _M_path2; }
719f9a78e0eSmrg     const char* what() const noexcept { return _M_what.c_str(); }
720f9a78e0eSmrg 
721f9a78e0eSmrg   private:
722f9a78e0eSmrg     std::string _M_gen_what();
723f9a78e0eSmrg 
724f9a78e0eSmrg     path _M_path1;
725f9a78e0eSmrg     path _M_path2;
726f9a78e0eSmrg     std::string _M_what = _M_gen_what();
727f9a78e0eSmrg   };
728f9a78e0eSmrg 
729fb8a8121Smrg   /// @cond undocumented
730f9a78e0eSmrg   struct path::_Cmpt : path
731f9a78e0eSmrg   {
732f9a78e0eSmrg     _Cmpt(string_type __s, _Type __t, size_t __pos)
733f9a78e0eSmrg       : path(std::move(__s), __t), _M_pos(__pos) { }
734f9a78e0eSmrg 
735f9a78e0eSmrg     _Cmpt() : _M_pos(-1) { }
736f9a78e0eSmrg 
737f9a78e0eSmrg     size_t _M_pos;
738f9a78e0eSmrg   };
739f9a78e0eSmrg 
740f9a78e0eSmrg   // specialize _Cvt for degenerate 'noconv' case
741f9a78e0eSmrg   template<>
742f9a78e0eSmrg     struct path::_Cvt<path::value_type>
743f9a78e0eSmrg     {
744b1e83836Smrg       // We need this type to be defined because we don't have `if constexpr`
745b1e83836Smrg       // in C++11 and so path::string<C,T,A>(const A&) needs to be able to
746b1e83836Smrg       // declare a variable of this type and pass it to __str_codecvt_in_all.
747b1e83836Smrg       using __codecvt_utf8_to_wide = _Cvt;
748b1e83836Smrg       // Dummy overload used for unreachable calls in path::string<C,T,A>.
749b1e83836Smrg       template<typename _WStr>
750b1e83836Smrg 	friend bool
751b1e83836Smrg 	__str_codecvt_in_all(const char*, const char*,
752b1e83836Smrg 			     _WStr&, __codecvt_utf8_to_wide&) noexcept
753b1e83836Smrg 	{ return true; }
754b1e83836Smrg 
755f9a78e0eSmrg       template<typename _Iter>
756f9a78e0eSmrg 	static string_type
757f9a78e0eSmrg 	_S_convert(_Iter __first, _Iter __last)
758f9a78e0eSmrg 	{ return string_type{__first, __last}; }
759f9a78e0eSmrg     };
760f9a78e0eSmrg 
761b1e83836Smrg   // Performs conversions from _CharT to path::string_type.
762f9a78e0eSmrg   template<typename _CharT>
763f9a78e0eSmrg     struct path::_Cvt
764f9a78e0eSmrg     {
765b1e83836Smrg       // FIXME: We currently assume that the native wide encoding for wchar_t
766b1e83836Smrg       // is either UTF-32 or UTF-16 (depending on the width of wchar_t).
767b1e83836Smrg       // See comments in <bits/fs_path.h> for further details.
768b1e83836Smrg       using __codecvt_utf8_to_wchar
769b1e83836Smrg 	= __conditional_t<sizeof(wchar_t) == sizeof(char32_t),
770b1e83836Smrg 			  std::codecvt_utf8<wchar_t>,        // from UTF-32
771b1e83836Smrg 			  std::codecvt_utf8_utf16<wchar_t>>; // from UTF-16
772b1e83836Smrg 
773b1e83836Smrg       // Converts from char16_t or char32_t using std::codecvt<charNN_t, char>.
774b1e83836Smrg       // Need derived class here because std::codecvt has protected destructor.
775b1e83836Smrg       struct __codecvt_utf8_to_utfNN : std::codecvt<_CharT, char, mbstate_t>
776b1e83836Smrg       { };
777b1e83836Smrg 
778b1e83836Smrg       // Convert from native pathname format (assumed to be UTF-8 everywhere)
779b1e83836Smrg       // to the encoding implied by the wide character type _CharT.
780b1e83836Smrg       using __codecvt_utf8_to_wide
781b1e83836Smrg 	= __conditional_t<is_same<_CharT, wchar_t>::value,
782b1e83836Smrg 			  __codecvt_utf8_to_wchar,
783b1e83836Smrg 			  __codecvt_utf8_to_utfNN>;
784b1e83836Smrg 
785f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
786fb8a8121Smrg #ifdef _GLIBCXX_USE_CHAR8_T
787f9a78e0eSmrg       static string_type
788fb8a8121Smrg       _S_wconvert(const char8_t* __f, const char8_t* __l, const char8_t*)
789fb8a8121Smrg       {
790fb8a8121Smrg 	const char* __f2 = (const char*)__f;
791fb8a8121Smrg 	const char* __l2 = (const char*)__l;
792fb8a8121Smrg 	std::wstring __wstr;
793fb8a8121Smrg 	std::codecvt_utf8_utf16<wchar_t> __wcvt;
794fb8a8121Smrg 	if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
795fb8a8121Smrg 	  return __wstr;
796fb8a8121Smrg       }
797fb8a8121Smrg #endif
798fb8a8121Smrg 
799fb8a8121Smrg       static string_type
800fb8a8121Smrg       _S_wconvert(const char* __f, const char* __l, const char*)
801f9a78e0eSmrg       {
802b1e83836Smrg 	std::codecvt_utf8_utf16<wchar_t> __cvt;
803f9a78e0eSmrg 	std::wstring __wstr;
804181254a7Smrg 	if (__str_codecvt_in_all(__f, __l, __wstr, __cvt))
805f9a78e0eSmrg 	    return __wstr;
806f9a78e0eSmrg 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
807f9a78e0eSmrg 	      "Cannot convert character sequence",
808f9a78e0eSmrg 	      std::make_error_code(errc::illegal_byte_sequence)));
809f9a78e0eSmrg       }
810f9a78e0eSmrg 
811f9a78e0eSmrg       static string_type
812fb8a8121Smrg       _S_wconvert(const _CharT* __f, const _CharT* __l, const void*)
813181254a7Smrg       {
814b1e83836Smrg 	__codecvt_utf8_to_wide __cvt;
815f9a78e0eSmrg 	std::string __str;
816181254a7Smrg 	if (__str_codecvt_out_all(__f, __l, __str, __cvt))
817f9a78e0eSmrg 	  {
818f9a78e0eSmrg 	    const char* __f2 = __str.data();
819f9a78e0eSmrg 	    const char* __l2 = __f2 + __str.size();
820181254a7Smrg 	    std::codecvt_utf8_utf16<wchar_t> __wcvt;
821f9a78e0eSmrg 	    std::wstring __wstr;
822181254a7Smrg 	    if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
823f9a78e0eSmrg 	      return __wstr;
824f9a78e0eSmrg 	  }
825f9a78e0eSmrg 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
826f9a78e0eSmrg 	      "Cannot convert character sequence",
827f9a78e0eSmrg 	      std::make_error_code(errc::illegal_byte_sequence)));
828f9a78e0eSmrg       }
829f9a78e0eSmrg 
830f9a78e0eSmrg       static string_type
831f9a78e0eSmrg       _S_convert(const _CharT* __f, const _CharT* __l)
832f9a78e0eSmrg       {
833fb8a8121Smrg 	return _S_wconvert(__f, __l, (const _CharT*)nullptr);
834f9a78e0eSmrg       }
835f9a78e0eSmrg #else
836f9a78e0eSmrg       static string_type
837f9a78e0eSmrg       _S_convert(const _CharT* __f, const _CharT* __l)
838f9a78e0eSmrg       {
839181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
840181254a7Smrg 	if constexpr (is_same<_CharT, char8_t>::value)
841181254a7Smrg 	  return string_type(__f, __l);
842181254a7Smrg 	else
843181254a7Smrg #endif
844fb8a8121Smrg 	  {
845b1e83836Smrg 	    __codecvt_utf8_to_wide __cvt;
846f9a78e0eSmrg 	    std::string __str;
847181254a7Smrg 	    if (__str_codecvt_out_all(__f, __l, __str, __cvt))
848f9a78e0eSmrg 	      return __str;
849f9a78e0eSmrg 	    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
850f9a78e0eSmrg 		  "Cannot convert character sequence",
851f9a78e0eSmrg 		  std::make_error_code(errc::illegal_byte_sequence)));
852f9a78e0eSmrg 	  }
853fb8a8121Smrg       }
854f9a78e0eSmrg #endif
855f9a78e0eSmrg 
856f9a78e0eSmrg       static string_type
857f9a78e0eSmrg       _S_convert(_CharT* __f, _CharT* __l)
858f9a78e0eSmrg       {
859f9a78e0eSmrg 	return _S_convert(const_cast<const _CharT*>(__f),
860f9a78e0eSmrg 			  const_cast<const _CharT*>(__l));
861f9a78e0eSmrg       }
862f9a78e0eSmrg 
863f9a78e0eSmrg       template<typename _Iter>
864f9a78e0eSmrg 	static string_type
865f9a78e0eSmrg 	_S_convert(_Iter __first, _Iter __last)
866f9a78e0eSmrg 	{
867f9a78e0eSmrg 	  const std::basic_string<_CharT> __str(__first, __last);
868f9a78e0eSmrg 	  return _S_convert(__str.data(), __str.data() + __str.size());
869f9a78e0eSmrg 	}
870f9a78e0eSmrg 
871f9a78e0eSmrg       template<typename _Iter, typename _Cont>
872f9a78e0eSmrg 	static string_type
873f9a78e0eSmrg 	_S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first,
874f9a78e0eSmrg 		  __gnu_cxx::__normal_iterator<_Iter, _Cont> __last)
875f9a78e0eSmrg 	{ return _S_convert(__first.base(), __last.base()); }
876f9a78e0eSmrg     };
877fb8a8121Smrg   /// @endcond
878f9a78e0eSmrg 
879f9a78e0eSmrg   /// An iterator for the components of a path
880f9a78e0eSmrg   class path::iterator
881f9a78e0eSmrg   {
882f9a78e0eSmrg   public:
883f9a78e0eSmrg     using difference_type	= std::ptrdiff_t;
884f9a78e0eSmrg     using value_type		= path;
885f9a78e0eSmrg     using reference		= const path&;
886f9a78e0eSmrg     using pointer		= const path*;
887f9a78e0eSmrg     using iterator_category	= std::bidirectional_iterator_tag;
888f9a78e0eSmrg 
889b1e83836Smrg     iterator() noexcept : _M_path(nullptr), _M_cur(), _M_at_end() { }
890f9a78e0eSmrg 
891f9a78e0eSmrg     iterator(const iterator&) = default;
892f9a78e0eSmrg     iterator& operator=(const iterator&) = default;
893f9a78e0eSmrg 
894b1e83836Smrg     reference operator*() const noexcept;
895b1e83836Smrg     pointer   operator->() const noexcept { return std::__addressof(**this); }
896f9a78e0eSmrg 
897b1e83836Smrg     iterator& operator++() noexcept;
898f9a78e0eSmrg 
899b1e83836Smrg     iterator  operator++(int) noexcept
900b1e83836Smrg     { auto __tmp = *this; ++*this; return __tmp; }
901f9a78e0eSmrg 
902b1e83836Smrg     iterator& operator--() noexcept;
903b1e83836Smrg 
904b1e83836Smrg     iterator  operator--(int) noexcept
905b1e83836Smrg     { auto __tmp = *this; --*this; return __tmp; }
906b1e83836Smrg 
907b1e83836Smrg     friend bool
908b1e83836Smrg     operator==(const iterator& __lhs, const iterator& __rhs) noexcept
909f9a78e0eSmrg     { return __lhs._M_equals(__rhs); }
910f9a78e0eSmrg 
911b1e83836Smrg     friend bool
912b1e83836Smrg     operator!=(const iterator& __lhs, const iterator& __rhs) noexcept
913f9a78e0eSmrg     { return !__lhs._M_equals(__rhs); }
914f9a78e0eSmrg 
915f9a78e0eSmrg   private:
916f9a78e0eSmrg     friend class path;
917f9a78e0eSmrg 
918b1e83836Smrg     iterator(const path* __path, path::_List::const_iterator __iter) noexcept
919f9a78e0eSmrg     : _M_path(__path), _M_cur(__iter), _M_at_end()
920f9a78e0eSmrg     { }
921f9a78e0eSmrg 
922b1e83836Smrg     iterator(const path* __path, bool __at_end) noexcept
923f9a78e0eSmrg     : _M_path(__path), _M_cur(), _M_at_end(__at_end)
924f9a78e0eSmrg     { }
925f9a78e0eSmrg 
926b1e83836Smrg     bool _M_equals(iterator) const noexcept;
927f9a78e0eSmrg 
928f9a78e0eSmrg     const path* 		_M_path;
929f9a78e0eSmrg     path::_List::const_iterator _M_cur;
930f9a78e0eSmrg     bool			_M_at_end;  // only used when type != _Multi
931f9a78e0eSmrg   };
932f9a78e0eSmrg 
933b1e83836Smrg   inline
934b1e83836Smrg   path::path() noexcept = default;
935b1e83836Smrg 
936b1e83836Smrg   inline
937b1e83836Smrg   path::path(const path&) = default;
938b1e83836Smrg 
939b1e83836Smrg   inline
940b1e83836Smrg   path::path(path&& __p) noexcept
941b1e83836Smrg   : _M_pathname(std::move(__p._M_pathname)),
942b1e83836Smrg     _M_cmpts(__p._M_cmpts),
943b1e83836Smrg     _M_type(__p._M_type)
944b1e83836Smrg   { __p.clear(); }
945b1e83836Smrg 
946b1e83836Smrg   inline
947b1e83836Smrg   path::path(string_type&& __source)
948b1e83836Smrg   : _M_pathname(std::move(__source))
949b1e83836Smrg   { _M_split_cmpts(); }
950b1e83836Smrg 
951b1e83836Smrg   inline
952b1e83836Smrg   path::path(string_type __str, _Type __type)
953b1e83836Smrg   : _M_pathname(__str), _M_type(__type)
954b1e83836Smrg   {
955b1e83836Smrg     __glibcxx_assert(!empty());
956b1e83836Smrg     __glibcxx_assert(_M_type != _Type::_Multi);
957b1e83836Smrg   }
958b1e83836Smrg 
959b1e83836Smrg   inline
960b1e83836Smrg   path::~path() = default;
961b1e83836Smrg 
962b1e83836Smrg   inline path&
963b1e83836Smrg   path::operator=(const path& __p) = default;
964f9a78e0eSmrg 
965f9a78e0eSmrg   inline path&
966f9a78e0eSmrg   path::operator=(path&& __p) noexcept
967f9a78e0eSmrg   {
968f9a78e0eSmrg     _M_pathname = std::move(__p._M_pathname);
969f9a78e0eSmrg     _M_cmpts = std::move(__p._M_cmpts);
970f9a78e0eSmrg     _M_type = __p._M_type;
971f9a78e0eSmrg     __p.clear();
972f9a78e0eSmrg     return *this;
973f9a78e0eSmrg   }
974f9a78e0eSmrg 
975f9a78e0eSmrg   inline path&
976f9a78e0eSmrg   path::operator=(string_type&& __source)
977f9a78e0eSmrg   { return *this = path(std::move(__source)); }
978f9a78e0eSmrg 
979f9a78e0eSmrg   inline path&
980f9a78e0eSmrg   path::assign(string_type&& __source)
981f9a78e0eSmrg   { return *this = path(std::move(__source)); }
982f9a78e0eSmrg 
983f9a78e0eSmrg   inline path&
984f9a78e0eSmrg   path::operator+=(const path& __p)
985f9a78e0eSmrg   {
986f9a78e0eSmrg     return operator+=(__p.native());
987f9a78e0eSmrg   }
988f9a78e0eSmrg 
989f9a78e0eSmrg   inline path&
990f9a78e0eSmrg   path::operator+=(const string_type& __x)
991f9a78e0eSmrg   {
992f9a78e0eSmrg     _M_pathname += __x;
993f9a78e0eSmrg     _M_split_cmpts();
994f9a78e0eSmrg     return *this;
995f9a78e0eSmrg   }
996f9a78e0eSmrg 
997f9a78e0eSmrg   inline path&
998f9a78e0eSmrg   path::operator+=(const value_type* __x)
999f9a78e0eSmrg   {
1000f9a78e0eSmrg     _M_pathname += __x;
1001f9a78e0eSmrg     _M_split_cmpts();
1002f9a78e0eSmrg     return *this;
1003f9a78e0eSmrg   }
1004f9a78e0eSmrg 
1005f9a78e0eSmrg   inline path&
1006f9a78e0eSmrg   path::operator+=(value_type __x)
1007f9a78e0eSmrg   {
1008f9a78e0eSmrg     _M_pathname += __x;
1009f9a78e0eSmrg     _M_split_cmpts();
1010f9a78e0eSmrg     return *this;
1011f9a78e0eSmrg   }
1012f9a78e0eSmrg 
1013f9a78e0eSmrg #if __cplusplus >= 201402L
1014f9a78e0eSmrg   inline path&
1015b17d1066Smrg   path::operator+=(basic_string_view<value_type> __x)
1016f9a78e0eSmrg   {
1017f9a78e0eSmrg     _M_pathname.append(__x.data(), __x.size());
1018f9a78e0eSmrg     _M_split_cmpts();
1019f9a78e0eSmrg     return *this;
1020f9a78e0eSmrg   }
1021f9a78e0eSmrg #endif
1022f9a78e0eSmrg 
1023f9a78e0eSmrg   template<typename _CharT>
1024fb8a8121Smrg     inline __detail::_Path<_CharT*, _CharT*>&
1025f9a78e0eSmrg     path::operator+=(_CharT __x)
1026f9a78e0eSmrg     {
1027f9a78e0eSmrg       auto* __addr = std::__addressof(__x);
1028f9a78e0eSmrg       return concat(__addr, __addr + 1);
1029f9a78e0eSmrg     }
1030f9a78e0eSmrg 
1031f9a78e0eSmrg   inline path&
1032f9a78e0eSmrg   path::make_preferred()
1033f9a78e0eSmrg   {
1034f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1035f9a78e0eSmrg     std::replace(_M_pathname.begin(), _M_pathname.end(), L'/',
1036f9a78e0eSmrg 		 preferred_separator);
1037f9a78e0eSmrg #endif
1038f9a78e0eSmrg     return *this;
1039f9a78e0eSmrg   }
1040f9a78e0eSmrg 
1041f9a78e0eSmrg   inline void path::swap(path& __rhs) noexcept
1042f9a78e0eSmrg   {
1043f9a78e0eSmrg     _M_pathname.swap(__rhs._M_pathname);
1044f9a78e0eSmrg     _M_cmpts.swap(__rhs._M_cmpts);
1045f9a78e0eSmrg     std::swap(_M_type, __rhs._M_type);
1046f9a78e0eSmrg   }
1047f9a78e0eSmrg 
1048f9a78e0eSmrg   template<typename _CharT, typename _Traits, typename _Allocator>
1049f9a78e0eSmrg     inline std::basic_string<_CharT, _Traits, _Allocator>
1050f9a78e0eSmrg     path::string(const _Allocator& __a) const
1051f9a78e0eSmrg     {
1052*0a307195Smrg       if _GLIBCXX17_CONSTEXPR (is_same<_CharT, value_type>::value)
1053f9a78e0eSmrg 	return { _M_pathname.begin(), _M_pathname.end(), __a };
1054f9a78e0eSmrg 
1055181254a7Smrg       using _WString = basic_string<_CharT, _Traits, _Allocator>;
1056181254a7Smrg 
1057f9a78e0eSmrg       const value_type* __first = _M_pathname.data();
1058f9a78e0eSmrg       const value_type* __last = __first + _M_pathname.size();
1059f9a78e0eSmrg 
1060f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1061f9a78e0eSmrg       using _CharAlloc = __alloc_rebind<_Allocator, char>;
1062f9a78e0eSmrg       using _String = basic_string<char, char_traits<char>, _CharAlloc>;
1063f9a78e0eSmrg 
1064181254a7Smrg       // First convert native string from UTF-16 to to UTF-8.
1065181254a7Smrg       // XXX This assumes that the execution wide-character set is UTF-16.
1066181254a7Smrg       codecvt_utf8_utf16<value_type> __cvt;
1067f9a78e0eSmrg       _String __u8str{_CharAlloc{__a}};
1068181254a7Smrg       if (__str_codecvt_out_all(__first, __last, __u8str, __cvt))
1069f9a78e0eSmrg 	{
1070f9a78e0eSmrg 	  struct
1071f9a78e0eSmrg 	  {
1072f9a78e0eSmrg 	    const _String*
1073f9a78e0eSmrg 	    operator()(const _String& __from, _String&, true_type)
1074f9a78e0eSmrg 	    { return std::__addressof(__from); }
1075f9a78e0eSmrg 
1076f9a78e0eSmrg 	    _WString*
1077f9a78e0eSmrg 	    operator()(const _String& __from, _WString& __to, false_type)
1078f9a78e0eSmrg 	    {
1079181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1080181254a7Smrg 	      if constexpr (is_same<_CharT, char8_t>::value)
1081181254a7Smrg 	        {
1082181254a7Smrg 	          __to.assign(__from.begin(), __from.end());
1083181254a7Smrg 	          return std::__addressof(__to);
1084181254a7Smrg 	        }
1085181254a7Smrg 	      else
1086181254a7Smrg #endif
1087181254a7Smrg 	        {
1088b1e83836Smrg 		  // Convert UTF-8 to char16_t or char32_t string.
1089b1e83836Smrg 		  typename path::_Cvt<_CharT>::__codecvt_utf8_to_wide __cvt;
1090f9a78e0eSmrg 	          const char* __f = __from.data();
1091f9a78e0eSmrg 	          const char* __l = __f + __from.size();
1092181254a7Smrg 	          if (__str_codecvt_in_all(__f, __l, __to, __cvt))
1093f9a78e0eSmrg 		    return std::__addressof(__to);
1094181254a7Smrg 	        }
1095f9a78e0eSmrg 	      return nullptr;
1096f9a78e0eSmrg 	    }
1097f9a78e0eSmrg 	  } __dispatch;
1098181254a7Smrg 	  _WString __wstr(__a);
1099f9a78e0eSmrg 	  if (auto* __p = __dispatch(__u8str, __wstr, is_same<_CharT, char>{}))
1100f9a78e0eSmrg 	    return *__p;
1101f9a78e0eSmrg 	}
1102b1e83836Smrg #else // ! Windows
1103181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1104181254a7Smrg       if constexpr (is_same<_CharT, char8_t>::value)
1105181254a7Smrg           return _WString(__first, __last, __a);
1106181254a7Smrg       else
1107181254a7Smrg #endif
1108181254a7Smrg         {
1109b1e83836Smrg 	  typename path::_Cvt<_CharT>::__codecvt_utf8_to_wide __cvt;
1110181254a7Smrg           _WString __wstr(__a);
1111181254a7Smrg           if (__str_codecvt_in_all(__first, __last, __wstr, __cvt))
1112f9a78e0eSmrg 	    return __wstr;
1113181254a7Smrg         }
1114f9a78e0eSmrg #endif
1115f9a78e0eSmrg       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1116f9a78e0eSmrg 	    "Cannot convert character sequence",
1117f9a78e0eSmrg 	    std::make_error_code(errc::illegal_byte_sequence)));
1118f9a78e0eSmrg     }
1119f9a78e0eSmrg 
1120f9a78e0eSmrg   inline std::string
1121f9a78e0eSmrg   path::string() const { return string<char>(); }
1122f9a78e0eSmrg 
1123f9a78e0eSmrg #if _GLIBCXX_USE_WCHAR_T
1124f9a78e0eSmrg   inline std::wstring
1125f9a78e0eSmrg   path::wstring() const { return string<wchar_t>(); }
1126f9a78e0eSmrg #endif
1127f9a78e0eSmrg 
1128181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1129181254a7Smrg   inline std::u8string
1130181254a7Smrg   path::u8string() const { return string<char8_t>(); }
1131181254a7Smrg #else
1132f9a78e0eSmrg   inline std::string
1133f9a78e0eSmrg   path::u8string() const
1134f9a78e0eSmrg   {
1135f9a78e0eSmrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1136f9a78e0eSmrg     std::string __str;
1137181254a7Smrg     // convert from native wide encoding (assumed to be UTF-16) to UTF-8
1138181254a7Smrg     std::codecvt_utf8_utf16<value_type> __cvt;
1139f9a78e0eSmrg     const value_type* __first = _M_pathname.data();
1140f9a78e0eSmrg     const value_type* __last = __first + _M_pathname.size();
1141181254a7Smrg     if (__str_codecvt_out_all(__first, __last, __str, __cvt))
1142f9a78e0eSmrg       return __str;
1143f9a78e0eSmrg     _GLIBCXX_THROW_OR_ABORT(filesystem_error(
1144f9a78e0eSmrg 	  "Cannot convert character sequence",
1145f9a78e0eSmrg 	  std::make_error_code(errc::illegal_byte_sequence)));
1146f9a78e0eSmrg #else
1147f9a78e0eSmrg     return _M_pathname;
1148f9a78e0eSmrg #endif
1149f9a78e0eSmrg   }
1150181254a7Smrg #endif // _GLIBCXX_USE_CHAR8_T
1151f9a78e0eSmrg 
1152f9a78e0eSmrg   inline std::u16string
1153f9a78e0eSmrg   path::u16string() const { return string<char16_t>(); }
1154f9a78e0eSmrg 
1155f9a78e0eSmrg   inline std::u32string
1156f9a78e0eSmrg   path::u32string() const { return string<char32_t>(); }
1157f9a78e0eSmrg 
1158f9a78e0eSmrg   template<typename _CharT, typename _Traits, typename _Allocator>
1159f9a78e0eSmrg     inline std::basic_string<_CharT, _Traits, _Allocator>
1160f9a78e0eSmrg     path::generic_string(const _Allocator& __a) const
1161fb8a8121Smrg     {
1162fb8a8121Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1163fb8a8121Smrg       const _CharT __slash = is_same<_CharT, wchar_t>::value
1164fb8a8121Smrg 	? _CharT(L'/')
1165fb8a8121Smrg 	: _CharT('/'); // Assume value is correct for the encoding.
1166fb8a8121Smrg #else
1167fb8a8121Smrg       const _CharT __slash = _CharT('/');
1168fb8a8121Smrg #endif
1169fb8a8121Smrg       basic_string<_CharT, _Traits, _Allocator> __str(__a);
1170fb8a8121Smrg       __str.reserve(_M_pathname.size());
1171fb8a8121Smrg       bool __add_slash = false;
1172fb8a8121Smrg       for (auto& __elem : *this)
1173fb8a8121Smrg 	{
1174fb8a8121Smrg 	  if (__elem._M_type == _Type::_Root_dir)
1175fb8a8121Smrg 	    {
1176fb8a8121Smrg 	      __str += __slash;
1177fb8a8121Smrg 	      continue;
1178fb8a8121Smrg 	    }
1179fb8a8121Smrg 	  if (__add_slash)
1180fb8a8121Smrg 	    __str += __slash;
1181fb8a8121Smrg 	  __str += __elem.string<_CharT, _Traits, _Allocator>(__a);
1182fb8a8121Smrg 	  __add_slash = __elem._M_type == _Type::_Filename;
1183fb8a8121Smrg 	}
1184fb8a8121Smrg       return __str;
1185fb8a8121Smrg     }
1186f9a78e0eSmrg 
1187f9a78e0eSmrg   inline std::string
1188fb8a8121Smrg   path::generic_string() const { return generic_string<char>(); }
1189f9a78e0eSmrg 
1190f9a78e0eSmrg #if _GLIBCXX_USE_WCHAR_T
1191f9a78e0eSmrg   inline std::wstring
1192fb8a8121Smrg   path::generic_wstring() const { return generic_string<wchar_t>(); }
1193f9a78e0eSmrg #endif
1194f9a78e0eSmrg 
1195181254a7Smrg #ifdef _GLIBCXX_USE_CHAR8_T
1196181254a7Smrg   inline std::u8string
1197fb8a8121Smrg   path::generic_u8string() const { return generic_string<char8_t>(); }
1198181254a7Smrg #else
1199f9a78e0eSmrg   inline std::string
1200fb8a8121Smrg   path::generic_u8string() const { return generic_string<char>(); }
1201181254a7Smrg #endif
1202f9a78e0eSmrg 
1203f9a78e0eSmrg   inline std::u16string
1204fb8a8121Smrg   path::generic_u16string() const { return generic_string<char16_t>(); }
1205f9a78e0eSmrg 
1206f9a78e0eSmrg   inline std::u32string
1207fb8a8121Smrg   path::generic_u32string() const { return generic_string<char32_t>(); }
1208f9a78e0eSmrg 
1209f9a78e0eSmrg   inline int
1210f9a78e0eSmrg   path::compare(const string_type& __s) const { return compare(path(__s)); }
1211f9a78e0eSmrg 
1212f9a78e0eSmrg   inline int
1213f9a78e0eSmrg   path::compare(const value_type* __s) const { return compare(path(__s)); }
1214f9a78e0eSmrg 
1215f9a78e0eSmrg #if __cplusplus >= 201402L
1216f9a78e0eSmrg   inline int
1217b17d1066Smrg   path::compare(basic_string_view<value_type> __s) const
1218f9a78e0eSmrg   { return compare(path(__s)); }
1219f9a78e0eSmrg #endif
1220f9a78e0eSmrg 
1221f9a78e0eSmrg   inline path
1222f9a78e0eSmrg   path::filename() const { return empty() ? path() : *--end(); }
1223f9a78e0eSmrg 
1224f9a78e0eSmrg   inline path
1225f9a78e0eSmrg   path::stem() const
1226f9a78e0eSmrg   {
1227f9a78e0eSmrg     auto ext = _M_find_extension();
1228f9a78e0eSmrg     if (ext.first && ext.second != 0)
1229f9a78e0eSmrg       return path{ext.first->substr(0, ext.second)};
1230f9a78e0eSmrg     return {};
1231f9a78e0eSmrg   }
1232f9a78e0eSmrg 
1233f9a78e0eSmrg   inline path
1234f9a78e0eSmrg   path::extension() const
1235f9a78e0eSmrg   {
1236f9a78e0eSmrg     auto ext = _M_find_extension();
1237f9a78e0eSmrg     if (ext.first && ext.second != string_type::npos)
1238f9a78e0eSmrg       return path{ext.first->substr(ext.second)};
1239f9a78e0eSmrg     return {};
1240f9a78e0eSmrg   }
1241f9a78e0eSmrg 
1242f9a78e0eSmrg   inline bool
1243f9a78e0eSmrg   path::has_stem() const
1244f9a78e0eSmrg   {
1245f9a78e0eSmrg     auto ext = _M_find_extension();
1246f9a78e0eSmrg     return ext.first && ext.second != 0;
1247f9a78e0eSmrg   }
1248f9a78e0eSmrg 
1249f9a78e0eSmrg   inline bool
1250f9a78e0eSmrg   path::has_extension() const
1251f9a78e0eSmrg   {
1252f9a78e0eSmrg     auto ext = _M_find_extension();
1253f9a78e0eSmrg     return ext.first && ext.second != string_type::npos;
1254f9a78e0eSmrg   }
1255f9a78e0eSmrg 
1256181254a7Smrg   inline bool
1257181254a7Smrg   path::is_absolute() const
1258181254a7Smrg   {
1259181254a7Smrg #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1260181254a7Smrg     return has_root_name() && has_root_directory();
1261181254a7Smrg #else
1262181254a7Smrg     return has_root_directory();
1263181254a7Smrg #endif
1264181254a7Smrg   }
1265181254a7Smrg 
1266f9a78e0eSmrg   inline path::iterator
1267b1e83836Smrg   path::begin() const noexcept
1268f9a78e0eSmrg   {
1269f9a78e0eSmrg     if (_M_type == _Type::_Multi)
1270f9a78e0eSmrg       return iterator(this, _M_cmpts.begin());
1271f9a78e0eSmrg     return iterator(this, false);
1272f9a78e0eSmrg   }
1273f9a78e0eSmrg 
1274f9a78e0eSmrg   inline path::iterator
1275b1e83836Smrg   path::end() const noexcept
1276f9a78e0eSmrg   {
1277f9a78e0eSmrg     if (_M_type == _Type::_Multi)
1278f9a78e0eSmrg       return iterator(this, _M_cmpts.end());
1279f9a78e0eSmrg     return iterator(this, true);
1280f9a78e0eSmrg   }
1281f9a78e0eSmrg 
1282f9a78e0eSmrg   inline path::iterator&
1283b1e83836Smrg   path::iterator::operator++() noexcept
1284f9a78e0eSmrg   {
1285f9a78e0eSmrg     __glibcxx_assert(_M_path != nullptr);
1286f9a78e0eSmrg     if (_M_path->_M_type == _Type::_Multi)
1287f9a78e0eSmrg       {
1288f9a78e0eSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1289f9a78e0eSmrg 	++_M_cur;
1290f9a78e0eSmrg       }
1291f9a78e0eSmrg     else
1292f9a78e0eSmrg       {
1293f9a78e0eSmrg 	__glibcxx_assert(!_M_at_end);
1294f9a78e0eSmrg 	_M_at_end = true;
1295f9a78e0eSmrg       }
1296f9a78e0eSmrg     return *this;
1297f9a78e0eSmrg   }
1298f9a78e0eSmrg 
1299f9a78e0eSmrg   inline path::iterator&
1300b1e83836Smrg   path::iterator::operator--() noexcept
1301f9a78e0eSmrg   {
1302f9a78e0eSmrg     __glibcxx_assert(_M_path != nullptr);
1303f9a78e0eSmrg     if (_M_path->_M_type == _Type::_Multi)
1304f9a78e0eSmrg       {
1305f9a78e0eSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
1306f9a78e0eSmrg 	--_M_cur;
1307f9a78e0eSmrg       }
1308f9a78e0eSmrg     else
1309f9a78e0eSmrg       {
1310f9a78e0eSmrg 	__glibcxx_assert(_M_at_end);
1311f9a78e0eSmrg 	_M_at_end = false;
1312f9a78e0eSmrg       }
1313f9a78e0eSmrg     return *this;
1314f9a78e0eSmrg   }
1315f9a78e0eSmrg 
1316f9a78e0eSmrg   inline path::iterator::reference
1317b1e83836Smrg   path::iterator::operator*() const noexcept
1318f9a78e0eSmrg   {
1319f9a78e0eSmrg     __glibcxx_assert(_M_path != nullptr);
1320f9a78e0eSmrg     if (_M_path->_M_type == _Type::_Multi)
1321f9a78e0eSmrg       {
1322f9a78e0eSmrg 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
1323f9a78e0eSmrg 	return *_M_cur;
1324f9a78e0eSmrg       }
1325f9a78e0eSmrg     return *_M_path;
1326f9a78e0eSmrg   }
1327f9a78e0eSmrg 
1328f9a78e0eSmrg   inline bool
1329b1e83836Smrg   path::iterator::_M_equals(iterator __rhs) const noexcept
1330f9a78e0eSmrg   {
1331f9a78e0eSmrg     if (_M_path != __rhs._M_path)
1332f9a78e0eSmrg       return false;
1333f9a78e0eSmrg     if (_M_path == nullptr)
1334f9a78e0eSmrg       return true;
1335f9a78e0eSmrg     if (_M_path->_M_type == path::_Type::_Multi)
1336f9a78e0eSmrg       return _M_cur == __rhs._M_cur;
1337f9a78e0eSmrg     return _M_at_end == __rhs._M_at_end;
1338f9a78e0eSmrg   }
1339f9a78e0eSmrg 
1340b1e83836Smrg   // Define these now that path and path::iterator are complete.
1341b1e83836Smrg   // They needs to consider the string_view(Range&&) constructor during
1342b1e83836Smrg   // overload resolution, which depends on whether range<path> is satisfied,
1343b1e83836Smrg   // which depends on whether path::iterator is complete.
1344b1e83836Smrg   inline bool operator<(const path& __lhs, const path& __rhs) noexcept
1345b1e83836Smrg   { return __lhs.compare(__rhs) < 0; }
1346b1e83836Smrg 
1347b1e83836Smrg   inline bool operator==(const path& __lhs, const path& __rhs) noexcept
1348b1e83836Smrg   { return __lhs.compare(__rhs) == 0; }
1349b1e83836Smrg 
1350a448f87cSmrg   /// @} group filesystem-ts
1351f9a78e0eSmrg _GLIBCXX_END_NAMESPACE_CXX11
1352f9a78e0eSmrg } // namespace v1
1353f9a78e0eSmrg } // namespace filesystem
1354f9a78e0eSmrg } // namespace experimental
1355a3e9eb18Smrg 
1356a3e9eb18Smrg _GLIBCXX_END_NAMESPACE_VERSION
1357f9a78e0eSmrg } // namespace std
1358f9a78e0eSmrg 
1359f9a78e0eSmrg #endif // C++11
1360f9a78e0eSmrg 
1361f9a78e0eSmrg #endif // _GLIBCXX_EXPERIMENTAL_FS_PATH_H
1362