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