xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/fs_path.h (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj // Class filesystem::path -*- C++ -*-
238fd1498Szrj 
338fd1498Szrj // Copyright (C) 2014-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj 
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj 
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj 
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj 
2538fd1498Szrj /** @file include/bits/fs_path.h
2638fd1498Szrj  *  This is an internal header file, included by other library headers.
2738fd1498Szrj  *  Do not attempt to use it directly. @headername{filesystem}
2838fd1498Szrj  */
2938fd1498Szrj 
3038fd1498Szrj #ifndef _GLIBCXX_FS_PATH_H
3138fd1498Szrj #define _GLIBCXX_FS_PATH_H 1
3238fd1498Szrj 
3338fd1498Szrj #if __cplusplus >= 201703L
3438fd1498Szrj 
3538fd1498Szrj #include <utility>
3638fd1498Szrj #include <type_traits>
3738fd1498Szrj #include <vector>
3838fd1498Szrj #include <locale>
3938fd1498Szrj #include <iosfwd>
4038fd1498Szrj #include <codecvt>
4138fd1498Szrj #include <string_view>
4238fd1498Szrj #include <system_error>
4338fd1498Szrj #include <bits/stl_algobase.h>
4438fd1498Szrj #include <bits/quoted_string.h>
4538fd1498Szrj #include <bits/locale_conv.h>
4638fd1498Szrj 
4738fd1498Szrj #if defined(_WIN32) && !defined(__CYGWIN__)
4838fd1498Szrj # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1
4938fd1498Szrj # include <algorithm>
5038fd1498Szrj #endif
5138fd1498Szrj 
_GLIBCXX_VISIBILITY(default)5238fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
5338fd1498Szrj {
5438fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
5538fd1498Szrj 
5638fd1498Szrj namespace filesystem
5738fd1498Szrj {
5838fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_CXX11
5938fd1498Szrj 
6038fd1498Szrj   /**
6138fd1498Szrj    * @ingroup filesystem
6238fd1498Szrj    * @{
6338fd1498Szrj    */
6438fd1498Szrj 
6538fd1498Szrj   /// A filesystem path.
6638fd1498Szrj   class path
6738fd1498Szrj   {
6838fd1498Szrj     template<typename _CharT>
6938fd1498Szrj       struct __is_encoded_char : std::false_type { };
7038fd1498Szrj 
7138fd1498Szrj     template<typename _Iter,
7238fd1498Szrj 	     typename _Iter_traits = std::iterator_traits<_Iter>>
7338fd1498Szrj       using __is_path_iter_src
7438fd1498Szrj 	= __and_<__is_encoded_char<typename _Iter_traits::value_type>,
7538fd1498Szrj 		 std::is_base_of<std::input_iterator_tag,
7638fd1498Szrj 				 typename _Iter_traits::iterator_category>>;
7738fd1498Szrj 
7838fd1498Szrj     template<typename _Iter>
7938fd1498Szrj       static __is_path_iter_src<_Iter>
8038fd1498Szrj       __is_path_src(_Iter, int);
8138fd1498Szrj 
8238fd1498Szrj     template<typename _CharT, typename _Traits, typename _Alloc>
8338fd1498Szrj       static __is_encoded_char<_CharT>
8438fd1498Szrj       __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
8538fd1498Szrj 
8638fd1498Szrj     template<typename _CharT, typename _Traits>
8738fd1498Szrj       static __is_encoded_char<_CharT>
8838fd1498Szrj       __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
8938fd1498Szrj 
9038fd1498Szrj     template<typename _Unknown>
9138fd1498Szrj       static std::false_type
9238fd1498Szrj       __is_path_src(const _Unknown&, ...);
9338fd1498Szrj 
9438fd1498Szrj     template<typename _Tp1, typename _Tp2>
9538fd1498Szrj       struct __constructible_from;
9638fd1498Szrj 
9738fd1498Szrj     template<typename _Iter>
9838fd1498Szrj       struct __constructible_from<_Iter, _Iter>
9938fd1498Szrj       : __is_path_iter_src<_Iter>
10038fd1498Szrj       { };
10138fd1498Szrj 
10238fd1498Szrj     template<typename _Source>
10338fd1498Szrj       struct __constructible_from<_Source, void>
10438fd1498Szrj       : decltype(__is_path_src(std::declval<_Source>(), 0))
10538fd1498Szrj       { };
10638fd1498Szrj 
10738fd1498Szrj     template<typename _Tp1, typename _Tp2 = void>
10838fd1498Szrj       using _Path = typename
109*58e805e6Szrj 	std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
110*58e805e6Szrj 			      __not_<is_void<_Tp1>>,
11138fd1498Szrj 			      __constructible_from<_Tp1, _Tp2>>::value,
11238fd1498Szrj 		       path>::type;
11338fd1498Szrj 
11438fd1498Szrj     template<typename _Source>
11538fd1498Szrj       static _Source
11638fd1498Szrj       _S_range_begin(_Source __begin) { return __begin; }
11738fd1498Szrj 
11838fd1498Szrj     struct __null_terminated { };
11938fd1498Szrj 
12038fd1498Szrj     template<typename _Source>
12138fd1498Szrj       static __null_terminated
12238fd1498Szrj       _S_range_end(_Source) { return {}; }
12338fd1498Szrj 
12438fd1498Szrj     template<typename _CharT, typename _Traits, typename _Alloc>
12538fd1498Szrj       static const _CharT*
12638fd1498Szrj       _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
12738fd1498Szrj       { return __str.data(); }
12838fd1498Szrj 
12938fd1498Szrj     template<typename _CharT, typename _Traits, typename _Alloc>
13038fd1498Szrj       static const _CharT*
13138fd1498Szrj       _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
13238fd1498Szrj       { return __str.data() + __str.size(); }
13338fd1498Szrj 
13438fd1498Szrj     template<typename _CharT, typename _Traits>
13538fd1498Szrj       static const _CharT*
13638fd1498Szrj       _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
13738fd1498Szrj       { return __str.data(); }
13838fd1498Szrj 
13938fd1498Szrj     template<typename _CharT, typename _Traits>
14038fd1498Szrj       static const _CharT*
14138fd1498Szrj       _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
14238fd1498Szrj       { return __str.data() + __str.size(); }
14338fd1498Szrj 
14438fd1498Szrj     template<typename _Tp,
14538fd1498Szrj 	     typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
14638fd1498Szrj 	     typename _Val = typename std::iterator_traits<_Iter>::value_type>
14738fd1498Szrj       using __value_type_is_char
14838fd1498Szrj 	= typename std::enable_if<std::is_same<_Val, char>::value>::type;
14938fd1498Szrj 
15038fd1498Szrj   public:
15138fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
15238fd1498Szrj     typedef wchar_t				value_type;
15338fd1498Szrj     static constexpr value_type			preferred_separator = L'\\';
15438fd1498Szrj #else
15538fd1498Szrj     typedef char				value_type;
15638fd1498Szrj     static constexpr value_type			preferred_separator = '/';
15738fd1498Szrj #endif
15838fd1498Szrj     typedef std::basic_string<value_type>	string_type;
15938fd1498Szrj 
16038fd1498Szrj     enum format { native_format, generic_format, auto_format };
16138fd1498Szrj 
16238fd1498Szrj     // constructors and destructor
16338fd1498Szrj 
16438fd1498Szrj     path() noexcept { }
16538fd1498Szrj 
16638fd1498Szrj     path(const path& __p) = default;
16738fd1498Szrj 
16838fd1498Szrj     path(path&& __p) noexcept
16938fd1498Szrj     : _M_pathname(std::move(__p._M_pathname)), _M_type(__p._M_type)
17038fd1498Szrj     {
17138fd1498Szrj       _M_split_cmpts();
17238fd1498Szrj       __p.clear();
17338fd1498Szrj     }
17438fd1498Szrj 
17538fd1498Szrj     path(string_type&& __source, format = auto_format)
17638fd1498Szrj     : _M_pathname(std::move(__source))
17738fd1498Szrj     { _M_split_cmpts(); }
17838fd1498Szrj 
17938fd1498Szrj     template<typename _Source,
18038fd1498Szrj 	     typename _Require = _Path<_Source>>
18138fd1498Szrj       path(_Source const& __source, format = auto_format)
18238fd1498Szrj       : _M_pathname(_S_convert(_S_range_begin(__source),
18338fd1498Szrj 			       _S_range_end(__source)))
18438fd1498Szrj       { _M_split_cmpts(); }
18538fd1498Szrj 
18638fd1498Szrj     template<typename _InputIterator,
18738fd1498Szrj 	     typename _Require = _Path<_InputIterator, _InputIterator>>
18838fd1498Szrj       path(_InputIterator __first, _InputIterator __last, format = auto_format)
18938fd1498Szrj       : _M_pathname(_S_convert(__first, __last))
19038fd1498Szrj       { _M_split_cmpts(); }
19138fd1498Szrj 
19238fd1498Szrj     template<typename _Source,
19338fd1498Szrj 	     typename _Require = _Path<_Source>,
19438fd1498Szrj 	     typename _Require2 = __value_type_is_char<_Source>>
19538fd1498Szrj       path(_Source const& __source, const locale& __loc, format = auto_format)
19638fd1498Szrj       : _M_pathname(_S_convert_loc(_S_range_begin(__source),
19738fd1498Szrj 				   _S_range_end(__source), __loc))
19838fd1498Szrj       { _M_split_cmpts(); }
19938fd1498Szrj 
20038fd1498Szrj     template<typename _InputIterator,
20138fd1498Szrj 	     typename _Require = _Path<_InputIterator, _InputIterator>,
20238fd1498Szrj 	     typename _Require2 = __value_type_is_char<_InputIterator>>
20338fd1498Szrj       path(_InputIterator __first, _InputIterator __last, const locale& __loc,
20438fd1498Szrj 	   format = auto_format)
20538fd1498Szrj       : _M_pathname(_S_convert_loc(__first, __last, __loc))
20638fd1498Szrj       { _M_split_cmpts(); }
20738fd1498Szrj 
20838fd1498Szrj     ~path() = default;
20938fd1498Szrj 
21038fd1498Szrj     // assignments
21138fd1498Szrj 
21238fd1498Szrj     path& operator=(const path& __p) = default;
21338fd1498Szrj     path& operator=(path&& __p) noexcept;
21438fd1498Szrj     path& operator=(string_type&& __source);
21538fd1498Szrj     path& assign(string_type&& __source);
21638fd1498Szrj 
21738fd1498Szrj     template<typename _Source>
21838fd1498Szrj       _Path<_Source>&
21938fd1498Szrj       operator=(_Source const& __source)
22038fd1498Szrj       { return *this = path(__source); }
22138fd1498Szrj 
22238fd1498Szrj     template<typename _Source>
22338fd1498Szrj       _Path<_Source>&
22438fd1498Szrj       assign(_Source const& __source)
22538fd1498Szrj       { return *this = path(__source); }
22638fd1498Szrj 
22738fd1498Szrj     template<typename _InputIterator>
22838fd1498Szrj       _Path<_InputIterator, _InputIterator>&
22938fd1498Szrj       assign(_InputIterator __first, _InputIterator __last)
23038fd1498Szrj       { return *this = path(__first, __last); }
23138fd1498Szrj 
23238fd1498Szrj     // appends
23338fd1498Szrj 
23438fd1498Szrj     path& operator/=(const path& __p)
23538fd1498Szrj     {
23638fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
23738fd1498Szrj       if (__p.is_absolute()
23838fd1498Szrj 	  || (__p.has_root_name() && __p.root_name() != root_name()))
23938fd1498Szrj 	operator=(__p);
24038fd1498Szrj       else
24138fd1498Szrj 	{
24238fd1498Szrj 	  string_type __pathname;
24338fd1498Szrj 	  if (__p.has_root_directory())
24438fd1498Szrj 	    __pathname = root_name().native();
24538fd1498Szrj 	  else if (has_filename() || (!has_root_directory() && is_absolute()))
24638fd1498Szrj 	    __pathname = _M_pathname + preferred_separator;
24738fd1498Szrj 	  __pathname += __p.relative_path().native(); // XXX is this right?
24838fd1498Szrj 	  _M_pathname.swap(__pathname);
24938fd1498Szrj 	  _M_split_cmpts();
25038fd1498Szrj 	}
25138fd1498Szrj #else
25238fd1498Szrj       // Much simpler, as any path with root-name or root-dir is absolute.
25338fd1498Szrj       if (__p.is_absolute())
25438fd1498Szrj 	operator=(__p);
25538fd1498Szrj       else
25638fd1498Szrj 	{
25738fd1498Szrj 	  if (has_filename() || (_M_type == _Type::_Root_name))
25838fd1498Szrj 	    _M_pathname += preferred_separator;
25938fd1498Szrj 	  _M_pathname += __p.native();
26038fd1498Szrj 	  _M_split_cmpts();
26138fd1498Szrj 	}
26238fd1498Szrj #endif
26338fd1498Szrj       return *this;
26438fd1498Szrj     }
26538fd1498Szrj 
26638fd1498Szrj     template <class _Source>
26738fd1498Szrj       _Path<_Source>&
26838fd1498Szrj       operator/=(_Source const& __source)
269*58e805e6Szrj       { return _M_append(path(__source)); }
27038fd1498Szrj 
27138fd1498Szrj     template<typename _Source>
27238fd1498Szrj       _Path<_Source>&
27338fd1498Szrj       append(_Source const& __source)
274*58e805e6Szrj       { return _M_append(path(__source)); }
27538fd1498Szrj 
27638fd1498Szrj     template<typename _InputIterator>
27738fd1498Szrj       _Path<_InputIterator, _InputIterator>&
27838fd1498Szrj       append(_InputIterator __first, _InputIterator __last)
279*58e805e6Szrj       { return _M_append(path(__first, __last)); }
28038fd1498Szrj 
28138fd1498Szrj     // concatenation
28238fd1498Szrj 
28338fd1498Szrj     path& operator+=(const path& __x);
28438fd1498Szrj     path& operator+=(const string_type& __x);
28538fd1498Szrj     path& operator+=(const value_type* __x);
28638fd1498Szrj     path& operator+=(value_type __x);
28738fd1498Szrj     path& operator+=(basic_string_view<value_type> __x);
28838fd1498Szrj 
28938fd1498Szrj     template<typename _Source>
29038fd1498Szrj       _Path<_Source>&
29138fd1498Szrj       operator+=(_Source const& __x) { return concat(__x); }
29238fd1498Szrj 
29338fd1498Szrj     template<typename _CharT>
29438fd1498Szrj       _Path<_CharT*, _CharT*>&
29538fd1498Szrj       operator+=(_CharT __x);
29638fd1498Szrj 
29738fd1498Szrj     template<typename _Source>
29838fd1498Szrj       _Path<_Source>&
29938fd1498Szrj       concat(_Source const& __x)
30038fd1498Szrj       { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); }
30138fd1498Szrj 
30238fd1498Szrj     template<typename _InputIterator>
30338fd1498Szrj       _Path<_InputIterator, _InputIterator>&
30438fd1498Szrj       concat(_InputIterator __first, _InputIterator __last)
30538fd1498Szrj       { return *this += _S_convert(__first, __last); }
30638fd1498Szrj 
30738fd1498Szrj     // modifiers
30838fd1498Szrj 
30938fd1498Szrj     void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
31038fd1498Szrj 
31138fd1498Szrj     path& make_preferred();
31238fd1498Szrj     path& remove_filename();
31338fd1498Szrj     path& replace_filename(const path& __replacement);
31438fd1498Szrj     path& replace_extension(const path& __replacement = path());
31538fd1498Szrj 
31638fd1498Szrj     void swap(path& __rhs) noexcept;
31738fd1498Szrj 
31838fd1498Szrj     // native format observers
31938fd1498Szrj 
32038fd1498Szrj     const string_type&  native() const noexcept { return _M_pathname; }
32138fd1498Szrj     const value_type*   c_str() const noexcept { return _M_pathname.c_str(); }
32238fd1498Szrj     operator string_type() const { return _M_pathname; }
32338fd1498Szrj 
32438fd1498Szrj     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
32538fd1498Szrj 	     typename _Allocator = std::allocator<_CharT>>
32638fd1498Szrj       std::basic_string<_CharT, _Traits, _Allocator>
32738fd1498Szrj       string(const _Allocator& __a = _Allocator()) const;
32838fd1498Szrj 
32938fd1498Szrj     std::string    string() const;
33038fd1498Szrj #if _GLIBCXX_USE_WCHAR_T
33138fd1498Szrj     std::wstring   wstring() const;
33238fd1498Szrj #endif
33338fd1498Szrj     std::string    u8string() const;
33438fd1498Szrj     std::u16string u16string() const;
33538fd1498Szrj     std::u32string u32string() const;
33638fd1498Szrj 
33738fd1498Szrj     // generic format observers
33838fd1498Szrj     template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
33938fd1498Szrj 	     typename _Allocator = std::allocator<_CharT>>
34038fd1498Szrj       std::basic_string<_CharT, _Traits, _Allocator>
34138fd1498Szrj       generic_string(const _Allocator& __a = _Allocator()) const;
34238fd1498Szrj 
34338fd1498Szrj     std::string    generic_string() const;
34438fd1498Szrj #if _GLIBCXX_USE_WCHAR_T
34538fd1498Szrj     std::wstring   generic_wstring() const;
34638fd1498Szrj #endif
34738fd1498Szrj     std::string    generic_u8string() const;
34838fd1498Szrj     std::u16string generic_u16string() const;
34938fd1498Szrj     std::u32string generic_u32string() const;
35038fd1498Szrj 
35138fd1498Szrj     // compare
35238fd1498Szrj 
35338fd1498Szrj     int compare(const path& __p) const noexcept;
35438fd1498Szrj     int compare(const string_type& __s) const;
35538fd1498Szrj     int compare(const value_type* __s) const;
35638fd1498Szrj     int compare(const basic_string_view<value_type> __s) const;
35738fd1498Szrj 
35838fd1498Szrj     // decomposition
35938fd1498Szrj 
36038fd1498Szrj     path root_name() const;
36138fd1498Szrj     path root_directory() const;
36238fd1498Szrj     path root_path() const;
36338fd1498Szrj     path relative_path() const;
36438fd1498Szrj     path parent_path() const;
36538fd1498Szrj     path filename() const;
36638fd1498Szrj     path stem() const;
36738fd1498Szrj     path extension() const;
36838fd1498Szrj 
36938fd1498Szrj     // query
37038fd1498Szrj 
37138fd1498Szrj     [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); }
37238fd1498Szrj     bool has_root_name() const;
37338fd1498Szrj     bool has_root_directory() const;
37438fd1498Szrj     bool has_root_path() const;
37538fd1498Szrj     bool has_relative_path() const;
37638fd1498Szrj     bool has_parent_path() const;
37738fd1498Szrj     bool has_filename() const;
37838fd1498Szrj     bool has_stem() const;
37938fd1498Szrj     bool has_extension() const;
380*58e805e6Szrj     bool is_absolute() const { return has_root_directory(); }
38138fd1498Szrj     bool is_relative() const { return !is_absolute(); }
38238fd1498Szrj 
38338fd1498Szrj     // generation
38438fd1498Szrj     path lexically_normal() const;
38538fd1498Szrj     path lexically_relative(const path& base) const;
38638fd1498Szrj     path lexically_proximate(const path& base) const;
38738fd1498Szrj 
38838fd1498Szrj     // iterators
38938fd1498Szrj     class iterator;
39038fd1498Szrj     typedef iterator const_iterator;
39138fd1498Szrj 
39238fd1498Szrj     iterator begin() const;
39338fd1498Szrj     iterator end() const;
39438fd1498Szrj 
39538fd1498Szrj   private:
39638fd1498Szrj     enum class _Type : unsigned char {
39738fd1498Szrj 	_Multi, _Root_name, _Root_dir, _Filename
39838fd1498Szrj     };
39938fd1498Szrj 
40038fd1498Szrj     path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type)
40138fd1498Szrj     {
40238fd1498Szrj       __glibcxx_assert(_M_type != _Type::_Multi);
40338fd1498Szrj     }
40438fd1498Szrj 
40538fd1498Szrj     enum class _Split { _Stem, _Extension };
40638fd1498Szrj 
407*58e805e6Szrj     path&
408*58e805e6Szrj     _M_append(path __p)
40938fd1498Szrj     {
410*58e805e6Szrj       if (__p.is_absolute())
411*58e805e6Szrj 	operator=(std::move(__p));
41238fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
413*58e805e6Szrj       else if (__p.has_root_name() && __p.root_name() != root_name())
414*58e805e6Szrj 	operator=(std::move(__p));
41538fd1498Szrj #endif
416*58e805e6Szrj       else
417*58e805e6Szrj 	operator/=(const_cast<const path&>(__p));
41838fd1498Szrj       return *this;
41938fd1498Szrj     }
42038fd1498Szrj 
42138fd1498Szrj     pair<const string_type*, size_t> _M_find_extension() const;
42238fd1498Szrj 
42338fd1498Szrj     template<typename _CharT>
42438fd1498Szrj       struct _Cvt;
42538fd1498Szrj 
42638fd1498Szrj     static string_type
42738fd1498Szrj     _S_convert(value_type* __src, __null_terminated)
42838fd1498Szrj     { return string_type(__src); }
42938fd1498Szrj 
43038fd1498Szrj     static string_type
43138fd1498Szrj     _S_convert(const value_type* __src, __null_terminated)
43238fd1498Szrj     { return string_type(__src); }
43338fd1498Szrj 
43438fd1498Szrj     template<typename _Iter>
43538fd1498Szrj       static string_type
43638fd1498Szrj       _S_convert(_Iter __first, _Iter __last)
43738fd1498Szrj       {
43838fd1498Szrj 	using __value_type = typename std::iterator_traits<_Iter>::value_type;
43938fd1498Szrj 	return _Cvt<typename remove_cv<__value_type>::type>::
44038fd1498Szrj 	  _S_convert(__first, __last);
44138fd1498Szrj       }
44238fd1498Szrj 
44338fd1498Szrj     template<typename _InputIterator>
44438fd1498Szrj       static string_type
44538fd1498Szrj       _S_convert(_InputIterator __src, __null_terminated)
44638fd1498Szrj       {
44738fd1498Szrj 	using _Tp = typename std::iterator_traits<_InputIterator>::value_type;
44838fd1498Szrj 	std::basic_string<typename remove_cv<_Tp>::type> __tmp;
44938fd1498Szrj 	for (; *__src != _Tp{}; ++__src)
45038fd1498Szrj 	  __tmp.push_back(*__src);
45138fd1498Szrj 	return _S_convert(__tmp.c_str(), __tmp.c_str() + __tmp.size());
45238fd1498Szrj       }
45338fd1498Szrj 
45438fd1498Szrj     static string_type
45538fd1498Szrj     _S_convert_loc(const char* __first, const char* __last,
45638fd1498Szrj 		   const std::locale& __loc);
45738fd1498Szrj 
45838fd1498Szrj     template<typename _Iter>
45938fd1498Szrj       static string_type
46038fd1498Szrj       _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc)
46138fd1498Szrj       {
46238fd1498Szrj 	const std::string __str(__first, __last);
46338fd1498Szrj 	return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc);
46438fd1498Szrj       }
46538fd1498Szrj 
46638fd1498Szrj     template<typename _InputIterator>
46738fd1498Szrj       static string_type
46838fd1498Szrj       _S_convert_loc(_InputIterator __src, __null_terminated,
46938fd1498Szrj 		     const std::locale& __loc)
47038fd1498Szrj       {
47138fd1498Szrj 	std::string __tmp;
47238fd1498Szrj 	while (*__src != '\0')
47338fd1498Szrj 	  __tmp.push_back(*__src++);
47438fd1498Szrj 	return _S_convert_loc(__tmp.data(), __tmp.data()+__tmp.size(), __loc);
47538fd1498Szrj       }
47638fd1498Szrj 
47738fd1498Szrj     template<typename _CharT, typename _Traits, typename _Allocator>
47838fd1498Szrj       static basic_string<_CharT, _Traits, _Allocator>
47938fd1498Szrj       _S_str_convert(const string_type&, const _Allocator& __a);
48038fd1498Szrj 
48138fd1498Szrj     bool _S_is_dir_sep(value_type __ch)
48238fd1498Szrj     {
48338fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
48438fd1498Szrj       return __ch == L'/' || __ch == preferred_separator;
48538fd1498Szrj #else
48638fd1498Szrj       return __ch == '/';
48738fd1498Szrj #endif
48838fd1498Szrj     }
48938fd1498Szrj 
49038fd1498Szrj     void _M_split_cmpts();
49138fd1498Szrj     void _M_trim();
49238fd1498Szrj     void _M_add_root_name(size_t __n);
49338fd1498Szrj     void _M_add_root_dir(size_t __pos);
49438fd1498Szrj     void _M_add_filename(size_t __pos, size_t __n);
49538fd1498Szrj 
49638fd1498Szrj     string_type _M_pathname;
49738fd1498Szrj 
49838fd1498Szrj     struct _Cmpt;
49938fd1498Szrj     using _List = _GLIBCXX_STD_C::vector<_Cmpt>;
50038fd1498Szrj     _List _M_cmpts; // empty unless _M_type == _Type::_Multi
501*58e805e6Szrj     _Type _M_type = _Type::_Filename;
50238fd1498Szrj   };
50338fd1498Szrj 
50438fd1498Szrj   template<>
50538fd1498Szrj     struct path::__is_encoded_char<char> : std::true_type
50638fd1498Szrj     { using value_type = char; };
50738fd1498Szrj 
50838fd1498Szrj   template<>
50938fd1498Szrj     struct path::__is_encoded_char<wchar_t> : std::true_type
51038fd1498Szrj     { using value_type = wchar_t; };
51138fd1498Szrj 
51238fd1498Szrj   template<>
51338fd1498Szrj     struct path::__is_encoded_char<char16_t> : std::true_type
51438fd1498Szrj     { using value_type = char16_t; };
51538fd1498Szrj 
51638fd1498Szrj   template<>
51738fd1498Szrj     struct path::__is_encoded_char<char32_t> : std::true_type
51838fd1498Szrj     { using value_type = char32_t; };
51938fd1498Szrj 
52038fd1498Szrj   template<typename _Tp>
52138fd1498Szrj     struct path::__is_encoded_char<const _Tp> : __is_encoded_char<_Tp> { };
52238fd1498Szrj 
52338fd1498Szrj   inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
52438fd1498Szrj 
52538fd1498Szrj   size_t hash_value(const path& __p) noexcept;
52638fd1498Szrj 
52738fd1498Szrj   /// Compare paths
52838fd1498Szrj   inline bool operator<(const path& __lhs, const path& __rhs) noexcept
52938fd1498Szrj   { return __lhs.compare(__rhs) < 0; }
53038fd1498Szrj 
53138fd1498Szrj   /// Compare paths
53238fd1498Szrj   inline bool operator<=(const path& __lhs, const path& __rhs) noexcept
53338fd1498Szrj   { return !(__rhs < __lhs); }
53438fd1498Szrj 
53538fd1498Szrj   /// Compare paths
53638fd1498Szrj   inline bool operator>(const path& __lhs, const path& __rhs) noexcept
53738fd1498Szrj   { return __rhs < __lhs; }
53838fd1498Szrj 
53938fd1498Szrj   /// Compare paths
54038fd1498Szrj   inline bool operator>=(const path& __lhs, const path& __rhs) noexcept
54138fd1498Szrj   { return !(__lhs < __rhs); }
54238fd1498Szrj 
54338fd1498Szrj   /// Compare paths
54438fd1498Szrj   inline bool operator==(const path& __lhs, const path& __rhs) noexcept
54538fd1498Szrj   { return __lhs.compare(__rhs) == 0; }
54638fd1498Szrj 
54738fd1498Szrj   /// Compare paths
54838fd1498Szrj   inline bool operator!=(const path& __lhs, const path& __rhs) noexcept
54938fd1498Szrj   { return !(__lhs == __rhs); }
55038fd1498Szrj 
55138fd1498Szrj   /// Append one path to another
55238fd1498Szrj   inline path operator/(const path& __lhs, const path& __rhs)
553*58e805e6Szrj   {
554*58e805e6Szrj     path __result(__lhs);
555*58e805e6Szrj     __result /= __rhs;
556*58e805e6Szrj     return __result;
557*58e805e6Szrj   }
55838fd1498Szrj 
55938fd1498Szrj   /// Write a path to a stream
56038fd1498Szrj   template<typename _CharT, typename _Traits>
56138fd1498Szrj     basic_ostream<_CharT, _Traits>&
56238fd1498Szrj     operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p)
56338fd1498Szrj     {
56438fd1498Szrj       auto __tmp = __p.string<_CharT, _Traits>();
56538fd1498Szrj       using __quoted_string
56638fd1498Szrj 	= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
56738fd1498Szrj       __os << __quoted_string{__tmp, '"', '\\'};
56838fd1498Szrj       return __os;
56938fd1498Szrj     }
57038fd1498Szrj 
57138fd1498Szrj   /// Read a path from a stream
57238fd1498Szrj   template<typename _CharT, typename _Traits>
57338fd1498Szrj     basic_istream<_CharT, _Traits>&
57438fd1498Szrj     operator>>(basic_istream<_CharT, _Traits>& __is, path& __p)
57538fd1498Szrj     {
57638fd1498Szrj       basic_string<_CharT, _Traits> __tmp;
57738fd1498Szrj       using __quoted_string
57838fd1498Szrj 	= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
57938fd1498Szrj       if (__is >> __quoted_string{ __tmp, '"', '\\' })
58038fd1498Szrj 	__p = std::move(__tmp);
58138fd1498Szrj       return __is;
58238fd1498Szrj     }
58338fd1498Szrj 
58438fd1498Szrj   template<typename _Source>
58538fd1498Szrj     inline auto
58638fd1498Szrj     u8path(const _Source& __source)
58738fd1498Szrj     -> decltype(filesystem::path(__source, std::locale::classic()))
58838fd1498Szrj     {
58938fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
59038fd1498Szrj       const std::string __u8str{__source};
59138fd1498Szrj       return std::filesystem::u8path(__u8str.begin(), __u8str.end());
59238fd1498Szrj #else
59338fd1498Szrj       return path{ __source };
59438fd1498Szrj #endif
59538fd1498Szrj     }
59638fd1498Szrj 
59738fd1498Szrj   template<typename _InputIterator>
59838fd1498Szrj     inline auto
59938fd1498Szrj     u8path(_InputIterator __first, _InputIterator __last)
60038fd1498Szrj     -> decltype(filesystem::path(__first, __last, std::locale::classic()))
60138fd1498Szrj     {
60238fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
60338fd1498Szrj       codecvt_utf8<value_type> __cvt;
60438fd1498Szrj       string_type __tmp;
60538fd1498Szrj       if (__str_codecvt_in(__first, __last, __tmp, __cvt))
60638fd1498Szrj 	return path{ __tmp };
60738fd1498Szrj       else
60838fd1498Szrj 	return {};
60938fd1498Szrj #else
61038fd1498Szrj       return path{ __first, __last };
61138fd1498Szrj #endif
61238fd1498Szrj     }
61338fd1498Szrj 
61438fd1498Szrj   class filesystem_error : public std::system_error
61538fd1498Szrj   {
61638fd1498Szrj   public:
61738fd1498Szrj     filesystem_error(const string& __what_arg, error_code __ec)
61838fd1498Szrj     : system_error(__ec, __what_arg) { }
61938fd1498Szrj 
62038fd1498Szrj     filesystem_error(const string& __what_arg, const path& __p1,
62138fd1498Szrj 		     error_code __ec)
62238fd1498Szrj     : system_error(__ec, __what_arg), _M_path1(__p1) { }
62338fd1498Szrj 
62438fd1498Szrj     filesystem_error(const string& __what_arg, const path& __p1,
62538fd1498Szrj 		     const path& __p2, error_code __ec)
62638fd1498Szrj     : system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2)
62738fd1498Szrj     { }
62838fd1498Szrj 
62938fd1498Szrj     ~filesystem_error();
63038fd1498Szrj 
63138fd1498Szrj     const path& path1() const noexcept { return _M_path1; }
63238fd1498Szrj     const path& path2() const noexcept { return _M_path2; }
63338fd1498Szrj     const char* what() const noexcept { return _M_what.c_str(); }
63438fd1498Szrj 
63538fd1498Szrj   private:
63638fd1498Szrj     std::string _M_gen_what();
63738fd1498Szrj 
63838fd1498Szrj     path _M_path1;
63938fd1498Szrj     path _M_path2;
64038fd1498Szrj     std::string _M_what = _M_gen_what();
64138fd1498Szrj   };
64238fd1498Szrj 
64338fd1498Szrj   struct path::_Cmpt : path
64438fd1498Szrj   {
64538fd1498Szrj     _Cmpt(string_type __s, _Type __t, size_t __pos)
64638fd1498Szrj       : path(std::move(__s), __t), _M_pos(__pos) { }
64738fd1498Szrj 
64838fd1498Szrj     _Cmpt() : _M_pos(-1) { }
64938fd1498Szrj 
65038fd1498Szrj     size_t _M_pos;
65138fd1498Szrj   };
65238fd1498Szrj 
65338fd1498Szrj   // specialize _Cvt for degenerate 'noconv' case
65438fd1498Szrj   template<>
65538fd1498Szrj     struct path::_Cvt<path::value_type>
65638fd1498Szrj     {
65738fd1498Szrj       template<typename _Iter>
65838fd1498Szrj 	static string_type
65938fd1498Szrj 	_S_convert(_Iter __first, _Iter __last)
66038fd1498Szrj 	{ return string_type{__first, __last}; }
66138fd1498Szrj     };
66238fd1498Szrj 
66338fd1498Szrj   template<typename _CharT>
66438fd1498Szrj     struct path::_Cvt
66538fd1498Szrj     {
66638fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
66738fd1498Szrj       static string_type
66838fd1498Szrj       _S_wconvert(const char* __f, const char* __l, true_type)
66938fd1498Szrj       {
67038fd1498Szrj 	using _Cvt = std::codecvt<wchar_t, char, mbstate_t>;
67138fd1498Szrj 	const auto& __cvt = std::use_facet<_Cvt>(std::locale{});
67238fd1498Szrj 	std::wstring __wstr;
67338fd1498Szrj 	if (__str_codecvt_in(__f, __l, __wstr, __cvt))
67438fd1498Szrj 	    return __wstr;
67538fd1498Szrj 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
67638fd1498Szrj 	      "Cannot convert character sequence",
67738fd1498Szrj 	      std::make_error_code(errc::illegal_byte_sequence)));
67838fd1498Szrj       }
67938fd1498Szrj 
68038fd1498Szrj       static string_type
68138fd1498Szrj       _S_wconvert(const _CharT* __f, const _CharT* __l, false_type)
68238fd1498Szrj       {
68338fd1498Szrj 	std::codecvt_utf8<_CharT> __cvt;
68438fd1498Szrj 	std::string __str;
68538fd1498Szrj 	if (__str_codecvt_out(__f, __l, __str, __cvt))
68638fd1498Szrj 	  {
68738fd1498Szrj 	    const char* __f2 = __str.data();
68838fd1498Szrj 	    const char* __l2 = __f2 + __str.size();
68938fd1498Szrj 	    std::codecvt_utf8<wchar_t> __wcvt;
69038fd1498Szrj 	    std::wstring __wstr;
69138fd1498Szrj 	    if (__str_codecvt_in(__f2, __l2, __wstr, __wcvt))
69238fd1498Szrj 	      return __wstr;
69338fd1498Szrj 	  }
69438fd1498Szrj 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
69538fd1498Szrj 	      "Cannot convert character sequence",
69638fd1498Szrj 	      std::make_error_code(errc::illegal_byte_sequence)));
69738fd1498Szrj       }
69838fd1498Szrj 
69938fd1498Szrj       static string_type
70038fd1498Szrj       _S_convert(const _CharT* __f, const _CharT* __l)
70138fd1498Szrj       {
70238fd1498Szrj 	return _S_wconvert(__f, __l, is_same<_CharT, char>{});
70338fd1498Szrj       }
70438fd1498Szrj #else
70538fd1498Szrj       static string_type
70638fd1498Szrj       _S_convert(const _CharT* __f, const _CharT* __l)
70738fd1498Szrj       {
70838fd1498Szrj 	std::codecvt_utf8<_CharT> __cvt;
70938fd1498Szrj 	std::string __str;
71038fd1498Szrj 	if (__str_codecvt_out(__f, __l, __str, __cvt))
71138fd1498Szrj 	  return __str;
71238fd1498Szrj 	_GLIBCXX_THROW_OR_ABORT(filesystem_error(
71338fd1498Szrj 	      "Cannot convert character sequence",
71438fd1498Szrj 	      std::make_error_code(errc::illegal_byte_sequence)));
71538fd1498Szrj       }
71638fd1498Szrj #endif
71738fd1498Szrj 
71838fd1498Szrj       static string_type
71938fd1498Szrj       _S_convert(_CharT* __f, _CharT* __l)
72038fd1498Szrj       {
72138fd1498Szrj 	return _S_convert(const_cast<const _CharT*>(__f),
72238fd1498Szrj 			  const_cast<const _CharT*>(__l));
72338fd1498Szrj       }
72438fd1498Szrj 
72538fd1498Szrj       template<typename _Iter>
72638fd1498Szrj 	static string_type
72738fd1498Szrj 	_S_convert(_Iter __first, _Iter __last)
72838fd1498Szrj 	{
72938fd1498Szrj 	  const std::basic_string<_CharT> __str(__first, __last);
73038fd1498Szrj 	  return _S_convert(__str.data(), __str.data() + __str.size());
73138fd1498Szrj 	}
73238fd1498Szrj 
73338fd1498Szrj       template<typename _Iter, typename _Cont>
73438fd1498Szrj 	static string_type
73538fd1498Szrj 	_S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first,
73638fd1498Szrj 		  __gnu_cxx::__normal_iterator<_Iter, _Cont> __last)
73738fd1498Szrj 	{ return _S_convert(__first.base(), __last.base()); }
73838fd1498Szrj     };
73938fd1498Szrj 
74038fd1498Szrj   /// An iterator for the components of a path
74138fd1498Szrj   class path::iterator
74238fd1498Szrj   {
74338fd1498Szrj   public:
74438fd1498Szrj     using difference_type	= std::ptrdiff_t;
74538fd1498Szrj     using value_type		= path;
74638fd1498Szrj     using reference		= const path&;
74738fd1498Szrj     using pointer		= const path*;
74838fd1498Szrj     using iterator_category	= std::bidirectional_iterator_tag;
74938fd1498Szrj 
75038fd1498Szrj     iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { }
75138fd1498Szrj 
75238fd1498Szrj     iterator(const iterator&) = default;
75338fd1498Szrj     iterator& operator=(const iterator&) = default;
75438fd1498Szrj 
75538fd1498Szrj     reference operator*() const;
75638fd1498Szrj     pointer   operator->() const { return std::__addressof(**this); }
75738fd1498Szrj 
75838fd1498Szrj     iterator& operator++();
75938fd1498Szrj     iterator  operator++(int) { auto __tmp = *this; ++*this; return __tmp; }
76038fd1498Szrj 
76138fd1498Szrj     iterator& operator--();
76238fd1498Szrj     iterator  operator--(int) { auto __tmp = *this; --*this; return __tmp; }
76338fd1498Szrj 
76438fd1498Szrj     friend bool operator==(const iterator& __lhs, const iterator& __rhs)
76538fd1498Szrj     { return __lhs._M_equals(__rhs); }
76638fd1498Szrj 
76738fd1498Szrj     friend bool operator!=(const iterator& __lhs, const iterator& __rhs)
76838fd1498Szrj     { return !__lhs._M_equals(__rhs); }
76938fd1498Szrj 
77038fd1498Szrj   private:
77138fd1498Szrj     friend class path;
77238fd1498Szrj 
77338fd1498Szrj     iterator(const path* __path, path::_List::const_iterator __iter)
77438fd1498Szrj     : _M_path(__path), _M_cur(__iter), _M_at_end()
77538fd1498Szrj     { }
77638fd1498Szrj 
77738fd1498Szrj     iterator(const path* __path, bool __at_end)
77838fd1498Szrj     : _M_path(__path), _M_cur(), _M_at_end(__at_end)
77938fd1498Szrj     { }
78038fd1498Szrj 
78138fd1498Szrj     bool _M_equals(iterator) const;
78238fd1498Szrj 
78338fd1498Szrj     const path* 		_M_path;
78438fd1498Szrj     path::_List::const_iterator _M_cur;
78538fd1498Szrj     bool			_M_at_end;  // only used when type != _Multi
78638fd1498Szrj   };
78738fd1498Szrj 
78838fd1498Szrj 
78938fd1498Szrj   inline path&
79038fd1498Szrj   path::operator=(path&& __p) noexcept
79138fd1498Szrj   {
79238fd1498Szrj     _M_pathname = std::move(__p._M_pathname);
79338fd1498Szrj     _M_cmpts = std::move(__p._M_cmpts);
79438fd1498Szrj     _M_type = __p._M_type;
79538fd1498Szrj     __p.clear();
79638fd1498Szrj     return *this;
79738fd1498Szrj   }
79838fd1498Szrj 
79938fd1498Szrj   inline path&
80038fd1498Szrj   path::operator=(string_type&& __source)
80138fd1498Szrj   { return *this = path(std::move(__source)); }
80238fd1498Szrj 
80338fd1498Szrj   inline path&
80438fd1498Szrj   path::assign(string_type&& __source)
80538fd1498Szrj   { return *this = path(std::move(__source)); }
80638fd1498Szrj 
80738fd1498Szrj   inline path&
80838fd1498Szrj   path::operator+=(const path& __p)
80938fd1498Szrj   {
81038fd1498Szrj     return operator+=(__p.native());
81138fd1498Szrj   }
81238fd1498Szrj 
81338fd1498Szrj   inline path&
81438fd1498Szrj   path::operator+=(const string_type& __x)
81538fd1498Szrj   {
81638fd1498Szrj     _M_pathname += __x;
81738fd1498Szrj     _M_split_cmpts();
81838fd1498Szrj     return *this;
81938fd1498Szrj   }
82038fd1498Szrj 
82138fd1498Szrj   inline path&
82238fd1498Szrj   path::operator+=(const value_type* __x)
82338fd1498Szrj   {
82438fd1498Szrj     _M_pathname += __x;
82538fd1498Szrj     _M_split_cmpts();
82638fd1498Szrj     return *this;
82738fd1498Szrj   }
82838fd1498Szrj 
82938fd1498Szrj   inline path&
83038fd1498Szrj   path::operator+=(value_type __x)
83138fd1498Szrj   {
83238fd1498Szrj     _M_pathname += __x;
83338fd1498Szrj     _M_split_cmpts();
83438fd1498Szrj     return *this;
83538fd1498Szrj   }
83638fd1498Szrj 
83738fd1498Szrj   inline path&
83838fd1498Szrj   path::operator+=(basic_string_view<value_type> __x)
83938fd1498Szrj   {
84038fd1498Szrj     _M_pathname.append(__x.data(), __x.size());
84138fd1498Szrj     _M_split_cmpts();
84238fd1498Szrj     return *this;
84338fd1498Szrj   }
84438fd1498Szrj 
84538fd1498Szrj   template<typename _CharT>
84638fd1498Szrj     inline path::_Path<_CharT*, _CharT*>&
84738fd1498Szrj     path::operator+=(_CharT __x)
84838fd1498Szrj     {
84938fd1498Szrj       auto* __addr = std::__addressof(__x);
85038fd1498Szrj       return concat(__addr, __addr + 1);
85138fd1498Szrj     }
85238fd1498Szrj 
85338fd1498Szrj   inline path&
85438fd1498Szrj   path::make_preferred()
85538fd1498Szrj   {
85638fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
85738fd1498Szrj     std::replace(_M_pathname.begin(), _M_pathname.end(), L'/',
85838fd1498Szrj 		 preferred_separator);
85938fd1498Szrj #endif
86038fd1498Szrj     return *this;
86138fd1498Szrj   }
86238fd1498Szrj 
86338fd1498Szrj   inline void path::swap(path& __rhs) noexcept
86438fd1498Szrj   {
86538fd1498Szrj     _M_pathname.swap(__rhs._M_pathname);
86638fd1498Szrj     _M_cmpts.swap(__rhs._M_cmpts);
86738fd1498Szrj     std::swap(_M_type, __rhs._M_type);
86838fd1498Szrj   }
86938fd1498Szrj 
87038fd1498Szrj   template<typename _CharT, typename _Traits, typename _Allocator>
87138fd1498Szrj     std::basic_string<_CharT, _Traits, _Allocator>
87238fd1498Szrj     path::_S_str_convert(const string_type& __str, const _Allocator& __a)
87338fd1498Szrj     {
87438fd1498Szrj       if (__str.size() == 0)
87538fd1498Szrj 	return std::basic_string<_CharT, _Traits, _Allocator>(__a);
87638fd1498Szrj 
87738fd1498Szrj       const value_type* __first = __str.data();
87838fd1498Szrj       const value_type* __last = __first + __str.size();
87938fd1498Szrj 
88038fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
88138fd1498Szrj       using _CharAlloc = __alloc_rebind<_Allocator, char>;
88238fd1498Szrj       using _String = basic_string<char, char_traits<char>, _CharAlloc>;
88338fd1498Szrj       using _WString = basic_string<_CharT, _Traits, _Allocator>;
88438fd1498Szrj 
88538fd1498Szrj       // use codecvt_utf8<wchar_t> to convert native string to UTF-8
88638fd1498Szrj       codecvt_utf8<value_type> __cvt;
88738fd1498Szrj       _String __u8str{_CharAlloc{__a}};
88838fd1498Szrj       if (__str_codecvt_out(__first, __last, __u8str, __cvt))
88938fd1498Szrj 	{
89038fd1498Szrj 	  if constexpr (is_same_v<_CharT, char>)
89138fd1498Szrj 	    return __u8str;
89238fd1498Szrj 	  else
89338fd1498Szrj 	    {
89438fd1498Szrj 	      _WString __wstr;
89538fd1498Szrj 	      // use codecvt_utf8<_CharT> to convert UTF-8 to wide string
89638fd1498Szrj 	      codecvt_utf8<_CharT> __cvt;
89738fd1498Szrj 	      const char* __f = __u8str.data();
89838fd1498Szrj 	      const char* __l = __f + __u8str.size();
89938fd1498Szrj 	      if (__str_codecvt_in(__f, __l, __wstr, __cvt))
90038fd1498Szrj 		return __wstr;
90138fd1498Szrj 	    }
90238fd1498Szrj 	}
90338fd1498Szrj #else
90438fd1498Szrj       codecvt_utf8<_CharT> __cvt;
90538fd1498Szrj       basic_string<_CharT, _Traits, _Allocator> __wstr{__a};
90638fd1498Szrj       if (__str_codecvt_in(__first, __last, __wstr, __cvt))
90738fd1498Szrj 	return __wstr;
90838fd1498Szrj #endif
90938fd1498Szrj       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
91038fd1498Szrj 	    "Cannot convert character sequence",
91138fd1498Szrj 	    std::make_error_code(errc::illegal_byte_sequence)));
91238fd1498Szrj     }
91338fd1498Szrj 
91438fd1498Szrj   template<typename _CharT, typename _Traits, typename _Allocator>
91538fd1498Szrj     inline basic_string<_CharT, _Traits, _Allocator>
91638fd1498Szrj     path::string(const _Allocator& __a) const
91738fd1498Szrj     {
91838fd1498Szrj       if constexpr (is_same_v<_CharT, value_type>)
91938fd1498Szrj #if _GLIBCXX_USE_CXX11_ABI
92038fd1498Szrj 	return { _M_pathname, __a };
92138fd1498Szrj #else
92238fd1498Szrj 	return { _M_pathname, string_type::size_type(0), __a };
92338fd1498Szrj #endif
92438fd1498Szrj       else
92538fd1498Szrj 	return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);
92638fd1498Szrj     }
92738fd1498Szrj 
92838fd1498Szrj   inline std::string
92938fd1498Szrj   path::string() const { return string<char>(); }
93038fd1498Szrj 
93138fd1498Szrj #if _GLIBCXX_USE_WCHAR_T
93238fd1498Szrj   inline std::wstring
93338fd1498Szrj   path::wstring() const { return string<wchar_t>(); }
93438fd1498Szrj #endif
93538fd1498Szrj 
93638fd1498Szrj   inline std::string
93738fd1498Szrj   path::u8string() const
93838fd1498Szrj   {
93938fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
94038fd1498Szrj     std::string __str;
94138fd1498Szrj     // convert from native encoding to UTF-8
94238fd1498Szrj     codecvt_utf8<value_type> __cvt;
94338fd1498Szrj     const value_type* __first = _M_pathname.data();
94438fd1498Szrj     const value_type* __last = __first + _M_pathname.size();
94538fd1498Szrj     if (__str_codecvt_out(__first, __last, __str, __cvt))
94638fd1498Szrj       return __str;
94738fd1498Szrj     _GLIBCXX_THROW_OR_ABORT(filesystem_error(
94838fd1498Szrj 	  "Cannot convert character sequence",
94938fd1498Szrj 	  std::make_error_code(errc::illegal_byte_sequence)));
95038fd1498Szrj #else
95138fd1498Szrj     return _M_pathname;
95238fd1498Szrj #endif
95338fd1498Szrj   }
95438fd1498Szrj 
95538fd1498Szrj   inline std::u16string
95638fd1498Szrj   path::u16string() const { return string<char16_t>(); }
95738fd1498Szrj 
95838fd1498Szrj   inline std::u32string
95938fd1498Szrj   path::u32string() const { return string<char32_t>(); }
96038fd1498Szrj 
96138fd1498Szrj   template<typename _CharT, typename _Traits, typename _Allocator>
96238fd1498Szrj     inline std::basic_string<_CharT, _Traits, _Allocator>
96338fd1498Szrj     path::generic_string(const _Allocator& __a) const
96438fd1498Szrj     {
96538fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
96638fd1498Szrj       const value_type __slash = L'/';
96738fd1498Szrj #else
96838fd1498Szrj       const value_type __slash = '/';
96938fd1498Szrj #endif
97038fd1498Szrj       string_type __str(__a);
97138fd1498Szrj 
97238fd1498Szrj       if (_M_type == _Type::_Root_dir)
97338fd1498Szrj 	__str.assign(1, __slash);
97438fd1498Szrj       else
97538fd1498Szrj 	{
97638fd1498Szrj 	  __str.reserve(_M_pathname.size());
97738fd1498Szrj 	  bool __add_slash = false;
97838fd1498Szrj 	  for (auto& __elem : *this)
97938fd1498Szrj 	    {
98038fd1498Szrj 	      if (__add_slash)
98138fd1498Szrj 		__str += __slash;
98238fd1498Szrj 	      __str += __elem._M_pathname;
98338fd1498Szrj 	      __add_slash = __elem._M_type == _Type::_Filename;
98438fd1498Szrj 	    }
98538fd1498Szrj 	}
98638fd1498Szrj 
98738fd1498Szrj       if constexpr (is_same_v<_CharT, value_type>)
98838fd1498Szrj 	return __str;
98938fd1498Szrj       else
99038fd1498Szrj 	return _S_str_convert<_CharT, _Traits>(__str, __a);
99138fd1498Szrj     }
99238fd1498Szrj 
99338fd1498Szrj   inline std::string
99438fd1498Szrj   path::generic_string() const
99538fd1498Szrj   { return generic_string<char>(); }
99638fd1498Szrj 
99738fd1498Szrj #if _GLIBCXX_USE_WCHAR_T
99838fd1498Szrj   inline std::wstring
99938fd1498Szrj   path::generic_wstring() const
100038fd1498Szrj   { return generic_string<wchar_t>(); }
100138fd1498Szrj #endif
100238fd1498Szrj 
100338fd1498Szrj   inline std::string
100438fd1498Szrj   path::generic_u8string() const
100538fd1498Szrj   { return generic_string(); }
100638fd1498Szrj 
100738fd1498Szrj   inline std::u16string
100838fd1498Szrj   path::generic_u16string() const
100938fd1498Szrj   { return generic_string<char16_t>(); }
101038fd1498Szrj 
101138fd1498Szrj   inline std::u32string
101238fd1498Szrj   path::generic_u32string() const
101338fd1498Szrj   { return generic_string<char32_t>(); }
101438fd1498Szrj 
101538fd1498Szrj   inline int
101638fd1498Szrj   path::compare(const string_type& __s) const { return compare(path(__s)); }
101738fd1498Szrj 
101838fd1498Szrj   inline int
101938fd1498Szrj   path::compare(const value_type* __s) const { return compare(path(__s)); }
102038fd1498Szrj 
102138fd1498Szrj   inline int
102238fd1498Szrj   path::compare(basic_string_view<value_type> __s) const
102338fd1498Szrj   { return compare(path(__s)); }
102438fd1498Szrj 
102538fd1498Szrj   inline path
102638fd1498Szrj   path::filename() const
102738fd1498Szrj   {
102838fd1498Szrj     if (empty())
102938fd1498Szrj       return {};
103038fd1498Szrj     else if (_M_type == _Type::_Filename)
103138fd1498Szrj       return *this;
103238fd1498Szrj     else if (_M_type == _Type::_Multi)
103338fd1498Szrj       {
103438fd1498Szrj 	if (_M_pathname.back() == preferred_separator)
103538fd1498Szrj 	  return {};
103638fd1498Szrj 	auto& __last = *--end();
103738fd1498Szrj 	if (__last._M_type == _Type::_Filename)
103838fd1498Szrj 	  return __last;
103938fd1498Szrj       }
104038fd1498Szrj     return {};
104138fd1498Szrj   }
104238fd1498Szrj 
104338fd1498Szrj   inline path
104438fd1498Szrj   path::stem() const
104538fd1498Szrj   {
104638fd1498Szrj     auto ext = _M_find_extension();
104738fd1498Szrj     if (ext.first && ext.second != 0)
104838fd1498Szrj       return path{ext.first->substr(0, ext.second)};
104938fd1498Szrj     return {};
105038fd1498Szrj   }
105138fd1498Szrj 
105238fd1498Szrj   inline path
105338fd1498Szrj   path::extension() const
105438fd1498Szrj   {
105538fd1498Szrj     auto ext = _M_find_extension();
105638fd1498Szrj     if (ext.first && ext.second != string_type::npos)
105738fd1498Szrj       return path{ext.first->substr(ext.second)};
105838fd1498Szrj     return {};
105938fd1498Szrj   }
106038fd1498Szrj 
106138fd1498Szrj   inline bool
106238fd1498Szrj   path::has_stem() const
106338fd1498Szrj   {
106438fd1498Szrj     auto ext = _M_find_extension();
106538fd1498Szrj     return ext.first && ext.second != 0;
106638fd1498Szrj   }
106738fd1498Szrj 
106838fd1498Szrj   inline bool
106938fd1498Szrj   path::has_extension() const
107038fd1498Szrj   {
107138fd1498Szrj     auto ext = _M_find_extension();
107238fd1498Szrj     return ext.first && ext.second != string_type::npos;
107338fd1498Szrj   }
107438fd1498Szrj 
107538fd1498Szrj   inline path::iterator
107638fd1498Szrj   path::begin() const
107738fd1498Szrj   {
107838fd1498Szrj     if (_M_type == _Type::_Multi)
107938fd1498Szrj       return iterator(this, _M_cmpts.begin());
1080*58e805e6Szrj     return iterator(this, empty());
108138fd1498Szrj   }
108238fd1498Szrj 
108338fd1498Szrj   inline path::iterator
108438fd1498Szrj   path::end() const
108538fd1498Szrj   {
108638fd1498Szrj     if (_M_type == _Type::_Multi)
108738fd1498Szrj       return iterator(this, _M_cmpts.end());
108838fd1498Szrj     return iterator(this, true);
108938fd1498Szrj   }
109038fd1498Szrj 
109138fd1498Szrj   inline path::iterator&
109238fd1498Szrj   path::iterator::operator++()
109338fd1498Szrj   {
109438fd1498Szrj     __glibcxx_assert(_M_path != nullptr);
109538fd1498Szrj     if (_M_path->_M_type == _Type::_Multi)
109638fd1498Szrj       {
109738fd1498Szrj 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
109838fd1498Szrj 	++_M_cur;
109938fd1498Szrj       }
110038fd1498Szrj     else
110138fd1498Szrj       {
110238fd1498Szrj 	__glibcxx_assert(!_M_at_end);
110338fd1498Szrj 	_M_at_end = true;
110438fd1498Szrj       }
110538fd1498Szrj     return *this;
110638fd1498Szrj   }
110738fd1498Szrj 
110838fd1498Szrj   inline path::iterator&
110938fd1498Szrj   path::iterator::operator--()
111038fd1498Szrj   {
111138fd1498Szrj     __glibcxx_assert(_M_path != nullptr);
111238fd1498Szrj     if (_M_path->_M_type == _Type::_Multi)
111338fd1498Szrj       {
111438fd1498Szrj 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
111538fd1498Szrj 	--_M_cur;
111638fd1498Szrj       }
111738fd1498Szrj     else
111838fd1498Szrj       {
111938fd1498Szrj 	__glibcxx_assert(_M_at_end);
112038fd1498Szrj 	_M_at_end = false;
112138fd1498Szrj       }
112238fd1498Szrj     return *this;
112338fd1498Szrj   }
112438fd1498Szrj 
112538fd1498Szrj   inline path::iterator::reference
112638fd1498Szrj   path::iterator::operator*() const
112738fd1498Szrj   {
112838fd1498Szrj     __glibcxx_assert(_M_path != nullptr);
112938fd1498Szrj     if (_M_path->_M_type == _Type::_Multi)
113038fd1498Szrj       {
113138fd1498Szrj 	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
113238fd1498Szrj 	return *_M_cur;
113338fd1498Szrj       }
113438fd1498Szrj     return *_M_path;
113538fd1498Szrj   }
113638fd1498Szrj 
113738fd1498Szrj   inline bool
113838fd1498Szrj   path::iterator::_M_equals(iterator __rhs) const
113938fd1498Szrj   {
114038fd1498Szrj     if (_M_path != __rhs._M_path)
114138fd1498Szrj       return false;
114238fd1498Szrj     if (_M_path == nullptr)
114338fd1498Szrj       return true;
114438fd1498Szrj     if (_M_path->_M_type == path::_Type::_Multi)
114538fd1498Szrj       return _M_cur == __rhs._M_cur;
114638fd1498Szrj     return _M_at_end == __rhs._M_at_end;
114738fd1498Szrj   }
114838fd1498Szrj 
114938fd1498Szrj   // @} group filesystem
115038fd1498Szrj _GLIBCXX_END_NAMESPACE_CXX11
115138fd1498Szrj } // namespace filesystem
115238fd1498Szrj 
115338fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
115438fd1498Szrj } // namespace std
115538fd1498Szrj 
115638fd1498Szrj #endif // C++17
115738fd1498Szrj 
115838fd1498Szrj #endif // _GLIBCXX_FS_PATH_H
1159