The C and C++ Include Header Files
/usr/include/c++/11/bits/fs_path.h
$ cat -n /usr/include/c++/11/bits/fs_path.h 1 // Class filesystem::path -*- C++ -*- 2 3 // Copyright (C) 2014-2021 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 //
. 24 25 /** @file include/bits/fs_path.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{filesystem} 28 */ 29 30 #ifndef _GLIBCXX_FS_PATH_H 31 #define _GLIBCXX_FS_PATH_H 1 32 33 #if __cplusplus >= 201703L 34 35 #include
36 #include
37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43 #include
44 #include
45 #include
46 #include
47 #include
48 49 #if __cplusplus > 201703L 50 # include
51 #endif 52 53 #if defined(_WIN32) && !defined(__CYGWIN__) 54 # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 55 # include
56 #endif 57 58 namespace std _GLIBCXX_VISIBILITY(default) 59 { 60 _GLIBCXX_BEGIN_NAMESPACE_VERSION 61 62 namespace filesystem 63 { 64 _GLIBCXX_BEGIN_NAMESPACE_CXX11 65 66 class path; 67 68 /// @cond undocumented 69 namespace __detail 70 { 71 /// @addtogroup filesystem 72 /// @{ 73 template
74 inline constexpr bool __is_encoded_char = false; 75 template<> 76 inline constexpr bool __is_encoded_char
= true; 77 #ifdef _GLIBCXX_USE_CHAR8_T 78 template<> 79 inline constexpr bool __is_encoded_char
= true; 80 #endif 81 #if _GLIBCXX_USE_WCHAR_T 82 template<> 83 inline constexpr bool __is_encoded_char
= true; 84 #endif 85 template<> 86 inline constexpr bool __is_encoded_char
= true; 87 template<> 88 inline constexpr bool __is_encoded_char
= true; 89 90 #if __cpp_concepts >= 201907L 91 template
92 using __safe_iterator_traits = std::iterator_traits<_Iter>; 93 #else 94 template
95 struct __safe_iterator_traits : std::iterator_traits<_Iter> 96 { }; 97 98 // Protect against ill-formed iterator_traits specializations in C++17 99 template<> struct __safe_iterator_traits
{ }; 100 template<> struct __safe_iterator_traits
{ }; 101 template<> struct __safe_iterator_traits
{ }; 102 template<> struct __safe_iterator_traits
{ }; 103 #endif 104 105 template
106 struct __is_path_iter_src 107 : false_type 108 { }; 109 110 template
111 struct __is_path_iter_src<_Iter_traits, 112 void_t
> 113 : bool_constant<__is_encoded_char
> 114 { }; 115 116 template
117 inline constexpr bool __is_path_src 118 = __is_path_iter_src
>>::value; 119 120 template<> 121 inline constexpr bool __is_path_src
= false; 122 123 template<> 124 inline constexpr bool __is_path_src
= false; 125 126 template<> 127 inline constexpr bool __is_path_src
= false; 128 129 template<> 130 inline constexpr bool __is_path_src
= false; 131 132 template<> 133 inline constexpr bool __is_path_src
= false; 134 135 template<> 136 inline constexpr bool __is_path_src
= false; 137 138 template
139 inline constexpr bool 140 __is_path_src
> 141 = __is_encoded_char<_CharT>; 142 143 template
144 inline constexpr bool 145 __is_path_src
> 146 = __is_encoded_char<_CharT>; 147 148 // SFINAE constraint for Source parameters as required by [fs.path.req]. 149 template
150 using _Path = enable_if_t<__is_path_src<_Tp>, path>; 151 152 // SFINAE constraint for InputIterator parameters as required by [fs.req]. 153 template
> 154 using _Path2 = enable_if_t<__is_path_iter_src<_Tr>::value, path>; 155 156 // The __effective_range overloads convert a Source parameter into 157 // either a basic_string_view or basic_string containing the 158 // effective range of the Source, as defined in [fs.path.req]. 159 160 template
161 inline basic_string_view<_CharT, _Traits> 162 __effective_range(const basic_string<_CharT, _Traits, _Alloc>& __source) 163 { return __source; } 164 165 template
166 inline const basic_string_view<_CharT, _Traits>& 167 __effective_range(const basic_string_view<_CharT, _Traits>& __source) 168 { return __source; } 169 170 template
171 inline auto 172 __effective_range(const _Source& __source) 173 { 174 if constexpr (is_pointer_v
>) 175 return basic_string_view{&*__source}; 176 else 177 { 178 // _Source is an input iterator that iterates over an NTCTS. 179 // Create a basic_string by reading until the null character. 180 using value_type 181 = typename iterator_traits<_Source>::value_type; 182 basic_string
__str; 183 _Source __it = __source; 184 for (value_type __ch = *__it; __ch != value_type(); __ch = *++__it) 185 __str.push_back(__ch); 186 return __str; 187 } 188 } 189 190 // The value type of a Source parameter's effective range. 191 template
192 using __value_t = typename remove_reference_t< 193 decltype(__detail::__effective_range(std::declval<_Tp>()))>::value_type; 194 195 // SFINAE helper to check that an effective range has value_type char, 196 // as required by path constructors taking a std::locale parameter. 197 // The type _Tp must have already been checked by _Path
or _Path2<_Tp>. 198 template
> 199 using __value_type_is_char 200 = std::enable_if_t
, _Val>; 201 202 // As above, but also allows char8_t, as required by u8path 203 // C++20 [depr.fs.path.factory] 204 template
> 205 using __value_type_is_char_or_char8_t 206 = std::enable_if_t
207 #ifdef _GLIBCXX_USE_CHAR8_T 208 || std::is_same_v<_Val, char8_t> 209 #endif 210 , _Val>; 211 212 // Create a string or string view from an iterator range. 213 template
214 inline auto 215 __string_from_range(_InputIterator __first, _InputIterator __last) 216 { 217 using _EcharT 218 = typename std::iterator_traits<_InputIterator>::value_type; 219 static_assert(__is_encoded_char<_EcharT>); 220 221 #if __cpp_lib_concepts 222 constexpr bool __contiguous = std::contiguous_iterator<_InputIterator>; 223 #else 224 constexpr bool __contiguous 225 = is_pointer_v
; 226 #endif 227 if constexpr (__contiguous) 228 { 229 // For contiguous iterators we can just return a string view. 230 const auto* __f = std::__to_address(std::__niter_base(__first)); 231 const auto* __l = std::__to_address(std::__niter_base(__last)); 232 return basic_string_view<_EcharT>(__f, __l - __f); 233 } 234 else 235 // Conversion requires contiguous characters, so create a string. 236 return basic_string<_EcharT>(__first, __last); 237 } 238 239 /// @} group filesystem 240 } // namespace __detail 241 /// @endcond 242 243 /// @addtogroup filesystem 244 /// @{ 245 246 /// A filesystem path 247 /// @ingroup filesystem 248 class path 249 { 250 public: 251 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 252 using value_type = wchar_t; 253 static constexpr value_type preferred_separator = L'\\'; 254 #else 255 # ifdef _GLIBCXX_DOXYGEN 256 /// Windows uses wchar_t for path::value_type, POSIX uses char. 257 using value_type = __os_dependent__; 258 # else 259 using value_type = char; 260 # endif 261 static constexpr value_type preferred_separator = '/'; 262 #endif 263 using string_type = std::basic_string
; 264 265 /// path::format is ignored in this implementation 266 enum format : unsigned char { native_format, generic_format, auto_format }; 267 268 // constructors and destructor 269 270 path() noexcept { } 271 272 path(const path& __p) = default; 273 274 path(path&& __p) 275 #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_FULLY_DYNAMIC_STRING == 0 276 noexcept 277 #endif 278 : _M_pathname(std::move(__p._M_pathname)), 279 _M_cmpts(std::move(__p._M_cmpts)) 280 { __p.clear(); } 281 282 path(string_type&& __source, format = auto_format) 283 : _M_pathname(std::move(__source)) 284 { _M_split_cmpts(); } 285 286 template
> 288 path(_Source const& __source, format = auto_format) 289 : _M_pathname(_S_convert(__detail::__effective_range(__source))) 290 { _M_split_cmpts(); } 291 292 template
> 294 path(_InputIterator __first, _InputIterator __last, format = auto_format) 295 : _M_pathname(_S_convert(__detail::__string_from_range(__first, __last))) 296 { _M_split_cmpts(); } 297 298 template
, 300 typename _Require2 = __detail::__value_type_is_char<_Source>> 301 path(_Source const& __src, const locale& __loc, format = auto_format) 302 : _M_pathname(_S_convert_loc(__detail::__effective_range(__src), __loc)) 303 { _M_split_cmpts(); } 304 305 template
, 307 typename _Req2 = __detail::__value_type_is_char<_InputIterator>> 308 path(_InputIterator __first, _InputIterator __last, const locale& __loc, 309 format = auto_format) 310 : _M_pathname(_S_convert_loc(__first, __last, __loc)) 311 { _M_split_cmpts(); } 312 313 ~path() = default; 314 315 // assignments 316 317 path& operator=(const path&); 318 path& operator=(path&&) noexcept; 319 path& operator=(string_type&& __source); 320 path& assign(string_type&& __source); 321 322 template
323 __detail::_Path<_Source>& 324 operator=(_Source const& __source) 325 { return *this = path(__source); } 326 327 template
328 __detail::_Path<_Source>& 329 assign(_Source const& __source) 330 { return *this = path(__source); } 331 332 template
333 __detail::_Path2<_InputIterator>& 334 assign(_InputIterator __first, _InputIterator __last) 335 { return *this = path(__first, __last); } 336 337 // appends 338 339 path& operator/=(const path& __p); 340 341 template
342 __detail::_Path<_Source>& 343 operator/=(_Source const& __source) 344 { 345 _M_append(_S_convert(__detail::__effective_range(__source))); 346 return *this; 347 } 348 349 template
350 __detail::_Path<_Source>& 351 append(_Source const& __source) 352 { 353 _M_append(_S_convert(__detail::__effective_range(__source))); 354 return *this; 355 } 356 357 template
358 __detail::_Path2<_InputIterator>& 359 append(_InputIterator __first, _InputIterator __last) 360 { 361 _M_append(_S_convert(__detail::__string_from_range(__first, __last))); 362 return *this; 363 } 364 365 // concatenation 366 367 path& operator+=(const path& __x); 368 path& operator+=(const string_type& __x); 369 path& operator+=(const value_type* __x); 370 path& operator+=(value_type __x); 371 path& operator+=(basic_string_view
__x); 372 373 template
374 __detail::_Path<_Source>& 375 operator+=(_Source const& __x) { return concat(__x); } 376 377 template
378 __detail::_Path2<_CharT*>& 379 operator+=(_CharT __x); 380 381 template
382 __detail::_Path<_Source>& 383 concat(_Source const& __x) 384 { 385 _M_concat(_S_convert(__detail::__effective_range(__x))); 386 return *this; 387 } 388 389 template
390 __detail::_Path2<_InputIterator>& 391 concat(_InputIterator __first, _InputIterator __last) 392 { 393 _M_concat(_S_convert(__detail::__string_from_range(__first, __last))); 394 return *this; 395 } 396 397 // modifiers 398 399 void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); } 400 401 path& make_preferred(); 402 path& remove_filename(); 403 path& replace_filename(const path& __replacement); 404 path& replace_extension(const path& __replacement = path()); 405 406 void swap(path& __rhs) noexcept; 407 408 // native format observers 409 410 const string_type& native() const noexcept { return _M_pathname; } 411 const value_type* c_str() const noexcept { return _M_pathname.c_str(); } 412 operator string_type() const { return _M_pathname; } 413 414 template
, 415 typename _Allocator = std::allocator<_CharT>> 416 std::basic_string<_CharT, _Traits, _Allocator> 417 string(const _Allocator& __a = _Allocator()) const; 418 419 std::string string() const; 420 #if _GLIBCXX_USE_WCHAR_T 421 std::wstring wstring() const; 422 #endif 423 #ifdef _GLIBCXX_USE_CHAR8_T 424 __attribute__((__abi_tag__("__u8"))) 425 std::u8string u8string() const; 426 #else 427 std::string u8string() const; 428 #endif // _GLIBCXX_USE_CHAR8_T 429 std::u16string u16string() const; 430 std::u32string u32string() const; 431 432 // generic format observers 433 template
, 434 typename _Allocator = std::allocator<_CharT>> 435 std::basic_string<_CharT, _Traits, _Allocator> 436 generic_string(const _Allocator& __a = _Allocator()) const; 437 438 std::string generic_string() const; 439 #if _GLIBCXX_USE_WCHAR_T 440 std::wstring generic_wstring() const; 441 #endif 442 #ifdef _GLIBCXX_USE_CHAR8_T 443 __attribute__((__abi_tag__("__u8"))) 444 std::u8string generic_u8string() const; 445 #else 446 std::string generic_u8string() const; 447 #endif // _GLIBCXX_USE_CHAR8_T 448 std::u16string generic_u16string() const; 449 std::u32string generic_u32string() const; 450 451 // compare 452 453 int compare(const path& __p) const noexcept; 454 int compare(const string_type& __s) const noexcept; 455 int compare(const value_type* __s) const noexcept; 456 int compare(basic_string_view
__s) const noexcept; 457 458 // decomposition 459 460 path root_name() const; 461 path root_directory() const; 462 path root_path() const; 463 path relative_path() const; 464 path parent_path() const; 465 path filename() const; 466 path stem() const; 467 path extension() const; 468 469 // query 470 471 [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); } 472 bool has_root_name() const noexcept; 473 bool has_root_directory() const noexcept; 474 bool has_root_path() const noexcept; 475 bool has_relative_path() const noexcept; 476 bool has_parent_path() const noexcept; 477 bool has_filename() const noexcept; 478 bool has_stem() const noexcept; 479 bool has_extension() const noexcept; 480 bool is_absolute() const noexcept; 481 bool is_relative() const noexcept { return !is_absolute(); } 482 483 // generation 484 path lexically_normal() const; 485 path lexically_relative(const path& base) const; 486 path lexically_proximate(const path& base) const; 487 488 // iterators 489 class iterator; 490 using const_iterator = iterator; 491 492 iterator begin() const; 493 iterator end() const; 494 495 /// Write a path to a stream 496 template
497 friend std::basic_ostream<_CharT, _Traits>& 498 operator<<(std::basic_ostream<_CharT, _Traits>& __os, const path& __p) 499 { 500 __os << std::quoted(__p.string<_CharT, _Traits>()); 501 return __os; 502 } 503 504 /// Read a path from a stream 505 template
506 friend std::basic_istream<_CharT, _Traits>& 507 operator>>(std::basic_istream<_CharT, _Traits>& __is, path& __p) 508 { 509 std::basic_string<_CharT, _Traits> __tmp; 510 if (__is >> std::quoted(__tmp)) 511 __p = std::move(__tmp); 512 return __is; 513 } 514 515 // non-member operators 516 517 /// Compare paths 518 friend bool operator==(const path& __lhs, const path& __rhs) noexcept 519 { return path::_S_compare(__lhs, __rhs) == 0; } 520 521 #if __cpp_lib_three_way_comparison 522 /// Compare paths 523 friend strong_ordering 524 operator<=>(const path& __lhs, const path& __rhs) noexcept 525 { return path::_S_compare(__lhs, __rhs) <=> 0; } 526 #else 527 /// Compare paths 528 friend bool operator!=(const path& __lhs, const path& __rhs) noexcept 529 { return !(__lhs == __rhs); } 530 531 /// Compare paths 532 friend bool operator<(const path& __lhs, const path& __rhs) noexcept 533 { return __lhs.compare(__rhs) < 0; } 534 535 /// Compare paths 536 friend bool operator<=(const path& __lhs, const path& __rhs) noexcept 537 { return !(__rhs < __lhs); } 538 539 /// Compare paths 540 friend bool operator>(const path& __lhs, const path& __rhs) noexcept 541 { return __rhs < __lhs; } 542 543 /// Compare paths 544 friend bool operator>=(const path& __lhs, const path& __rhs) noexcept 545 { return !(__lhs < __rhs); } 546 #endif 547 548 /// Append one path to another 549 friend path operator/(const path& __lhs, const path& __rhs) 550 { 551 path __result(__lhs); 552 __result /= __rhs; 553 return __result; 554 } 555 556 private: 557 enum class _Type : unsigned char { 558 _Multi = 0, _Root_name, _Root_dir, _Filename 559 }; 560 561 path(basic_string_view
__str, _Type __type); 562 563 enum class _Split { _Stem, _Extension }; 564 565 void _M_append(basic_string_view
); 566 void _M_concat(basic_string_view
); 567 568 pair
_M_find_extension() const noexcept; 569 570 // path::_S_convert creates a basic_string
or 571 // basic_string_view
from a range (either the effective 572 // range of a Source parameter, or a pair of InputIterator parameters), 573 // performing the conversions required by [fs.path.type.cvt]. 574 // If the value_type of the range value type is path::value_type, 575 // no encoding conversion is performed. If the range is contiguous 576 // a string_view 577 578 static string_type 579 _S_convert(string_type __str) 580 { return __str; } 581 582 template
583 static auto 584 _S_convert(const _Tp& __str) 585 { 586 if constexpr (is_same_v<_Tp, string_type>) 587 return __str; 588 else if constexpr (is_same_v<_Tp, basic_string_view
>) 589 return __str; 590 else if constexpr (is_same_v
) 591 return basic_string_view
(__str.data(), __str.size()); 592 else 593 return _S_convert(__str.data(), __str.data() + __str.size()); 594 } 595 596 template
597 static auto 598 _S_convert(const _EcharT* __first, const _EcharT* __last); 599 600 static string_type 601 _S_convert_loc(const char* __first, const char* __last, 602 const std::locale& __loc); 603 604 template
605 static string_type 606 _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc) 607 { 608 const auto __s = __detail::__string_from_range(__first, __last); 609 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc); 610 } 611 612 template
613 static string_type 614 _S_convert_loc(const _Tp& __s, const std::locale& __loc) 615 { 616 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc); 617 } 618 619 template
620 static basic_string<_CharT, _Traits, _Allocator> 621 _S_str_convert(basic_string_view
, const _Allocator&); 622 623 // Returns lhs.compare(rhs), but defined after path::iterator is complete. 624 __attribute__((__always_inline__)) 625 static int 626 _S_compare(const path& __lhs, const path& __rhs) noexcept; 627 628 void _M_split_cmpts(); 629 630 _Type _M_type() const noexcept { return _M_cmpts.type(); } 631 632 string_type _M_pathname; 633 634 struct _Cmpt; 635 636 struct _List 637 { 638 using value_type = _Cmpt; 639 using iterator = value_type*; 640 using const_iterator = const value_type*; 641 642 _List(); 643 _List(const _List&); 644 _List(_List&&) = default; 645 _List& operator=(const _List&); 646 _List& operator=(_List&&) = default; 647 ~_List() = default; 648 649 _Type type() const noexcept 650 { return _Type(reinterpret_cast
(_M_impl.get()) & 0x3); } 651 652 void type(_Type) noexcept; 653 654 int size() const noexcept; // zero unless type() == _Type::_Multi 655 bool empty() const noexcept; // true unless type() == _Type::_Multi 656 void clear(); 657 void swap(_List& __l) noexcept { _M_impl.swap(__l._M_impl); } 658 int capacity() const noexcept; 659 void reserve(int, bool); ///< @pre type() == _Type::_Multi 660 661 // All the member functions below here have a precondition !empty() 662 // (and they should only be called from within the library). 663 664 iterator begin() noexcept; 665 iterator end() noexcept; 666 const_iterator begin() const noexcept; 667 const_iterator end() const noexcept; 668 669 value_type& front() noexcept; 670 value_type& back() noexcept; 671 const value_type& front() const noexcept; 672 const value_type& back() const noexcept; 673 674 void pop_back(); 675 void _M_erase_from(const_iterator __pos); // erases [__pos,end()) 676 677 struct _Impl; 678 struct _Impl_deleter 679 { 680 void operator()(_Impl*) const noexcept; 681 }; 682 unique_ptr<_Impl, _Impl_deleter> _M_impl; 683 }; 684 _List _M_cmpts; 685 686 struct _Parser; 687 688 template
struct _Codecvt; 689 }; 690 691 /// @{ 692 /// @relates std::filesystem::path 693 694 inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } 695 696 size_t hash_value(const path& __p) noexcept; 697 698 /// @} 699 700 /// Exception type thrown by the Filesystem library 701 class filesystem_error : public std::system_error 702 { 703 public: 704 filesystem_error(const string& __what_arg, error_code __ec); 705 706 filesystem_error(const string& __what_arg, const path& __p1, 707 error_code __ec); 708 709 filesystem_error(const string& __what_arg, const path& __p1, 710 const path& __p2, error_code __ec); 711 712 filesystem_error(const filesystem_error&) = default; 713 filesystem_error& operator=(const filesystem_error&) = default; 714 715 // No move constructor or assignment operator. 716 // Copy rvalues instead, so that _M_impl is not left empty. 717 718 ~filesystem_error(); 719 720 const path& path1() const noexcept; 721 const path& path2() const noexcept; 722 const char* what() const noexcept; 723 724 private: 725 struct _Impl; 726 std::__shared_ptr
_M_impl; 727 }; 728 729 /// @cond undocumented 730 namespace __detail 731 { 732 [[noreturn]] inline void 733 __throw_conversion_error() 734 { 735 _GLIBCXX_THROW_OR_ABORT(filesystem_error( 736 "Cannot convert character sequence", 737 std::make_error_code(errc::illegal_byte_sequence))); 738 } 739 740 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 741 template
742 inline std::wstring 743 __wstr_from_utf8(const _Tp& __str) 744 { 745 static_assert(std::is_same_v
); 746 std::wstring __wstr; 747 // XXX This assumes native wide encoding is UTF-16. 748 std::codecvt_utf8_utf16
__wcvt; 749 const auto __p = __str.data(); 750 if (!__str_codecvt_in_all(__p, __p + __str.size(), __wstr, __wcvt)) 751 __detail::__throw_conversion_error(); 752 return __wstr; 753 } 754 #endif 755 756 } // namespace __detail 757 /// @endcond 758 759 760 /** Create a path from a UTF-8-encoded sequence of char 761 * 762 * @relates std::filesystem::path 763 */ 764 template
, 766 typename _CharT 767 = __detail::__value_type_is_char_or_char8_t<_InputIterator>> 768 inline path 769 u8path(_InputIterator __first, _InputIterator __last) 770 { 771 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 772 if constexpr (is_same_v<_CharT, char>) 773 return path{ __detail::__wstr_from_utf8( 774 __detail::__string_from_range(__first, __last)) }; 775 else 776 return path{ __first, __last }; // constructor handles char8_t 777 #else 778 // This assumes native normal encoding is UTF-8. 779 return path{ __first, __last }; 780 #endif 781 } 782 783 /** Create a path from a UTF-8-encoded sequence of char 784 * 785 * @relates std::filesystem::path 786 */ 787 template
, 789 typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>> 790 inline path 791 u8path(const _Source& __source) 792 { 793 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 794 if constexpr (is_same_v<_CharT, char>) 795 return path{ __detail::__wstr_from_utf8( 796 __detail::__effective_range(__source)) }; 797 else 798 return path{ __source }; // constructor handles char8_t 799 #else 800 // This assumes native normal encoding is UTF-8. 801 return path{ __source }; 802 #endif 803 } 804 805 /// @cond undocumented 806 807 struct path::_Cmpt : path 808 { 809 _Cmpt(basic_string_view
__s, _Type __t, size_t __pos); 810 811 _Cmpt() : _M_pos(-1) { } 812 813 size_t _M_pos; 814 }; 815 816 // path::_Codecvt
Performs conversions between C and path::string_type. 817 // The native encoding of char strings is the OS-dependent current 818 // encoding for pathnames. FIXME: We assume this is UTF-8 everywhere, 819 // but should use a Windows API to query it. 820 821 // Converts between native pathname encoding and char16_t or char32_t. 822 template
823 struct path::_Codecvt 824 // Need derived class here because std::codecvt has protected destructor. 825 : std::codecvt<_EcharT, char, mbstate_t> 826 { }; 827 828 // Converts between native pathname encoding and native wide encoding. 829 // The native encoding for wide strings is the execution wide-character 830 // set encoding. FIXME: We assume that this is either UTF-32 or UTF-16 831 // (depending on the width of wchar_t). That matches GCC's default, 832 // but can be changed with -fwide-exec-charset. 833 // We need a custom codecvt converting the native pathname encoding 834 // to/from the native wide encoding. 835 template<> 836 struct path::_Codecvt
837 : conditional_t
, // UTF-8 <-> UTF-32 839 std::codecvt_utf8_utf16
> // UTF-8 <-> UTF-16 840 { }; 841 842 template
843 auto 844 path::_S_convert(const _EcharT* __f, const _EcharT* __l) 845 { 846 static_assert(__detail::__is_encoded_char<_EcharT>); 847 848 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 849 # define _GLIBCXX_CONV_FROM_UTF8(S) __detail::__wstr_from_utf8(S) 850 #else 851 # define _GLIBCXX_CONV_FROM_UTF8(S) S 852 #endif 853 854 if constexpr (is_same_v<_EcharT, value_type>) 855 return basic_string_view
(__f, __l - __f); 856 #ifdef _GLIBCXX_USE_CHAR8_T 857 else if constexpr (is_same_v<_EcharT, char8_t>) 858 { 859 string_view __str(reinterpret_cast
(__f), __l - __f); 860 return _GLIBCXX_CONV_FROM_UTF8(__str); 861 } 862 #endif 863 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 864 else if constexpr (is_same_v<_EcharT, char>) 865 { 866 std::wstring __wstr; 867 path::_Codecvt
__cvt; 868 if (__str_codecvt_in_all(__f, __l, __wstr, __cvt)) 869 return __wstr; 870 } 871 #endif 872 else 873 { 874 path::_Codecvt<_EcharT> __cvt; 875 std::string __str; 876 if (__str_codecvt_out_all(__f, __l, __str, __cvt)) 877 return _GLIBCXX_CONV_FROM_UTF8(__str); 878 } 879 __detail::__throw_conversion_error(); 880 } 881 #undef _GLIBCXX_CONV_FROM_UTF8 882 883 /// @endcond 884 885 /// An iterator for the components of a path 886 class path::iterator 887 { 888 public: 889 using difference_type = std::ptrdiff_t; 890 using value_type = path; 891 using reference = const path&; 892 using pointer = const path*; 893 using iterator_category = std::bidirectional_iterator_tag; 894 895 iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { } 896 897 iterator(const iterator&) = default; 898 iterator& operator=(const iterator&) = default; 899 900 reference operator*() const; 901 pointer operator->() const { return std::__addressof(**this); } 902 903 iterator& operator++(); 904 iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } 905 906 iterator& operator--(); 907 iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; } 908 909 friend bool operator==(const iterator& __lhs, const iterator& __rhs) 910 { return __lhs._M_equals(__rhs); } 911 912 friend bool operator!=(const iterator& __lhs, const iterator& __rhs) 913 { return !__lhs._M_equals(__rhs); } 914 915 private: 916 friend class path; 917 918 bool _M_is_multi() const { return _M_path->_M_type() == _Type::_Multi; } 919 920 friend difference_type 921 __path_iter_distance(const iterator& __first, const iterator& __last) 922 { 923 __glibcxx_assert(__first._M_path != nullptr); 924 __glibcxx_assert(__first._M_path == __last._M_path); 925 if (__first._M_is_multi()) 926 return std::distance(__first._M_cur, __last._M_cur); 927 else if (__first._M_at_end == __last._M_at_end) 928 return 0; 929 else 930 return __first._M_at_end ? -1 : 1; 931 } 932 933 friend void 934 __path_iter_advance(iterator& __i, difference_type __n) 935 { 936 if (__n == 1) 937 ++__i; 938 else if (__n == -1) 939 --__i; 940 else if (__n != 0) 941 { 942 __glibcxx_assert(__i._M_path != nullptr); 943 __glibcxx_assert(__i._M_is_multi()); 944 // __glibcxx_assert(__i._M_path->_M_cmpts.end() - __i._M_cur >= __n); 945 __i._M_cur += __n; 946 } 947 } 948 949 iterator(const path* __path, path::_List::const_iterator __iter) 950 : _M_path(__path), _M_cur(__iter), _M_at_end() 951 { } 952 953 iterator(const path* __path, bool __at_end) 954 : _M_path(__path), _M_cur(), _M_at_end(__at_end) 955 { } 956 957 bool _M_equals(iterator) const; 958 959 const path* _M_path; 960 path::_List::const_iterator _M_cur; 961 bool _M_at_end; // only used when type != _Multi 962 }; 963 964 965 inline path& 966 path::operator=(path&& __p) noexcept 967 { 968 if (&__p == this) [[__unlikely__]] 969 return *this; 970 971 _M_pathname = std::move(__p._M_pathname); 972 _M_cmpts = std::move(__p._M_cmpts); 973 __p.clear(); 974 return *this; 975 } 976 977 inline path& 978 path::operator=(string_type&& __source) 979 { return *this = path(std::move(__source)); } 980 981 inline path& 982 path::assign(string_type&& __source) 983 { return *this = path(std::move(__source)); } 984 985 inline path& 986 path::operator+=(const string_type& __x) 987 { 988 _M_concat(__x); 989 return *this; 990 } 991 992 inline path& 993 path::operator+=(const value_type* __x) 994 { 995 _M_concat(__x); 996 return *this; 997 } 998 999 inline path& 1000 path::operator+=(value_type __x) 1001 { 1002 _M_concat(basic_string_view
(&__x, 1)); 1003 return *this; 1004 } 1005 1006 inline path& 1007 path::operator+=(basic_string_view
__x) 1008 { 1009 _M_concat(__x); 1010 return *this; 1011 } 1012 1013 template
1014 inline __detail::_Path2<_CharT*>& 1015 path::operator+=(const _CharT __x) 1016 { 1017 _M_concat(_S_convert(&__x, &__x + 1)); 1018 return *this; 1019 } 1020 1021 inline path& 1022 path::make_preferred() 1023 { 1024 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1025 std::replace(_M_pathname.begin(), _M_pathname.end(), L'/', 1026 preferred_separator); 1027 #endif 1028 return *this; 1029 } 1030 1031 inline void path::swap(path& __rhs) noexcept 1032 { 1033 _M_pathname.swap(__rhs._M_pathname); 1034 _M_cmpts.swap(__rhs._M_cmpts); 1035 } 1036 1037 /// @cond undocumented 1038 template
1039 std::basic_string<_CharT, _Traits, _Allocator> 1040 path::_S_str_convert(basic_string_view
__str, 1041 const _Allocator& __a) 1042 { 1043 static_assert(!is_same_v<_CharT, value_type>); 1044 1045 using _WString = basic_string<_CharT, _Traits, _Allocator>; 1046 1047 if (__str.size() == 0) 1048 return _WString(__a); 1049 1050 #ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1051 string_view __u8str = __str; 1052 #else 1053 // First convert native string from UTF-16 to to UTF-8. 1054 // XXX This assumes that the execution wide-character set is UTF-16. 1055 std::codecvt_utf8_utf16
__cvt; 1056 1057 using _CharAlloc = __alloc_rebind<_Allocator, char>; 1058 using _String = basic_string
, _CharAlloc>; 1059 _String __u8str{_CharAlloc{__a}}; 1060 const value_type* __wfirst = __str.data(); 1061 const value_type* __wlast = __wfirst + __str.size(); 1062 if (!__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt)) 1063 __detail::__throw_conversion_error(); 1064 if constexpr (is_same_v<_CharT, char>) 1065 return __u8str; // XXX assumes native ordinary encoding is UTF-8. 1066 else 1067 #endif 1068 { 1069 const char* __first = __u8str.data(); 1070 const char* __last = __first + __u8str.size(); 1071 1072 // Convert UTF-8 string to requested format. 1073 #ifdef _GLIBCXX_USE_CHAR8_T 1074 if constexpr (is_same_v<_CharT, char8_t>) 1075 return _WString(__first, __last, __a); 1076 else 1077 #endif 1078 { 1079 // Convert UTF-8 to wide string. 1080 _WString __wstr(__a); 1081 path::_Codecvt<_CharT> __cvt; 1082 if (__str_codecvt_in_all(__first, __last, __wstr, __cvt)) 1083 return __wstr; 1084 } 1085 } 1086 __detail::__throw_conversion_error(); 1087 } 1088 /// @endcond 1089 1090 template
1091 inline basic_string<_CharT, _Traits, _Allocator> 1092 path::string(const _Allocator& __a) const 1093 { 1094 if constexpr (is_same_v<_CharT, value_type>) 1095 return { _M_pathname.c_str(), _M_pathname.length(), __a }; 1096 else 1097 return _S_str_convert<_CharT, _Traits>(_M_pathname, __a); 1098 } 1099 1100 inline std::string 1101 path::string() const { return string
(); } 1102 1103 #if _GLIBCXX_USE_WCHAR_T 1104 inline std::wstring 1105 path::wstring() const { return string
(); } 1106 #endif 1107 1108 #ifdef _GLIBCXX_USE_CHAR8_T 1109 inline std::u8string 1110 path::u8string() const { return string
(); } 1111 #else 1112 inline std::string 1113 path::u8string() const 1114 { 1115 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1116 std::string __str; 1117 // convert from native wide encoding (assumed to be UTF-16) to UTF-8 1118 std::codecvt_utf8_utf16
__cvt; 1119 const value_type* __first = _M_pathname.data(); 1120 const value_type* __last = __first + _M_pathname.size(); 1121 if (__str_codecvt_out_all(__first, __last, __str, __cvt)) 1122 return __str; 1123 __detail::__throw_conversion_error(); 1124 #else 1125 return _M_pathname; 1126 #endif 1127 } 1128 #endif // _GLIBCXX_USE_CHAR8_T 1129 1130 inline std::u16string 1131 path::u16string() const { return string
(); } 1132 1133 inline std::u32string 1134 path::u32string() const { return string
(); } 1135 1136 template
1137 inline std::basic_string<_CharT, _Traits, _Allocator> 1138 path::generic_string(const _Allocator& __a) const 1139 { 1140 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1141 const value_type __slash = L'/'; 1142 #else 1143 const value_type __slash = '/'; 1144 #endif 1145 using _Alloc2 = typename allocator_traits<_Allocator>::template 1146 rebind_alloc
; 1147 basic_string
, _Alloc2> __str(__a); 1148 1149 if (_M_type() == _Type::_Root_dir) 1150 __str.assign(1, __slash); 1151 else 1152 { 1153 __str.reserve(_M_pathname.size()); 1154 bool __add_slash = false; 1155 for (auto& __elem : *this) 1156 { 1157 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1158 if (__elem._M_type() == _Type::_Root_dir) 1159 { 1160 __str += __slash; 1161 continue; 1162 } 1163 #endif 1164 if (__add_slash) 1165 __str += __slash; 1166 __str += basic_string_view
(__elem._M_pathname); 1167 __add_slash = __elem._M_type() == _Type::_Filename; 1168 } 1169 } 1170 1171 if constexpr (is_same_v<_CharT, value_type>) 1172 return __str; 1173 else 1174 return _S_str_convert<_CharT, _Traits>(__str, __a); 1175 } 1176 1177 inline std::string 1178 path::generic_string() const 1179 { return generic_string
(); } 1180 1181 #if _GLIBCXX_USE_WCHAR_T 1182 inline std::wstring 1183 path::generic_wstring() const 1184 { return generic_string
(); } 1185 #endif 1186 1187 #ifdef _GLIBCXX_USE_CHAR8_T 1188 inline std::u8string 1189 path::generic_u8string() const 1190 { return generic_string
(); } 1191 #else 1192 inline std::string 1193 path::generic_u8string() const 1194 { return generic_string(); } 1195 #endif 1196 1197 inline std::u16string 1198 path::generic_u16string() const 1199 { return generic_string
(); } 1200 1201 inline std::u32string 1202 path::generic_u32string() const 1203 { return generic_string
(); } 1204 1205 inline int 1206 path::compare(const string_type& __s) const noexcept 1207 { return compare(basic_string_view
(__s)); } 1208 1209 inline int 1210 path::compare(const value_type* __s) const noexcept 1211 { return compare(basic_string_view
(__s)); } 1212 1213 inline path 1214 path::filename() const 1215 { 1216 if (empty()) 1217 return {}; 1218 else if (_M_type() == _Type::_Filename) 1219 return *this; 1220 else if (_M_type() == _Type::_Multi) 1221 { 1222 if (_M_pathname.back() == preferred_separator) 1223 return {}; 1224 auto __last = --end(); 1225 if (__last->_M_type() == _Type::_Filename) 1226 return *__last; 1227 } 1228 return {}; 1229 } 1230 1231 inline path 1232 path::stem() const 1233 { 1234 auto ext = _M_find_extension(); 1235 if (ext.first && ext.second != 0) 1236 return path{ext.first->substr(0, ext.second)}; 1237 return {}; 1238 } 1239 1240 inline path 1241 path::extension() const 1242 { 1243 auto ext = _M_find_extension(); 1244 if (ext.first && ext.second != string_type::npos) 1245 return path{ext.first->substr(ext.second)}; 1246 return {}; 1247 } 1248 1249 inline bool 1250 path::has_stem() const noexcept 1251 { 1252 auto ext = _M_find_extension(); 1253 return ext.first && ext.second != 0; 1254 } 1255 1256 inline bool 1257 path::has_extension() const noexcept 1258 { 1259 auto ext = _M_find_extension(); 1260 return ext.first && ext.second != string_type::npos; 1261 } 1262 1263 inline bool 1264 path::is_absolute() const noexcept 1265 { 1266 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 1267 return has_root_name() && has_root_directory(); 1268 #else 1269 return has_root_directory(); 1270 #endif 1271 } 1272 1273 inline path::iterator 1274 path::begin() const 1275 { 1276 if (_M_type() == _Type::_Multi) 1277 return iterator(this, _M_cmpts.begin()); 1278 return iterator(this, empty()); 1279 } 1280 1281 inline path::iterator 1282 path::end() const 1283 { 1284 if (_M_type() == _Type::_Multi) 1285 return iterator(this, _M_cmpts.end()); 1286 return iterator(this, true); 1287 } 1288 1289 inline path::iterator& 1290 path::iterator::operator++() 1291 { 1292 __glibcxx_assert(_M_path != nullptr); 1293 if (_M_path->_M_type() == _Type::_Multi) 1294 { 1295 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 1296 ++_M_cur; 1297 } 1298 else 1299 { 1300 __glibcxx_assert(!_M_at_end); 1301 _M_at_end = true; 1302 } 1303 return *this; 1304 } 1305 1306 inline path::iterator& 1307 path::iterator::operator--() 1308 { 1309 __glibcxx_assert(_M_path != nullptr); 1310 if (_M_path->_M_type() == _Type::_Multi) 1311 { 1312 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin()); 1313 --_M_cur; 1314 } 1315 else 1316 { 1317 __glibcxx_assert(_M_at_end); 1318 _M_at_end = false; 1319 } 1320 return *this; 1321 } 1322 1323 inline path::iterator::reference 1324 path::iterator::operator*() const 1325 { 1326 __glibcxx_assert(_M_path != nullptr); 1327 if (_M_path->_M_type() == _Type::_Multi) 1328 { 1329 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); 1330 return *_M_cur; 1331 } 1332 return *_M_path; 1333 } 1334 1335 inline bool 1336 path::iterator::_M_equals(iterator __rhs) const 1337 { 1338 if (_M_path != __rhs._M_path) 1339 return false; 1340 if (_M_path == nullptr) 1341 return true; 1342 if (_M_path->_M_type() == path::_Type::_Multi) 1343 return _M_cur == __rhs._M_cur; 1344 return _M_at_end == __rhs._M_at_end; 1345 } 1346 1347 // Define this now that path and path::iterator are complete. 1348 // It needs to consider the string_view(Range&&) constructor during 1349 // overload resolution, which depends on whether range
is satisfied, 1350 // which depends on whether path::iterator is complete. 1351 inline int 1352 path::_S_compare(const path& __lhs, const path& __rhs) noexcept 1353 { return __lhs.compare(__rhs); } 1354 1355 /// @} group filesystem 1356 _GLIBCXX_END_NAMESPACE_CXX11 1357 } // namespace filesystem 1358 1359 /// @cond undocumented 1360 1361 inline ptrdiff_t 1362 distance(filesystem::path::iterator __first, filesystem::path::iterator __last) 1363 { return __path_iter_distance(__first, __last); } 1364 1365 template
1366 void 1367 advance(filesystem::path::iterator& __i, _Distance __n) 1368 { __path_iter_advance(__i, static_cast
(__n)); } 1369 1370 extern template class __shared_ptr
; 1371 1372 /// @endcond 1373 1374 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1375 // 3657. std::hash
is not enabled 1376 template<> 1377 struct hash
1378 { 1379 size_t 1380 operator()(const filesystem::path& __p) const noexcept 1381 { return filesystem::hash_value(__p); } 1382 }; 1383 1384 _GLIBCXX_END_NAMESPACE_VERSION 1385 } // namespace std 1386 1387 #endif // C++17 1388 1389 #endif // _GLIBCXX_FS_PATH_H
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2024 MyWebUniversity.com ™