1*38fd1498Szrj // Class filesystem::path -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj // Copyright (C) 2014-2018 Free Software Foundation, Inc. 4*38fd1498Szrj // 5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj // software; you can redistribute it and/or modify it under the 7*38fd1498Szrj // terms of the GNU General Public License as published by the 8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option) 9*38fd1498Szrj // any later version. 10*38fd1498Szrj 11*38fd1498Szrj // This library is distributed in the hope that it will be useful, 12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*38fd1498Szrj // GNU General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj // 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj // You should have received a copy of the GNU General Public License and 21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj // <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj /** @file include/bits/fs_path.h 26*38fd1498Szrj * This is an internal header file, included by other library headers. 27*38fd1498Szrj * Do not attempt to use it directly. @headername{filesystem} 28*38fd1498Szrj */ 29*38fd1498Szrj 30*38fd1498Szrj #ifndef _GLIBCXX_FS_PATH_H 31*38fd1498Szrj #define _GLIBCXX_FS_PATH_H 1 32*38fd1498Szrj 33*38fd1498Szrj #if __cplusplus >= 201703L 34*38fd1498Szrj 35*38fd1498Szrj #include <utility> 36*38fd1498Szrj #include <type_traits> 37*38fd1498Szrj #include <vector> 38*38fd1498Szrj #include <locale> 39*38fd1498Szrj #include <iosfwd> 40*38fd1498Szrj #include <codecvt> 41*38fd1498Szrj #include <string_view> 42*38fd1498Szrj #include <system_error> 43*38fd1498Szrj #include <bits/stl_algobase.h> 44*38fd1498Szrj #include <bits/quoted_string.h> 45*38fd1498Szrj #include <bits/locale_conv.h> 46*38fd1498Szrj 47*38fd1498Szrj #if defined(_WIN32) && !defined(__CYGWIN__) 48*38fd1498Szrj # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 49*38fd1498Szrj # include <algorithm> 50*38fd1498Szrj #endif 51*38fd1498Szrj 52*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default) 53*38fd1498Szrj { 54*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION 55*38fd1498Szrj 56*38fd1498Szrj namespace filesystem 57*38fd1498Szrj { 58*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_CXX11 59*38fd1498Szrj 60*38fd1498Szrj /** 61*38fd1498Szrj * @ingroup filesystem 62*38fd1498Szrj * @{ 63*38fd1498Szrj */ 64*38fd1498Szrj 65*38fd1498Szrj /// A filesystem path. 66*38fd1498Szrj class path 67*38fd1498Szrj { 68*38fd1498Szrj template<typename _CharT> 69*38fd1498Szrj struct __is_encoded_char : std::false_type { }; 70*38fd1498Szrj 71*38fd1498Szrj template<typename _Iter, 72*38fd1498Szrj typename _Iter_traits = std::iterator_traits<_Iter>> 73*38fd1498Szrj using __is_path_iter_src 74*38fd1498Szrj = __and_<__is_encoded_char<typename _Iter_traits::value_type>, 75*38fd1498Szrj std::is_base_of<std::input_iterator_tag, 76*38fd1498Szrj typename _Iter_traits::iterator_category>>; 77*38fd1498Szrj 78*38fd1498Szrj template<typename _Iter> 79*38fd1498Szrj static __is_path_iter_src<_Iter> 80*38fd1498Szrj __is_path_src(_Iter, int); 81*38fd1498Szrj 82*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Alloc> 83*38fd1498Szrj static __is_encoded_char<_CharT> 84*38fd1498Szrj __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); 85*38fd1498Szrj 86*38fd1498Szrj template<typename _CharT, typename _Traits> 87*38fd1498Szrj static __is_encoded_char<_CharT> 88*38fd1498Szrj __is_path_src(const basic_string_view<_CharT, _Traits>&, int); 89*38fd1498Szrj 90*38fd1498Szrj template<typename _Unknown> 91*38fd1498Szrj static std::false_type 92*38fd1498Szrj __is_path_src(const _Unknown&, ...); 93*38fd1498Szrj 94*38fd1498Szrj template<typename _Tp1, typename _Tp2> 95*38fd1498Szrj struct __constructible_from; 96*38fd1498Szrj 97*38fd1498Szrj template<typename _Iter> 98*38fd1498Szrj struct __constructible_from<_Iter, _Iter> 99*38fd1498Szrj : __is_path_iter_src<_Iter> 100*38fd1498Szrj { }; 101*38fd1498Szrj 102*38fd1498Szrj template<typename _Source> 103*38fd1498Szrj struct __constructible_from<_Source, void> 104*38fd1498Szrj : decltype(__is_path_src(std::declval<_Source>(), 0)) 105*38fd1498Szrj { }; 106*38fd1498Szrj 107*38fd1498Szrj template<typename _Tp1, typename _Tp2 = void> 108*38fd1498Szrj using _Path = typename 109*38fd1498Szrj std::enable_if<__and_<__not_<is_same<_Tp1, path>>, 110*38fd1498Szrj __constructible_from<_Tp1, _Tp2>>::value, 111*38fd1498Szrj path>::type; 112*38fd1498Szrj 113*38fd1498Szrj template<typename _Source> 114*38fd1498Szrj static _Source 115*38fd1498Szrj _S_range_begin(_Source __begin) { return __begin; } 116*38fd1498Szrj 117*38fd1498Szrj struct __null_terminated { }; 118*38fd1498Szrj 119*38fd1498Szrj template<typename _Source> 120*38fd1498Szrj static __null_terminated 121*38fd1498Szrj _S_range_end(_Source) { return {}; } 122*38fd1498Szrj 123*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Alloc> 124*38fd1498Szrj static const _CharT* 125*38fd1498Szrj _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) 126*38fd1498Szrj { return __str.data(); } 127*38fd1498Szrj 128*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Alloc> 129*38fd1498Szrj static const _CharT* 130*38fd1498Szrj _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) 131*38fd1498Szrj { return __str.data() + __str.size(); } 132*38fd1498Szrj 133*38fd1498Szrj template<typename _CharT, typename _Traits> 134*38fd1498Szrj static const _CharT* 135*38fd1498Szrj _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) 136*38fd1498Szrj { return __str.data(); } 137*38fd1498Szrj 138*38fd1498Szrj template<typename _CharT, typename _Traits> 139*38fd1498Szrj static const _CharT* 140*38fd1498Szrj _S_range_end(const basic_string_view<_CharT, _Traits>& __str) 141*38fd1498Szrj { return __str.data() + __str.size(); } 142*38fd1498Szrj 143*38fd1498Szrj template<typename _Tp, 144*38fd1498Szrj typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), 145*38fd1498Szrj typename _Val = typename std::iterator_traits<_Iter>::value_type> 146*38fd1498Szrj using __value_type_is_char 147*38fd1498Szrj = typename std::enable_if<std::is_same<_Val, char>::value>::type; 148*38fd1498Szrj 149*38fd1498Szrj public: 150*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 151*38fd1498Szrj typedef wchar_t value_type; 152*38fd1498Szrj static constexpr value_type preferred_separator = L'\\'; 153*38fd1498Szrj #else 154*38fd1498Szrj typedef char value_type; 155*38fd1498Szrj static constexpr value_type preferred_separator = '/'; 156*38fd1498Szrj #endif 157*38fd1498Szrj typedef std::basic_string<value_type> string_type; 158*38fd1498Szrj 159*38fd1498Szrj enum format { native_format, generic_format, auto_format }; 160*38fd1498Szrj 161*38fd1498Szrj // constructors and destructor 162*38fd1498Szrj 163*38fd1498Szrj path() noexcept { } 164*38fd1498Szrj 165*38fd1498Szrj path(const path& __p) = default; 166*38fd1498Szrj 167*38fd1498Szrj path(path&& __p) noexcept 168*38fd1498Szrj : _M_pathname(std::move(__p._M_pathname)), _M_type(__p._M_type) 169*38fd1498Szrj { 170*38fd1498Szrj _M_split_cmpts(); 171*38fd1498Szrj __p.clear(); 172*38fd1498Szrj } 173*38fd1498Szrj 174*38fd1498Szrj path(string_type&& __source, format = auto_format) 175*38fd1498Szrj : _M_pathname(std::move(__source)) 176*38fd1498Szrj { _M_split_cmpts(); } 177*38fd1498Szrj 178*38fd1498Szrj template<typename _Source, 179*38fd1498Szrj typename _Require = _Path<_Source>> 180*38fd1498Szrj path(_Source const& __source, format = auto_format) 181*38fd1498Szrj : _M_pathname(_S_convert(_S_range_begin(__source), 182*38fd1498Szrj _S_range_end(__source))) 183*38fd1498Szrj { _M_split_cmpts(); } 184*38fd1498Szrj 185*38fd1498Szrj template<typename _InputIterator, 186*38fd1498Szrj typename _Require = _Path<_InputIterator, _InputIterator>> 187*38fd1498Szrj path(_InputIterator __first, _InputIterator __last, format = auto_format) 188*38fd1498Szrj : _M_pathname(_S_convert(__first, __last)) 189*38fd1498Szrj { _M_split_cmpts(); } 190*38fd1498Szrj 191*38fd1498Szrj template<typename _Source, 192*38fd1498Szrj typename _Require = _Path<_Source>, 193*38fd1498Szrj typename _Require2 = __value_type_is_char<_Source>> 194*38fd1498Szrj path(_Source const& __source, const locale& __loc, format = auto_format) 195*38fd1498Szrj : _M_pathname(_S_convert_loc(_S_range_begin(__source), 196*38fd1498Szrj _S_range_end(__source), __loc)) 197*38fd1498Szrj { _M_split_cmpts(); } 198*38fd1498Szrj 199*38fd1498Szrj template<typename _InputIterator, 200*38fd1498Szrj typename _Require = _Path<_InputIterator, _InputIterator>, 201*38fd1498Szrj typename _Require2 = __value_type_is_char<_InputIterator>> 202*38fd1498Szrj path(_InputIterator __first, _InputIterator __last, const locale& __loc, 203*38fd1498Szrj format = auto_format) 204*38fd1498Szrj : _M_pathname(_S_convert_loc(__first, __last, __loc)) 205*38fd1498Szrj { _M_split_cmpts(); } 206*38fd1498Szrj 207*38fd1498Szrj ~path() = default; 208*38fd1498Szrj 209*38fd1498Szrj // assignments 210*38fd1498Szrj 211*38fd1498Szrj path& operator=(const path& __p) = default; 212*38fd1498Szrj path& operator=(path&& __p) noexcept; 213*38fd1498Szrj path& operator=(string_type&& __source); 214*38fd1498Szrj path& assign(string_type&& __source); 215*38fd1498Szrj 216*38fd1498Szrj template<typename _Source> 217*38fd1498Szrj _Path<_Source>& 218*38fd1498Szrj operator=(_Source const& __source) 219*38fd1498Szrj { return *this = path(__source); } 220*38fd1498Szrj 221*38fd1498Szrj template<typename _Source> 222*38fd1498Szrj _Path<_Source>& 223*38fd1498Szrj assign(_Source const& __source) 224*38fd1498Szrj { return *this = path(__source); } 225*38fd1498Szrj 226*38fd1498Szrj template<typename _InputIterator> 227*38fd1498Szrj _Path<_InputIterator, _InputIterator>& 228*38fd1498Szrj assign(_InputIterator __first, _InputIterator __last) 229*38fd1498Szrj { return *this = path(__first, __last); } 230*38fd1498Szrj 231*38fd1498Szrj // appends 232*38fd1498Szrj 233*38fd1498Szrj path& operator/=(const path& __p) 234*38fd1498Szrj { 235*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 236*38fd1498Szrj if (__p.is_absolute() 237*38fd1498Szrj || (__p.has_root_name() && __p.root_name() != root_name())) 238*38fd1498Szrj operator=(__p); 239*38fd1498Szrj else 240*38fd1498Szrj { 241*38fd1498Szrj string_type __pathname; 242*38fd1498Szrj if (__p.has_root_directory()) 243*38fd1498Szrj __pathname = root_name().native(); 244*38fd1498Szrj else if (has_filename() || (!has_root_directory() && is_absolute())) 245*38fd1498Szrj __pathname = _M_pathname + preferred_separator; 246*38fd1498Szrj __pathname += __p.relative_path().native(); // XXX is this right? 247*38fd1498Szrj _M_pathname.swap(__pathname); 248*38fd1498Szrj _M_split_cmpts(); 249*38fd1498Szrj } 250*38fd1498Szrj #else 251*38fd1498Szrj // Much simpler, as any path with root-name or root-dir is absolute. 252*38fd1498Szrj if (__p.is_absolute()) 253*38fd1498Szrj operator=(__p); 254*38fd1498Szrj else 255*38fd1498Szrj { 256*38fd1498Szrj if (has_filename() || (_M_type == _Type::_Root_name)) 257*38fd1498Szrj _M_pathname += preferred_separator; 258*38fd1498Szrj _M_pathname += __p.native(); 259*38fd1498Szrj _M_split_cmpts(); 260*38fd1498Szrj } 261*38fd1498Szrj #endif 262*38fd1498Szrj return *this; 263*38fd1498Szrj } 264*38fd1498Szrj 265*38fd1498Szrj template <class _Source> 266*38fd1498Szrj _Path<_Source>& 267*38fd1498Szrj operator/=(_Source const& __source) 268*38fd1498Szrj { return append(__source); } 269*38fd1498Szrj 270*38fd1498Szrj template<typename _Source> 271*38fd1498Szrj _Path<_Source>& 272*38fd1498Szrj append(_Source const& __source) 273*38fd1498Szrj { 274*38fd1498Szrj return _M_append(_S_convert(_S_range_begin(__source), 275*38fd1498Szrj _S_range_end(__source))); 276*38fd1498Szrj } 277*38fd1498Szrj 278*38fd1498Szrj template<typename _InputIterator> 279*38fd1498Szrj _Path<_InputIterator, _InputIterator>& 280*38fd1498Szrj append(_InputIterator __first, _InputIterator __last) 281*38fd1498Szrj { return _M_append(_S_convert(__first, __last)); } 282*38fd1498Szrj 283*38fd1498Szrj // concatenation 284*38fd1498Szrj 285*38fd1498Szrj path& operator+=(const path& __x); 286*38fd1498Szrj path& operator+=(const string_type& __x); 287*38fd1498Szrj path& operator+=(const value_type* __x); 288*38fd1498Szrj path& operator+=(value_type __x); 289*38fd1498Szrj path& operator+=(basic_string_view<value_type> __x); 290*38fd1498Szrj 291*38fd1498Szrj template<typename _Source> 292*38fd1498Szrj _Path<_Source>& 293*38fd1498Szrj operator+=(_Source const& __x) { return concat(__x); } 294*38fd1498Szrj 295*38fd1498Szrj template<typename _CharT> 296*38fd1498Szrj _Path<_CharT*, _CharT*>& 297*38fd1498Szrj operator+=(_CharT __x); 298*38fd1498Szrj 299*38fd1498Szrj template<typename _Source> 300*38fd1498Szrj _Path<_Source>& 301*38fd1498Szrj concat(_Source const& __x) 302*38fd1498Szrj { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); } 303*38fd1498Szrj 304*38fd1498Szrj template<typename _InputIterator> 305*38fd1498Szrj _Path<_InputIterator, _InputIterator>& 306*38fd1498Szrj concat(_InputIterator __first, _InputIterator __last) 307*38fd1498Szrj { return *this += _S_convert(__first, __last); } 308*38fd1498Szrj 309*38fd1498Szrj // modifiers 310*38fd1498Szrj 311*38fd1498Szrj void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); } 312*38fd1498Szrj 313*38fd1498Szrj path& make_preferred(); 314*38fd1498Szrj path& remove_filename(); 315*38fd1498Szrj path& replace_filename(const path& __replacement); 316*38fd1498Szrj path& replace_extension(const path& __replacement = path()); 317*38fd1498Szrj 318*38fd1498Szrj void swap(path& __rhs) noexcept; 319*38fd1498Szrj 320*38fd1498Szrj // native format observers 321*38fd1498Szrj 322*38fd1498Szrj const string_type& native() const noexcept { return _M_pathname; } 323*38fd1498Szrj const value_type* c_str() const noexcept { return _M_pathname.c_str(); } 324*38fd1498Szrj operator string_type() const { return _M_pathname; } 325*38fd1498Szrj 326*38fd1498Szrj template<typename _CharT, typename _Traits = std::char_traits<_CharT>, 327*38fd1498Szrj typename _Allocator = std::allocator<_CharT>> 328*38fd1498Szrj std::basic_string<_CharT, _Traits, _Allocator> 329*38fd1498Szrj string(const _Allocator& __a = _Allocator()) const; 330*38fd1498Szrj 331*38fd1498Szrj std::string string() const; 332*38fd1498Szrj #if _GLIBCXX_USE_WCHAR_T 333*38fd1498Szrj std::wstring wstring() const; 334*38fd1498Szrj #endif 335*38fd1498Szrj std::string u8string() const; 336*38fd1498Szrj std::u16string u16string() const; 337*38fd1498Szrj std::u32string u32string() const; 338*38fd1498Szrj 339*38fd1498Szrj // generic format observers 340*38fd1498Szrj template<typename _CharT, typename _Traits = std::char_traits<_CharT>, 341*38fd1498Szrj typename _Allocator = std::allocator<_CharT>> 342*38fd1498Szrj std::basic_string<_CharT, _Traits, _Allocator> 343*38fd1498Szrj generic_string(const _Allocator& __a = _Allocator()) const; 344*38fd1498Szrj 345*38fd1498Szrj std::string generic_string() const; 346*38fd1498Szrj #if _GLIBCXX_USE_WCHAR_T 347*38fd1498Szrj std::wstring generic_wstring() const; 348*38fd1498Szrj #endif 349*38fd1498Szrj std::string generic_u8string() const; 350*38fd1498Szrj std::u16string generic_u16string() const; 351*38fd1498Szrj std::u32string generic_u32string() const; 352*38fd1498Szrj 353*38fd1498Szrj // compare 354*38fd1498Szrj 355*38fd1498Szrj int compare(const path& __p) const noexcept; 356*38fd1498Szrj int compare(const string_type& __s) const; 357*38fd1498Szrj int compare(const value_type* __s) const; 358*38fd1498Szrj int compare(const basic_string_view<value_type> __s) const; 359*38fd1498Szrj 360*38fd1498Szrj // decomposition 361*38fd1498Szrj 362*38fd1498Szrj path root_name() const; 363*38fd1498Szrj path root_directory() const; 364*38fd1498Szrj path root_path() const; 365*38fd1498Szrj path relative_path() const; 366*38fd1498Szrj path parent_path() const; 367*38fd1498Szrj path filename() const; 368*38fd1498Szrj path stem() const; 369*38fd1498Szrj path extension() const; 370*38fd1498Szrj 371*38fd1498Szrj // query 372*38fd1498Szrj 373*38fd1498Szrj [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); } 374*38fd1498Szrj bool has_root_name() const; 375*38fd1498Szrj bool has_root_directory() const; 376*38fd1498Szrj bool has_root_path() const; 377*38fd1498Szrj bool has_relative_path() const; 378*38fd1498Szrj bool has_parent_path() const; 379*38fd1498Szrj bool has_filename() const; 380*38fd1498Szrj bool has_stem() const; 381*38fd1498Szrj bool has_extension() const; 382*38fd1498Szrj bool is_absolute() const; 383*38fd1498Szrj bool is_relative() const { return !is_absolute(); } 384*38fd1498Szrj 385*38fd1498Szrj // generation 386*38fd1498Szrj path lexically_normal() const; 387*38fd1498Szrj path lexically_relative(const path& base) const; 388*38fd1498Szrj path lexically_proximate(const path& base) const; 389*38fd1498Szrj 390*38fd1498Szrj // iterators 391*38fd1498Szrj class iterator; 392*38fd1498Szrj typedef iterator const_iterator; 393*38fd1498Szrj 394*38fd1498Szrj iterator begin() const; 395*38fd1498Szrj iterator end() const; 396*38fd1498Szrj 397*38fd1498Szrj private: 398*38fd1498Szrj enum class _Type : unsigned char { 399*38fd1498Szrj _Multi, _Root_name, _Root_dir, _Filename 400*38fd1498Szrj }; 401*38fd1498Szrj 402*38fd1498Szrj path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type) 403*38fd1498Szrj { 404*38fd1498Szrj __glibcxx_assert(_M_type != _Type::_Multi); 405*38fd1498Szrj } 406*38fd1498Szrj 407*38fd1498Szrj enum class _Split { _Stem, _Extension }; 408*38fd1498Szrj 409*38fd1498Szrj path& _M_append(string_type&& __str) 410*38fd1498Szrj { 411*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 412*38fd1498Szrj operator/=(path(std::move(__str))); 413*38fd1498Szrj #else 414*38fd1498Szrj if (!_M_pathname.empty() && !_S_is_dir_sep(_M_pathname.back()) 415*38fd1498Szrj && (__str.empty() || !_S_is_dir_sep(__str.front()))) 416*38fd1498Szrj _M_pathname += preferred_separator; 417*38fd1498Szrj _M_pathname += __str; 418*38fd1498Szrj _M_split_cmpts(); 419*38fd1498Szrj #endif 420*38fd1498Szrj return *this; 421*38fd1498Szrj } 422*38fd1498Szrj 423*38fd1498Szrj pair<const string_type*, size_t> _M_find_extension() const; 424*38fd1498Szrj 425*38fd1498Szrj template<typename _CharT> 426*38fd1498Szrj struct _Cvt; 427*38fd1498Szrj 428*38fd1498Szrj static string_type 429*38fd1498Szrj _S_convert(value_type* __src, __null_terminated) 430*38fd1498Szrj { return string_type(__src); } 431*38fd1498Szrj 432*38fd1498Szrj static string_type 433*38fd1498Szrj _S_convert(const value_type* __src, __null_terminated) 434*38fd1498Szrj { return string_type(__src); } 435*38fd1498Szrj 436*38fd1498Szrj template<typename _Iter> 437*38fd1498Szrj static string_type 438*38fd1498Szrj _S_convert(_Iter __first, _Iter __last) 439*38fd1498Szrj { 440*38fd1498Szrj using __value_type = typename std::iterator_traits<_Iter>::value_type; 441*38fd1498Szrj return _Cvt<typename remove_cv<__value_type>::type>:: 442*38fd1498Szrj _S_convert(__first, __last); 443*38fd1498Szrj } 444*38fd1498Szrj 445*38fd1498Szrj template<typename _InputIterator> 446*38fd1498Szrj static string_type 447*38fd1498Szrj _S_convert(_InputIterator __src, __null_terminated) 448*38fd1498Szrj { 449*38fd1498Szrj using _Tp = typename std::iterator_traits<_InputIterator>::value_type; 450*38fd1498Szrj std::basic_string<typename remove_cv<_Tp>::type> __tmp; 451*38fd1498Szrj for (; *__src != _Tp{}; ++__src) 452*38fd1498Szrj __tmp.push_back(*__src); 453*38fd1498Szrj return _S_convert(__tmp.c_str(), __tmp.c_str() + __tmp.size()); 454*38fd1498Szrj } 455*38fd1498Szrj 456*38fd1498Szrj static string_type 457*38fd1498Szrj _S_convert_loc(const char* __first, const char* __last, 458*38fd1498Szrj const std::locale& __loc); 459*38fd1498Szrj 460*38fd1498Szrj template<typename _Iter> 461*38fd1498Szrj static string_type 462*38fd1498Szrj _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc) 463*38fd1498Szrj { 464*38fd1498Szrj const std::string __str(__first, __last); 465*38fd1498Szrj return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc); 466*38fd1498Szrj } 467*38fd1498Szrj 468*38fd1498Szrj template<typename _InputIterator> 469*38fd1498Szrj static string_type 470*38fd1498Szrj _S_convert_loc(_InputIterator __src, __null_terminated, 471*38fd1498Szrj const std::locale& __loc) 472*38fd1498Szrj { 473*38fd1498Szrj std::string __tmp; 474*38fd1498Szrj while (*__src != '\0') 475*38fd1498Szrj __tmp.push_back(*__src++); 476*38fd1498Szrj return _S_convert_loc(__tmp.data(), __tmp.data()+__tmp.size(), __loc); 477*38fd1498Szrj } 478*38fd1498Szrj 479*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Allocator> 480*38fd1498Szrj static basic_string<_CharT, _Traits, _Allocator> 481*38fd1498Szrj _S_str_convert(const string_type&, const _Allocator& __a); 482*38fd1498Szrj 483*38fd1498Szrj bool _S_is_dir_sep(value_type __ch) 484*38fd1498Szrj { 485*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 486*38fd1498Szrj return __ch == L'/' || __ch == preferred_separator; 487*38fd1498Szrj #else 488*38fd1498Szrj return __ch == '/'; 489*38fd1498Szrj #endif 490*38fd1498Szrj } 491*38fd1498Szrj 492*38fd1498Szrj void _M_split_cmpts(); 493*38fd1498Szrj void _M_trim(); 494*38fd1498Szrj void _M_add_root_name(size_t __n); 495*38fd1498Szrj void _M_add_root_dir(size_t __pos); 496*38fd1498Szrj void _M_add_filename(size_t __pos, size_t __n); 497*38fd1498Szrj 498*38fd1498Szrj string_type _M_pathname; 499*38fd1498Szrj 500*38fd1498Szrj struct _Cmpt; 501*38fd1498Szrj using _List = _GLIBCXX_STD_C::vector<_Cmpt>; 502*38fd1498Szrj _List _M_cmpts; // empty unless _M_type == _Type::_Multi 503*38fd1498Szrj _Type _M_type = _Type::_Multi; 504*38fd1498Szrj }; 505*38fd1498Szrj 506*38fd1498Szrj template<> 507*38fd1498Szrj struct path::__is_encoded_char<char> : std::true_type 508*38fd1498Szrj { using value_type = char; }; 509*38fd1498Szrj 510*38fd1498Szrj template<> 511*38fd1498Szrj struct path::__is_encoded_char<wchar_t> : std::true_type 512*38fd1498Szrj { using value_type = wchar_t; }; 513*38fd1498Szrj 514*38fd1498Szrj template<> 515*38fd1498Szrj struct path::__is_encoded_char<char16_t> : std::true_type 516*38fd1498Szrj { using value_type = char16_t; }; 517*38fd1498Szrj 518*38fd1498Szrj template<> 519*38fd1498Szrj struct path::__is_encoded_char<char32_t> : std::true_type 520*38fd1498Szrj { using value_type = char32_t; }; 521*38fd1498Szrj 522*38fd1498Szrj template<typename _Tp> 523*38fd1498Szrj struct path::__is_encoded_char<const _Tp> : __is_encoded_char<_Tp> { }; 524*38fd1498Szrj 525*38fd1498Szrj inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } 526*38fd1498Szrj 527*38fd1498Szrj size_t hash_value(const path& __p) noexcept; 528*38fd1498Szrj 529*38fd1498Szrj /// Compare paths 530*38fd1498Szrj inline bool operator<(const path& __lhs, const path& __rhs) noexcept 531*38fd1498Szrj { return __lhs.compare(__rhs) < 0; } 532*38fd1498Szrj 533*38fd1498Szrj /// Compare paths 534*38fd1498Szrj inline bool operator<=(const path& __lhs, const path& __rhs) noexcept 535*38fd1498Szrj { return !(__rhs < __lhs); } 536*38fd1498Szrj 537*38fd1498Szrj /// Compare paths 538*38fd1498Szrj inline bool operator>(const path& __lhs, const path& __rhs) noexcept 539*38fd1498Szrj { return __rhs < __lhs; } 540*38fd1498Szrj 541*38fd1498Szrj /// Compare paths 542*38fd1498Szrj inline bool operator>=(const path& __lhs, const path& __rhs) noexcept 543*38fd1498Szrj { return !(__lhs < __rhs); } 544*38fd1498Szrj 545*38fd1498Szrj /// Compare paths 546*38fd1498Szrj inline bool operator==(const path& __lhs, const path& __rhs) noexcept 547*38fd1498Szrj { return __lhs.compare(__rhs) == 0; } 548*38fd1498Szrj 549*38fd1498Szrj /// Compare paths 550*38fd1498Szrj inline bool operator!=(const path& __lhs, const path& __rhs) noexcept 551*38fd1498Szrj { return !(__lhs == __rhs); } 552*38fd1498Szrj 553*38fd1498Szrj /// Append one path to another 554*38fd1498Szrj inline path operator/(const path& __lhs, const path& __rhs) 555*38fd1498Szrj { return path(__lhs) /= __rhs; } 556*38fd1498Szrj 557*38fd1498Szrj /// Write a path to a stream 558*38fd1498Szrj template<typename _CharT, typename _Traits> 559*38fd1498Szrj basic_ostream<_CharT, _Traits>& 560*38fd1498Szrj operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) 561*38fd1498Szrj { 562*38fd1498Szrj auto __tmp = __p.string<_CharT, _Traits>(); 563*38fd1498Szrj using __quoted_string 564*38fd1498Szrj = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; 565*38fd1498Szrj __os << __quoted_string{__tmp, '"', '\\'}; 566*38fd1498Szrj return __os; 567*38fd1498Szrj } 568*38fd1498Szrj 569*38fd1498Szrj /// Read a path from a stream 570*38fd1498Szrj template<typename _CharT, typename _Traits> 571*38fd1498Szrj basic_istream<_CharT, _Traits>& 572*38fd1498Szrj operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) 573*38fd1498Szrj { 574*38fd1498Szrj basic_string<_CharT, _Traits> __tmp; 575*38fd1498Szrj using __quoted_string 576*38fd1498Szrj = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; 577*38fd1498Szrj if (__is >> __quoted_string{ __tmp, '"', '\\' }) 578*38fd1498Szrj __p = std::move(__tmp); 579*38fd1498Szrj return __is; 580*38fd1498Szrj } 581*38fd1498Szrj 582*38fd1498Szrj template<typename _Source> 583*38fd1498Szrj inline auto 584*38fd1498Szrj u8path(const _Source& __source) 585*38fd1498Szrj -> decltype(filesystem::path(__source, std::locale::classic())) 586*38fd1498Szrj { 587*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 588*38fd1498Szrj const std::string __u8str{__source}; 589*38fd1498Szrj return std::filesystem::u8path(__u8str.begin(), __u8str.end()); 590*38fd1498Szrj #else 591*38fd1498Szrj return path{ __source }; 592*38fd1498Szrj #endif 593*38fd1498Szrj } 594*38fd1498Szrj 595*38fd1498Szrj template<typename _InputIterator> 596*38fd1498Szrj inline auto 597*38fd1498Szrj u8path(_InputIterator __first, _InputIterator __last) 598*38fd1498Szrj -> decltype(filesystem::path(__first, __last, std::locale::classic())) 599*38fd1498Szrj { 600*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 601*38fd1498Szrj codecvt_utf8<value_type> __cvt; 602*38fd1498Szrj string_type __tmp; 603*38fd1498Szrj if (__str_codecvt_in(__first, __last, __tmp, __cvt)) 604*38fd1498Szrj return path{ __tmp }; 605*38fd1498Szrj else 606*38fd1498Szrj return {}; 607*38fd1498Szrj #else 608*38fd1498Szrj return path{ __first, __last }; 609*38fd1498Szrj #endif 610*38fd1498Szrj } 611*38fd1498Szrj 612*38fd1498Szrj class filesystem_error : public std::system_error 613*38fd1498Szrj { 614*38fd1498Szrj public: 615*38fd1498Szrj filesystem_error(const string& __what_arg, error_code __ec) 616*38fd1498Szrj : system_error(__ec, __what_arg) { } 617*38fd1498Szrj 618*38fd1498Szrj filesystem_error(const string& __what_arg, const path& __p1, 619*38fd1498Szrj error_code __ec) 620*38fd1498Szrj : system_error(__ec, __what_arg), _M_path1(__p1) { } 621*38fd1498Szrj 622*38fd1498Szrj filesystem_error(const string& __what_arg, const path& __p1, 623*38fd1498Szrj const path& __p2, error_code __ec) 624*38fd1498Szrj : system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2) 625*38fd1498Szrj { } 626*38fd1498Szrj 627*38fd1498Szrj ~filesystem_error(); 628*38fd1498Szrj 629*38fd1498Szrj const path& path1() const noexcept { return _M_path1; } 630*38fd1498Szrj const path& path2() const noexcept { return _M_path2; } 631*38fd1498Szrj const char* what() const noexcept { return _M_what.c_str(); } 632*38fd1498Szrj 633*38fd1498Szrj private: 634*38fd1498Szrj std::string _M_gen_what(); 635*38fd1498Szrj 636*38fd1498Szrj path _M_path1; 637*38fd1498Szrj path _M_path2; 638*38fd1498Szrj std::string _M_what = _M_gen_what(); 639*38fd1498Szrj }; 640*38fd1498Szrj 641*38fd1498Szrj struct path::_Cmpt : path 642*38fd1498Szrj { 643*38fd1498Szrj _Cmpt(string_type __s, _Type __t, size_t __pos) 644*38fd1498Szrj : path(std::move(__s), __t), _M_pos(__pos) { } 645*38fd1498Szrj 646*38fd1498Szrj _Cmpt() : _M_pos(-1) { } 647*38fd1498Szrj 648*38fd1498Szrj size_t _M_pos; 649*38fd1498Szrj }; 650*38fd1498Szrj 651*38fd1498Szrj // specialize _Cvt for degenerate 'noconv' case 652*38fd1498Szrj template<> 653*38fd1498Szrj struct path::_Cvt<path::value_type> 654*38fd1498Szrj { 655*38fd1498Szrj template<typename _Iter> 656*38fd1498Szrj static string_type 657*38fd1498Szrj _S_convert(_Iter __first, _Iter __last) 658*38fd1498Szrj { return string_type{__first, __last}; } 659*38fd1498Szrj }; 660*38fd1498Szrj 661*38fd1498Szrj template<typename _CharT> 662*38fd1498Szrj struct path::_Cvt 663*38fd1498Szrj { 664*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 665*38fd1498Szrj static string_type 666*38fd1498Szrj _S_wconvert(const char* __f, const char* __l, true_type) 667*38fd1498Szrj { 668*38fd1498Szrj using _Cvt = std::codecvt<wchar_t, char, mbstate_t>; 669*38fd1498Szrj const auto& __cvt = std::use_facet<_Cvt>(std::locale{}); 670*38fd1498Szrj std::wstring __wstr; 671*38fd1498Szrj if (__str_codecvt_in(__f, __l, __wstr, __cvt)) 672*38fd1498Szrj return __wstr; 673*38fd1498Szrj _GLIBCXX_THROW_OR_ABORT(filesystem_error( 674*38fd1498Szrj "Cannot convert character sequence", 675*38fd1498Szrj std::make_error_code(errc::illegal_byte_sequence))); 676*38fd1498Szrj } 677*38fd1498Szrj 678*38fd1498Szrj static string_type 679*38fd1498Szrj _S_wconvert(const _CharT* __f, const _CharT* __l, false_type) 680*38fd1498Szrj { 681*38fd1498Szrj std::codecvt_utf8<_CharT> __cvt; 682*38fd1498Szrj std::string __str; 683*38fd1498Szrj if (__str_codecvt_out(__f, __l, __str, __cvt)) 684*38fd1498Szrj { 685*38fd1498Szrj const char* __f2 = __str.data(); 686*38fd1498Szrj const char* __l2 = __f2 + __str.size(); 687*38fd1498Szrj std::codecvt_utf8<wchar_t> __wcvt; 688*38fd1498Szrj std::wstring __wstr; 689*38fd1498Szrj if (__str_codecvt_in(__f2, __l2, __wstr, __wcvt)) 690*38fd1498Szrj return __wstr; 691*38fd1498Szrj } 692*38fd1498Szrj _GLIBCXX_THROW_OR_ABORT(filesystem_error( 693*38fd1498Szrj "Cannot convert character sequence", 694*38fd1498Szrj std::make_error_code(errc::illegal_byte_sequence))); 695*38fd1498Szrj } 696*38fd1498Szrj 697*38fd1498Szrj static string_type 698*38fd1498Szrj _S_convert(const _CharT* __f, const _CharT* __l) 699*38fd1498Szrj { 700*38fd1498Szrj return _S_wconvert(__f, __l, is_same<_CharT, char>{}); 701*38fd1498Szrj } 702*38fd1498Szrj #else 703*38fd1498Szrj static string_type 704*38fd1498Szrj _S_convert(const _CharT* __f, const _CharT* __l) 705*38fd1498Szrj { 706*38fd1498Szrj std::codecvt_utf8<_CharT> __cvt; 707*38fd1498Szrj std::string __str; 708*38fd1498Szrj if (__str_codecvt_out(__f, __l, __str, __cvt)) 709*38fd1498Szrj return __str; 710*38fd1498Szrj _GLIBCXX_THROW_OR_ABORT(filesystem_error( 711*38fd1498Szrj "Cannot convert character sequence", 712*38fd1498Szrj std::make_error_code(errc::illegal_byte_sequence))); 713*38fd1498Szrj } 714*38fd1498Szrj #endif 715*38fd1498Szrj 716*38fd1498Szrj static string_type 717*38fd1498Szrj _S_convert(_CharT* __f, _CharT* __l) 718*38fd1498Szrj { 719*38fd1498Szrj return _S_convert(const_cast<const _CharT*>(__f), 720*38fd1498Szrj const_cast<const _CharT*>(__l)); 721*38fd1498Szrj } 722*38fd1498Szrj 723*38fd1498Szrj template<typename _Iter> 724*38fd1498Szrj static string_type 725*38fd1498Szrj _S_convert(_Iter __first, _Iter __last) 726*38fd1498Szrj { 727*38fd1498Szrj const std::basic_string<_CharT> __str(__first, __last); 728*38fd1498Szrj return _S_convert(__str.data(), __str.data() + __str.size()); 729*38fd1498Szrj } 730*38fd1498Szrj 731*38fd1498Szrj template<typename _Iter, typename _Cont> 732*38fd1498Szrj static string_type 733*38fd1498Szrj _S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first, 734*38fd1498Szrj __gnu_cxx::__normal_iterator<_Iter, _Cont> __last) 735*38fd1498Szrj { return _S_convert(__first.base(), __last.base()); } 736*38fd1498Szrj }; 737*38fd1498Szrj 738*38fd1498Szrj /// An iterator for the components of a path 739*38fd1498Szrj class path::iterator 740*38fd1498Szrj { 741*38fd1498Szrj public: 742*38fd1498Szrj using difference_type = std::ptrdiff_t; 743*38fd1498Szrj using value_type = path; 744*38fd1498Szrj using reference = const path&; 745*38fd1498Szrj using pointer = const path*; 746*38fd1498Szrj using iterator_category = std::bidirectional_iterator_tag; 747*38fd1498Szrj 748*38fd1498Szrj iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { } 749*38fd1498Szrj 750*38fd1498Szrj iterator(const iterator&) = default; 751*38fd1498Szrj iterator& operator=(const iterator&) = default; 752*38fd1498Szrj 753*38fd1498Szrj reference operator*() const; 754*38fd1498Szrj pointer operator->() const { return std::__addressof(**this); } 755*38fd1498Szrj 756*38fd1498Szrj iterator& operator++(); 757*38fd1498Szrj iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } 758*38fd1498Szrj 759*38fd1498Szrj iterator& operator--(); 760*38fd1498Szrj iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; } 761*38fd1498Szrj 762*38fd1498Szrj friend bool operator==(const iterator& __lhs, const iterator& __rhs) 763*38fd1498Szrj { return __lhs._M_equals(__rhs); } 764*38fd1498Szrj 765*38fd1498Szrj friend bool operator!=(const iterator& __lhs, const iterator& __rhs) 766*38fd1498Szrj { return !__lhs._M_equals(__rhs); } 767*38fd1498Szrj 768*38fd1498Szrj private: 769*38fd1498Szrj friend class path; 770*38fd1498Szrj 771*38fd1498Szrj iterator(const path* __path, path::_List::const_iterator __iter) 772*38fd1498Szrj : _M_path(__path), _M_cur(__iter), _M_at_end() 773*38fd1498Szrj { } 774*38fd1498Szrj 775*38fd1498Szrj iterator(const path* __path, bool __at_end) 776*38fd1498Szrj : _M_path(__path), _M_cur(), _M_at_end(__at_end) 777*38fd1498Szrj { } 778*38fd1498Szrj 779*38fd1498Szrj bool _M_equals(iterator) const; 780*38fd1498Szrj 781*38fd1498Szrj const path* _M_path; 782*38fd1498Szrj path::_List::const_iterator _M_cur; 783*38fd1498Szrj bool _M_at_end; // only used when type != _Multi 784*38fd1498Szrj }; 785*38fd1498Szrj 786*38fd1498Szrj 787*38fd1498Szrj inline path& 788*38fd1498Szrj path::operator=(path&& __p) noexcept 789*38fd1498Szrj { 790*38fd1498Szrj _M_pathname = std::move(__p._M_pathname); 791*38fd1498Szrj _M_cmpts = std::move(__p._M_cmpts); 792*38fd1498Szrj _M_type = __p._M_type; 793*38fd1498Szrj __p.clear(); 794*38fd1498Szrj return *this; 795*38fd1498Szrj } 796*38fd1498Szrj 797*38fd1498Szrj inline path& 798*38fd1498Szrj path::operator=(string_type&& __source) 799*38fd1498Szrj { return *this = path(std::move(__source)); } 800*38fd1498Szrj 801*38fd1498Szrj inline path& 802*38fd1498Szrj path::assign(string_type&& __source) 803*38fd1498Szrj { return *this = path(std::move(__source)); } 804*38fd1498Szrj 805*38fd1498Szrj inline path& 806*38fd1498Szrj path::operator+=(const path& __p) 807*38fd1498Szrj { 808*38fd1498Szrj return operator+=(__p.native()); 809*38fd1498Szrj } 810*38fd1498Szrj 811*38fd1498Szrj inline path& 812*38fd1498Szrj path::operator+=(const string_type& __x) 813*38fd1498Szrj { 814*38fd1498Szrj _M_pathname += __x; 815*38fd1498Szrj _M_split_cmpts(); 816*38fd1498Szrj return *this; 817*38fd1498Szrj } 818*38fd1498Szrj 819*38fd1498Szrj inline path& 820*38fd1498Szrj path::operator+=(const value_type* __x) 821*38fd1498Szrj { 822*38fd1498Szrj _M_pathname += __x; 823*38fd1498Szrj _M_split_cmpts(); 824*38fd1498Szrj return *this; 825*38fd1498Szrj } 826*38fd1498Szrj 827*38fd1498Szrj inline path& 828*38fd1498Szrj path::operator+=(value_type __x) 829*38fd1498Szrj { 830*38fd1498Szrj _M_pathname += __x; 831*38fd1498Szrj _M_split_cmpts(); 832*38fd1498Szrj return *this; 833*38fd1498Szrj } 834*38fd1498Szrj 835*38fd1498Szrj inline path& 836*38fd1498Szrj path::operator+=(basic_string_view<value_type> __x) 837*38fd1498Szrj { 838*38fd1498Szrj _M_pathname.append(__x.data(), __x.size()); 839*38fd1498Szrj _M_split_cmpts(); 840*38fd1498Szrj return *this; 841*38fd1498Szrj } 842*38fd1498Szrj 843*38fd1498Szrj template<typename _CharT> 844*38fd1498Szrj inline path::_Path<_CharT*, _CharT*>& 845*38fd1498Szrj path::operator+=(_CharT __x) 846*38fd1498Szrj { 847*38fd1498Szrj auto* __addr = std::__addressof(__x); 848*38fd1498Szrj return concat(__addr, __addr + 1); 849*38fd1498Szrj } 850*38fd1498Szrj 851*38fd1498Szrj inline path& 852*38fd1498Szrj path::make_preferred() 853*38fd1498Szrj { 854*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 855*38fd1498Szrj std::replace(_M_pathname.begin(), _M_pathname.end(), L'/', 856*38fd1498Szrj preferred_separator); 857*38fd1498Szrj #endif 858*38fd1498Szrj return *this; 859*38fd1498Szrj } 860*38fd1498Szrj 861*38fd1498Szrj inline void path::swap(path& __rhs) noexcept 862*38fd1498Szrj { 863*38fd1498Szrj _M_pathname.swap(__rhs._M_pathname); 864*38fd1498Szrj _M_cmpts.swap(__rhs._M_cmpts); 865*38fd1498Szrj std::swap(_M_type, __rhs._M_type); 866*38fd1498Szrj } 867*38fd1498Szrj 868*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Allocator> 869*38fd1498Szrj std::basic_string<_CharT, _Traits, _Allocator> 870*38fd1498Szrj path::_S_str_convert(const string_type& __str, const _Allocator& __a) 871*38fd1498Szrj { 872*38fd1498Szrj if (__str.size() == 0) 873*38fd1498Szrj return std::basic_string<_CharT, _Traits, _Allocator>(__a); 874*38fd1498Szrj 875*38fd1498Szrj const value_type* __first = __str.data(); 876*38fd1498Szrj const value_type* __last = __first + __str.size(); 877*38fd1498Szrj 878*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 879*38fd1498Szrj using _CharAlloc = __alloc_rebind<_Allocator, char>; 880*38fd1498Szrj using _String = basic_string<char, char_traits<char>, _CharAlloc>; 881*38fd1498Szrj using _WString = basic_string<_CharT, _Traits, _Allocator>; 882*38fd1498Szrj 883*38fd1498Szrj // use codecvt_utf8<wchar_t> to convert native string to UTF-8 884*38fd1498Szrj codecvt_utf8<value_type> __cvt; 885*38fd1498Szrj _String __u8str{_CharAlloc{__a}}; 886*38fd1498Szrj if (__str_codecvt_out(__first, __last, __u8str, __cvt)) 887*38fd1498Szrj { 888*38fd1498Szrj if constexpr (is_same_v<_CharT, char>) 889*38fd1498Szrj return __u8str; 890*38fd1498Szrj else 891*38fd1498Szrj { 892*38fd1498Szrj _WString __wstr; 893*38fd1498Szrj // use codecvt_utf8<_CharT> to convert UTF-8 to wide string 894*38fd1498Szrj codecvt_utf8<_CharT> __cvt; 895*38fd1498Szrj const char* __f = __u8str.data(); 896*38fd1498Szrj const char* __l = __f + __u8str.size(); 897*38fd1498Szrj if (__str_codecvt_in(__f, __l, __wstr, __cvt)) 898*38fd1498Szrj return __wstr; 899*38fd1498Szrj } 900*38fd1498Szrj } 901*38fd1498Szrj #else 902*38fd1498Szrj codecvt_utf8<_CharT> __cvt; 903*38fd1498Szrj basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; 904*38fd1498Szrj if (__str_codecvt_in(__first, __last, __wstr, __cvt)) 905*38fd1498Szrj return __wstr; 906*38fd1498Szrj #endif 907*38fd1498Szrj _GLIBCXX_THROW_OR_ABORT(filesystem_error( 908*38fd1498Szrj "Cannot convert character sequence", 909*38fd1498Szrj std::make_error_code(errc::illegal_byte_sequence))); 910*38fd1498Szrj } 911*38fd1498Szrj 912*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Allocator> 913*38fd1498Szrj inline basic_string<_CharT, _Traits, _Allocator> 914*38fd1498Szrj path::string(const _Allocator& __a) const 915*38fd1498Szrj { 916*38fd1498Szrj if constexpr (is_same_v<_CharT, value_type>) 917*38fd1498Szrj #if _GLIBCXX_USE_CXX11_ABI 918*38fd1498Szrj return { _M_pathname, __a }; 919*38fd1498Szrj #else 920*38fd1498Szrj return { _M_pathname, string_type::size_type(0), __a }; 921*38fd1498Szrj #endif 922*38fd1498Szrj else 923*38fd1498Szrj return _S_str_convert<_CharT, _Traits>(_M_pathname, __a); 924*38fd1498Szrj } 925*38fd1498Szrj 926*38fd1498Szrj inline std::string 927*38fd1498Szrj path::string() const { return string<char>(); } 928*38fd1498Szrj 929*38fd1498Szrj #if _GLIBCXX_USE_WCHAR_T 930*38fd1498Szrj inline std::wstring 931*38fd1498Szrj path::wstring() const { return string<wchar_t>(); } 932*38fd1498Szrj #endif 933*38fd1498Szrj 934*38fd1498Szrj inline std::string 935*38fd1498Szrj path::u8string() const 936*38fd1498Szrj { 937*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 938*38fd1498Szrj std::string __str; 939*38fd1498Szrj // convert from native encoding to UTF-8 940*38fd1498Szrj codecvt_utf8<value_type> __cvt; 941*38fd1498Szrj const value_type* __first = _M_pathname.data(); 942*38fd1498Szrj const value_type* __last = __first + _M_pathname.size(); 943*38fd1498Szrj if (__str_codecvt_out(__first, __last, __str, __cvt)) 944*38fd1498Szrj return __str; 945*38fd1498Szrj _GLIBCXX_THROW_OR_ABORT(filesystem_error( 946*38fd1498Szrj "Cannot convert character sequence", 947*38fd1498Szrj std::make_error_code(errc::illegal_byte_sequence))); 948*38fd1498Szrj #else 949*38fd1498Szrj return _M_pathname; 950*38fd1498Szrj #endif 951*38fd1498Szrj } 952*38fd1498Szrj 953*38fd1498Szrj inline std::u16string 954*38fd1498Szrj path::u16string() const { return string<char16_t>(); } 955*38fd1498Szrj 956*38fd1498Szrj inline std::u32string 957*38fd1498Szrj path::u32string() const { return string<char32_t>(); } 958*38fd1498Szrj 959*38fd1498Szrj template<typename _CharT, typename _Traits, typename _Allocator> 960*38fd1498Szrj inline std::basic_string<_CharT, _Traits, _Allocator> 961*38fd1498Szrj path::generic_string(const _Allocator& __a) const 962*38fd1498Szrj { 963*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 964*38fd1498Szrj const value_type __slash = L'/'; 965*38fd1498Szrj #else 966*38fd1498Szrj const value_type __slash = '/'; 967*38fd1498Szrj #endif 968*38fd1498Szrj string_type __str(__a); 969*38fd1498Szrj 970*38fd1498Szrj if (_M_type == _Type::_Root_dir) 971*38fd1498Szrj __str.assign(1, __slash); 972*38fd1498Szrj else 973*38fd1498Szrj { 974*38fd1498Szrj __str.reserve(_M_pathname.size()); 975*38fd1498Szrj bool __add_slash = false; 976*38fd1498Szrj for (auto& __elem : *this) 977*38fd1498Szrj { 978*38fd1498Szrj if (__add_slash) 979*38fd1498Szrj __str += __slash; 980*38fd1498Szrj __str += __elem._M_pathname; 981*38fd1498Szrj __add_slash = __elem._M_type == _Type::_Filename; 982*38fd1498Szrj } 983*38fd1498Szrj } 984*38fd1498Szrj 985*38fd1498Szrj if constexpr (is_same_v<_CharT, value_type>) 986*38fd1498Szrj return __str; 987*38fd1498Szrj else 988*38fd1498Szrj return _S_str_convert<_CharT, _Traits>(__str, __a); 989*38fd1498Szrj } 990*38fd1498Szrj 991*38fd1498Szrj inline std::string 992*38fd1498Szrj path::generic_string() const 993*38fd1498Szrj { return generic_string<char>(); } 994*38fd1498Szrj 995*38fd1498Szrj #if _GLIBCXX_USE_WCHAR_T 996*38fd1498Szrj inline std::wstring 997*38fd1498Szrj path::generic_wstring() const 998*38fd1498Szrj { return generic_string<wchar_t>(); } 999*38fd1498Szrj #endif 1000*38fd1498Szrj 1001*38fd1498Szrj inline std::string 1002*38fd1498Szrj path::generic_u8string() const 1003*38fd1498Szrj { return generic_string(); } 1004*38fd1498Szrj 1005*38fd1498Szrj inline std::u16string 1006*38fd1498Szrj path::generic_u16string() const 1007*38fd1498Szrj { return generic_string<char16_t>(); } 1008*38fd1498Szrj 1009*38fd1498Szrj inline std::u32string 1010*38fd1498Szrj path::generic_u32string() const 1011*38fd1498Szrj { return generic_string<char32_t>(); } 1012*38fd1498Szrj 1013*38fd1498Szrj inline int 1014*38fd1498Szrj path::compare(const string_type& __s) const { return compare(path(__s)); } 1015*38fd1498Szrj 1016*38fd1498Szrj inline int 1017*38fd1498Szrj path::compare(const value_type* __s) const { return compare(path(__s)); } 1018*38fd1498Szrj 1019*38fd1498Szrj inline int 1020*38fd1498Szrj path::compare(basic_string_view<value_type> __s) const 1021*38fd1498Szrj { return compare(path(__s)); } 1022*38fd1498Szrj 1023*38fd1498Szrj inline path 1024*38fd1498Szrj path::filename() const 1025*38fd1498Szrj { 1026*38fd1498Szrj if (empty()) 1027*38fd1498Szrj return {}; 1028*38fd1498Szrj else if (_M_type == _Type::_Filename) 1029*38fd1498Szrj return *this; 1030*38fd1498Szrj else if (_M_type == _Type::_Multi) 1031*38fd1498Szrj { 1032*38fd1498Szrj if (_M_pathname.back() == preferred_separator) 1033*38fd1498Szrj return {}; 1034*38fd1498Szrj auto& __last = *--end(); 1035*38fd1498Szrj if (__last._M_type == _Type::_Filename) 1036*38fd1498Szrj return __last; 1037*38fd1498Szrj } 1038*38fd1498Szrj return {}; 1039*38fd1498Szrj } 1040*38fd1498Szrj 1041*38fd1498Szrj inline path 1042*38fd1498Szrj path::stem() const 1043*38fd1498Szrj { 1044*38fd1498Szrj auto ext = _M_find_extension(); 1045*38fd1498Szrj if (ext.first && ext.second != 0) 1046*38fd1498Szrj return path{ext.first->substr(0, ext.second)}; 1047*38fd1498Szrj return {}; 1048*38fd1498Szrj } 1049*38fd1498Szrj 1050*38fd1498Szrj inline path 1051*38fd1498Szrj path::extension() const 1052*38fd1498Szrj { 1053*38fd1498Szrj auto ext = _M_find_extension(); 1054*38fd1498Szrj if (ext.first && ext.second != string_type::npos) 1055*38fd1498Szrj return path{ext.first->substr(ext.second)}; 1056*38fd1498Szrj return {}; 1057*38fd1498Szrj } 1058*38fd1498Szrj 1059*38fd1498Szrj inline bool 1060*38fd1498Szrj path::has_stem() const 1061*38fd1498Szrj { 1062*38fd1498Szrj auto ext = _M_find_extension(); 1063*38fd1498Szrj return ext.first && ext.second != 0; 1064*38fd1498Szrj } 1065*38fd1498Szrj 1066*38fd1498Szrj inline bool 1067*38fd1498Szrj path::has_extension() const 1068*38fd1498Szrj { 1069*38fd1498Szrj auto ext = _M_find_extension(); 1070*38fd1498Szrj return ext.first && ext.second != string_type::npos; 1071*38fd1498Szrj } 1072*38fd1498Szrj 1073*38fd1498Szrj inline bool 1074*38fd1498Szrj path::is_absolute() const 1075*38fd1498Szrj { 1076*38fd1498Szrj #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1077*38fd1498Szrj return has_root_name(); 1078*38fd1498Szrj #else 1079*38fd1498Szrj return has_root_directory(); 1080*38fd1498Szrj #endif 1081*38fd1498Szrj } 1082*38fd1498Szrj 1083*38fd1498Szrj inline path::iterator 1084*38fd1498Szrj path::begin() const 1085*38fd1498Szrj { 1086*38fd1498Szrj if (_M_type == _Type::_Multi) 1087*38fd1498Szrj return iterator(this, _M_cmpts.begin()); 1088*38fd1498Szrj return iterator(this, false); 1089*38fd1498Szrj } 1090*38fd1498Szrj 1091*38fd1498Szrj inline path::iterator 1092*38fd1498Szrj path::end() const 1093*38fd1498Szrj { 1094*38fd1498Szrj if (_M_type == _Type::_Multi) 1095*38fd1498Szrj return iterator(this, _M_cmpts.end()); 1096*38fd1498Szrj return iterator(this, true); 1097*38fd1498Szrj } 1098*38fd1498Szrj 1099*38fd1498Szrj inline path::iterator& 1100*38fd1498Szrj path::iterator::operator++() 1101*38fd1498Szrj { 1102*38fd1498Szrj __glibcxx_assert(_M_path != nullptr); 1103*38fd1498Szrj if (_M_path->_M_type == _Type::_Multi) 1104*38fd1498Szrj { 1105*38fd1498Szrj __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 1106*38fd1498Szrj ++_M_cur; 1107*38fd1498Szrj } 1108*38fd1498Szrj else 1109*38fd1498Szrj { 1110*38fd1498Szrj __glibcxx_assert(!_M_at_end); 1111*38fd1498Szrj _M_at_end = true; 1112*38fd1498Szrj } 1113*38fd1498Szrj return *this; 1114*38fd1498Szrj } 1115*38fd1498Szrj 1116*38fd1498Szrj inline path::iterator& 1117*38fd1498Szrj path::iterator::operator--() 1118*38fd1498Szrj { 1119*38fd1498Szrj __glibcxx_assert(_M_path != nullptr); 1120*38fd1498Szrj if (_M_path->_M_type == _Type::_Multi) 1121*38fd1498Szrj { 1122*38fd1498Szrj __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin()); 1123*38fd1498Szrj --_M_cur; 1124*38fd1498Szrj } 1125*38fd1498Szrj else 1126*38fd1498Szrj { 1127*38fd1498Szrj __glibcxx_assert(_M_at_end); 1128*38fd1498Szrj _M_at_end = false; 1129*38fd1498Szrj } 1130*38fd1498Szrj return *this; 1131*38fd1498Szrj } 1132*38fd1498Szrj 1133*38fd1498Szrj inline path::iterator::reference 1134*38fd1498Szrj path::iterator::operator*() const 1135*38fd1498Szrj { 1136*38fd1498Szrj __glibcxx_assert(_M_path != nullptr); 1137*38fd1498Szrj if (_M_path->_M_type == _Type::_Multi) 1138*38fd1498Szrj { 1139*38fd1498Szrj __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 1140*38fd1498Szrj return *_M_cur; 1141*38fd1498Szrj } 1142*38fd1498Szrj return *_M_path; 1143*38fd1498Szrj } 1144*38fd1498Szrj 1145*38fd1498Szrj inline bool 1146*38fd1498Szrj path::iterator::_M_equals(iterator __rhs) const 1147*38fd1498Szrj { 1148*38fd1498Szrj if (_M_path != __rhs._M_path) 1149*38fd1498Szrj return false; 1150*38fd1498Szrj if (_M_path == nullptr) 1151*38fd1498Szrj return true; 1152*38fd1498Szrj if (_M_path->_M_type == path::_Type::_Multi) 1153*38fd1498Szrj return _M_cur == __rhs._M_cur; 1154*38fd1498Szrj return _M_at_end == __rhs._M_at_end; 1155*38fd1498Szrj } 1156*38fd1498Szrj 1157*38fd1498Szrj // @} group filesystem 1158*38fd1498Szrj _GLIBCXX_END_NAMESPACE_CXX11 1159*38fd1498Szrj } // namespace filesystem 1160*38fd1498Szrj 1161*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION 1162*38fd1498Szrj } // namespace std 1163*38fd1498Szrj 1164*38fd1498Szrj #endif // C++17 1165*38fd1498Szrj 1166*38fd1498Szrj #endif // _GLIBCXX_FS_PATH_H 1167