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