1// Components for manipulating non-owning sequences of characters -*- C++ -*- 2 3// Copyright (C) 2013-2020 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// <http://www.gnu.org/licenses/>. 24 25/** @file experimental/string_view 26 * This is a TS C++ Library header. 27 * @ingroup libfund-ts 28 */ 29 30// 31// N3762 basic_string_view library 32// 33 34#ifndef _GLIBCXX_EXPERIMENTAL_STRING_VIEW 35#define _GLIBCXX_EXPERIMENTAL_STRING_VIEW 1 36 37#pragma GCC system_header 38 39#if __cplusplus >= 201402L 40 41#include <string> 42#include <limits> 43#include <experimental/bits/lfts_config.h> 44 45namespace std _GLIBCXX_VISIBILITY(default) 46{ 47_GLIBCXX_BEGIN_NAMESPACE_VERSION 48 49namespace experimental 50{ 51inline namespace fundamentals_v1 52{ 53#define __cpp_lib_experimental_string_view 201411 54 55 /** 56 * @class basic_string_view <experimental/string_view> 57 * @brief A non-owning reference to a string. 58 * 59 * @ingroup strings 60 * @ingroup sequences 61 * @ingroup libfund-ts 62 * 63 * @tparam _CharT Type of character 64 * @tparam _Traits Traits for character type, defaults to 65 * char_traits<_CharT>. 66 * 67 * A basic_string_view looks like this: 68 * 69 * @code 70 * _CharT* _M_str 71 * size_t _M_len 72 * @endcode 73 */ 74 template<typename _CharT, typename _Traits = std::char_traits<_CharT>> 75 class basic_string_view 76 { 77 public: 78 79 // types 80 using traits_type = _Traits; 81 using value_type = _CharT; 82 using pointer = _CharT*; 83 using const_pointer = const _CharT*; 84 using reference = _CharT&; 85 using const_reference = const _CharT&; 86 using const_iterator = const _CharT*; 87 using iterator = const_iterator; 88 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 89 using reverse_iterator = const_reverse_iterator; 90 using size_type = size_t; 91 using difference_type = ptrdiff_t; 92 static constexpr size_type npos = size_type(-1); 93 94 // [string.view.cons], construct/copy 95 96 constexpr 97 basic_string_view() noexcept 98 : _M_len{0}, _M_str{nullptr} 99 { } 100 101 constexpr basic_string_view(const basic_string_view&) noexcept = default; 102 103 template<typename _Allocator> 104 basic_string_view(const basic_string<_CharT, _Traits, 105 _Allocator>& __str) noexcept 106 : _M_len{__str.length()}, _M_str{__str.data()} 107 { } 108 109 constexpr basic_string_view(const _CharT* __str) 110 : _M_len{__str == nullptr ? 0 : traits_type::length(__str)}, 111 _M_str{__str} 112 { } 113 114 constexpr basic_string_view(const _CharT* __str, size_type __len) 115 : _M_len{__len}, 116 _M_str{__str} 117 { } 118 119 basic_string_view& 120 operator=(const basic_string_view&) noexcept = default; 121 122 // [string.view.iterators], iterators 123 124 constexpr const_iterator 125 begin() const noexcept 126 { return this->_M_str; } 127 128 constexpr const_iterator 129 end() const noexcept 130 { return this->_M_str + this->_M_len; } 131 132 constexpr const_iterator 133 cbegin() const noexcept 134 { return this->_M_str; } 135 136 constexpr const_iterator 137 cend() const noexcept 138 { return this->_M_str + this->_M_len; } 139 140 const_reverse_iterator 141 rbegin() const noexcept 142 { return const_reverse_iterator(this->end()); } 143 144 const_reverse_iterator 145 rend() const noexcept 146 { return const_reverse_iterator(this->begin()); } 147 148 const_reverse_iterator 149 crbegin() const noexcept 150 { return const_reverse_iterator(this->end()); } 151 152 const_reverse_iterator 153 crend() const noexcept 154 { return const_reverse_iterator(this->begin()); } 155 156 // [string.view.capacity], capacity 157 158 constexpr size_type 159 size() const noexcept 160 { return this->_M_len; } 161 162 constexpr size_type 163 length() const noexcept 164 { return _M_len; } 165 166 constexpr size_type 167 max_size() const noexcept 168 { 169 return (npos - sizeof(size_type) - sizeof(void*)) 170 / sizeof(value_type) / 4; 171 } 172 173 _GLIBCXX_NODISCARD constexpr bool 174 empty() const noexcept 175 { return this->_M_len == 0; } 176 177 // [string.view.access], element access 178 179 constexpr const _CharT& 180 operator[](size_type __pos) const 181 { 182 __glibcxx_assert(__pos < this->_M_len); 183 return *(this->_M_str + __pos); 184 } 185 186 constexpr const _CharT& 187 at(size_type __pos) const 188 { 189 return __pos < this->_M_len 190 ? *(this->_M_str + __pos) 191 : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos " 192 "(which is %zu) >= this->size() " 193 "(which is %zu)"), 194 __pos, this->size()), 195 *this->_M_str); 196 } 197 198 constexpr const _CharT& 199 front() const 200 { 201 __glibcxx_assert(this->_M_len > 0); 202 return *this->_M_str; 203 } 204 205 constexpr const _CharT& 206 back() const 207 { 208 __glibcxx_assert(this->_M_len > 0); 209 return *(this->_M_str + this->_M_len - 1); 210 } 211 212 constexpr const _CharT* 213 data() const noexcept 214 { return this->_M_str; } 215 216 // [string.view.modifiers], modifiers: 217 218 constexpr void 219 remove_prefix(size_type __n) 220 { 221 __glibcxx_assert(this->_M_len >= __n); 222 this->_M_str += __n; 223 this->_M_len -= __n; 224 } 225 226 constexpr void 227 remove_suffix(size_type __n) 228 { this->_M_len -= __n; } 229 230 constexpr void 231 swap(basic_string_view& __sv) noexcept 232 { 233 auto __tmp = *this; 234 *this = __sv; 235 __sv = __tmp; 236 } 237 238 239 // [string.view.ops], string operations: 240 241 template<typename _Allocator> 242 explicit operator basic_string<_CharT, _Traits, _Allocator>() const 243 { 244 return { this->_M_str, this->_M_len }; 245 } 246 247 template<typename _Allocator = std::allocator<_CharT>> 248 basic_string<_CharT, _Traits, _Allocator> 249 to_string(const _Allocator& __alloc = _Allocator()) const 250 { 251 return { this->_M_str, this->_M_len, __alloc }; 252 } 253 254 size_type 255 copy(_CharT* __str, size_type __n, size_type __pos = 0) const 256 { 257 __glibcxx_requires_string_len(__str, __n); 258 if (__pos > this->_M_len) 259 __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos " 260 "(which is %zu) > this->size() " 261 "(which is %zu)"), 262 __pos, this->size()); 263 size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})}; 264 for (auto __begin = this->_M_str + __pos, 265 __end = __begin + __rlen; __begin != __end;) 266 *__str++ = *__begin++; 267 return __rlen; 268 } 269 270 271 // [string.view.ops], string operations: 272 273 constexpr basic_string_view 274 substr(size_type __pos = 0, size_type __n = npos) const 275 { 276 return __pos <= this->_M_len 277 ? basic_string_view{this->_M_str + __pos, 278 std::min(__n, size_type{this->_M_len - __pos})} 279 : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos " 280 "(which is %zu) > this->size() " 281 "(which is %zu)"), 282 __pos, this->size()), basic_string_view{}); 283 } 284 285 constexpr int 286 compare(basic_string_view __str) const noexcept 287 { 288 int __ret = traits_type::compare(this->_M_str, __str._M_str, 289 std::min(this->_M_len, __str._M_len)); 290 if (__ret == 0) 291 __ret = _S_compare(this->_M_len, __str._M_len); 292 return __ret; 293 } 294 295 constexpr int 296 compare(size_type __pos1, size_type __n1, basic_string_view __str) const 297 { return this->substr(__pos1, __n1).compare(__str); } 298 299 constexpr int 300 compare(size_type __pos1, size_type __n1, 301 basic_string_view __str, size_type __pos2, size_type __n2) const 302 { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } 303 304 constexpr int 305 compare(const _CharT* __str) const noexcept 306 { return this->compare(basic_string_view{__str}); } 307 308 constexpr int 309 compare(size_type __pos1, size_type __n1, const _CharT* __str) const 310 { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } 311 312 constexpr int 313 compare(size_type __pos1, size_type __n1, 314 const _CharT* __str, size_type __n2) const 315 { 316 return this->substr(__pos1, __n1) 317 .compare(basic_string_view(__str, __n2)); 318 } 319 320 constexpr size_type 321 find(basic_string_view __str, size_type __pos = 0) const noexcept 322 { return this->find(__str._M_str, __pos, __str._M_len); } 323 324 constexpr size_type 325 find(_CharT __c, size_type __pos=0) const noexcept; 326 327 constexpr size_type 328 find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 329 330 constexpr size_type 331 find(const _CharT* __str, size_type __pos=0) const noexcept 332 { return this->find(__str, __pos, traits_type::length(__str)); } 333 334 constexpr size_type 335 rfind(basic_string_view __str, size_type __pos = npos) const noexcept 336 { return this->rfind(__str._M_str, __pos, __str._M_len); } 337 338 constexpr size_type 339 rfind(_CharT __c, size_type __pos = npos) const noexcept; 340 341 constexpr size_type 342 rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 343 344 constexpr size_type 345 rfind(const _CharT* __str, size_type __pos = npos) const noexcept 346 { return this->rfind(__str, __pos, traits_type::length(__str)); } 347 348 constexpr size_type 349 find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept 350 { return this->find_first_of(__str._M_str, __pos, __str._M_len); } 351 352 constexpr size_type 353 find_first_of(_CharT __c, size_type __pos = 0) const noexcept 354 { return this->find(__c, __pos); } 355 356 constexpr size_type 357 find_first_of(const _CharT* __str, size_type __pos, size_type __n) const; 358 359 constexpr size_type 360 find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept 361 { return this->find_first_of(__str, __pos, traits_type::length(__str)); } 362 363 constexpr size_type 364 find_last_of(basic_string_view __str, 365 size_type __pos = npos) const noexcept 366 { return this->find_last_of(__str._M_str, __pos, __str._M_len); } 367 368 constexpr size_type 369 find_last_of(_CharT __c, size_type __pos=npos) const noexcept 370 { return this->rfind(__c, __pos); } 371 372 constexpr size_type 373 find_last_of(const _CharT* __str, size_type __pos, size_type __n) const; 374 375 constexpr size_type 376 find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept 377 { return this->find_last_of(__str, __pos, traits_type::length(__str)); } 378 379 constexpr size_type 380 find_first_not_of(basic_string_view __str, 381 size_type __pos = 0) const noexcept 382 { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } 383 384 constexpr size_type 385 find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; 386 387 constexpr size_type 388 find_first_not_of(const _CharT* __str, 389 size_type __pos, size_type __n) const; 390 391 constexpr size_type 392 find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept 393 { 394 return this->find_first_not_of(__str, __pos, 395 traits_type::length(__str)); 396 } 397 398 constexpr size_type 399 find_last_not_of(basic_string_view __str, 400 size_type __pos = npos) const noexcept 401 { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } 402 403 constexpr size_type 404 find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; 405 406 constexpr size_type 407 find_last_not_of(const _CharT* __str, 408 size_type __pos, size_type __n) const; 409 410 constexpr size_type 411 find_last_not_of(const _CharT* __str, 412 size_type __pos = npos) const noexcept 413 { 414 return this->find_last_not_of(__str, __pos, 415 traits_type::length(__str)); 416 } 417 418 private: 419 420 static constexpr int 421 _S_compare(size_type __n1, size_type __n2) noexcept 422 { 423 return difference_type(__n1 - __n2) > std::numeric_limits<int>::max() 424 ? std::numeric_limits<int>::max() 425 : difference_type(__n1 - __n2) < std::numeric_limits<int>::min() 426 ? std::numeric_limits<int>::min() 427 : static_cast<int>(difference_type(__n1 - __n2)); 428 } 429 430 size_t _M_len; 431 const _CharT* _M_str; 432 }; 433 434 // [string.view.comparison], non-member basic_string_view comparison functions 435 436 // Several of these functions use type_identity_t to create a non-deduced 437 // context, so that only one argument participates in template argument 438 // deduction and the other argument gets implicitly converted to the deduced 439 // type (see N3766). 440 441 template<typename _CharT, typename _Traits> 442 constexpr bool 443 operator==(basic_string_view<_CharT, _Traits> __x, 444 basic_string_view<_CharT, _Traits> __y) noexcept 445 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 446 447 template<typename _CharT, typename _Traits> 448 constexpr bool 449 operator==(basic_string_view<_CharT, _Traits> __x, 450 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 451 noexcept 452 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 453 454 template<typename _CharT, typename _Traits> 455 constexpr bool 456 operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 457 basic_string_view<_CharT, _Traits> __y) noexcept 458 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 459 460 template<typename _CharT, typename _Traits> 461 constexpr bool 462 operator!=(basic_string_view<_CharT, _Traits> __x, 463 basic_string_view<_CharT, _Traits> __y) noexcept 464 { return !(__x == __y); } 465 466 template<typename _CharT, typename _Traits> 467 constexpr bool 468 operator!=(basic_string_view<_CharT, _Traits> __x, 469 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 470 noexcept 471 { return !(__x == __y); } 472 473 template<typename _CharT, typename _Traits> 474 constexpr bool 475 operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 476 basic_string_view<_CharT, _Traits> __y) noexcept 477 { return !(__x == __y); } 478 479 template<typename _CharT, typename _Traits> 480 constexpr bool 481 operator< (basic_string_view<_CharT, _Traits> __x, 482 basic_string_view<_CharT, _Traits> __y) noexcept 483 { return __x.compare(__y) < 0; } 484 485 template<typename _CharT, typename _Traits> 486 constexpr bool 487 operator< (basic_string_view<_CharT, _Traits> __x, 488 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 489 noexcept 490 { return __x.compare(__y) < 0; } 491 492 template<typename _CharT, typename _Traits> 493 constexpr bool 494 operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 495 basic_string_view<_CharT, _Traits> __y) noexcept 496 { return __x.compare(__y) < 0; } 497 498 template<typename _CharT, typename _Traits> 499 constexpr bool 500 operator> (basic_string_view<_CharT, _Traits> __x, 501 basic_string_view<_CharT, _Traits> __y) noexcept 502 { return __x.compare(__y) > 0; } 503 504 template<typename _CharT, typename _Traits> 505 constexpr bool 506 operator> (basic_string_view<_CharT, _Traits> __x, 507 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 508 noexcept 509 { return __x.compare(__y) > 0; } 510 511 template<typename _CharT, typename _Traits> 512 constexpr bool 513 operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 514 basic_string_view<_CharT, _Traits> __y) noexcept 515 { return __x.compare(__y) > 0; } 516 517 template<typename _CharT, typename _Traits> 518 constexpr bool 519 operator<=(basic_string_view<_CharT, _Traits> __x, 520 basic_string_view<_CharT, _Traits> __y) noexcept 521 { return __x.compare(__y) <= 0; } 522 523 template<typename _CharT, typename _Traits> 524 constexpr bool 525 operator<=(basic_string_view<_CharT, _Traits> __x, 526 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 527 noexcept 528 { return __x.compare(__y) <= 0; } 529 530 template<typename _CharT, typename _Traits> 531 constexpr bool 532 operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 533 basic_string_view<_CharT, _Traits> __y) noexcept 534 { return __x.compare(__y) <= 0; } 535 536 template<typename _CharT, typename _Traits> 537 constexpr bool 538 operator>=(basic_string_view<_CharT, _Traits> __x, 539 basic_string_view<_CharT, _Traits> __y) noexcept 540 { return __x.compare(__y) >= 0; } 541 542 template<typename _CharT, typename _Traits> 543 constexpr bool 544 operator>=(basic_string_view<_CharT, _Traits> __x, 545 __type_identity_t<basic_string_view<_CharT, _Traits>> __y) 546 noexcept 547 { return __x.compare(__y) >= 0; } 548 549 template<typename _CharT, typename _Traits> 550 constexpr bool 551 operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, 552 basic_string_view<_CharT, _Traits> __y) noexcept 553 { return __x.compare(__y) >= 0; } 554 555 // [string.view.io], Inserters and extractors 556 template<typename _CharT, typename _Traits> 557 inline basic_ostream<_CharT, _Traits>& 558 operator<<(basic_ostream<_CharT, _Traits>& __os, 559 basic_string_view<_CharT,_Traits> __str) 560 { return __ostream_insert(__os, __str.data(), __str.size()); } 561 562 563 // basic_string_view typedef names 564 565 using string_view = basic_string_view<char>; 566#ifdef _GLIBCXX_USE_WCHAR_T 567 using wstring_view = basic_string_view<wchar_t>; 568#endif 569#ifdef _GLIBCXX_USE_CHAR8_T 570 using u8string_view = basic_string_view<char8_t>; 571#endif 572 using u16string_view = basic_string_view<char16_t>; 573 using u32string_view = basic_string_view<char32_t>; 574} // namespace fundamentals_v1 575} // namespace experimental 576 577 578 // [string.view.hash], hash support: 579 template<typename _Tp> 580 struct hash; 581 582 template<> 583 struct hash<experimental::string_view> 584 : public __hash_base<size_t, experimental::string_view> 585 { 586 size_t 587 operator()(const experimental::string_view& __str) const noexcept 588 { return std::_Hash_impl::hash(__str.data(), __str.length()); } 589 }; 590 591 template<> 592 struct __is_fast_hash<hash<experimental::string_view>> : std::false_type 593 { }; 594 595#ifdef _GLIBCXX_USE_WCHAR_T 596 template<> 597 struct hash<experimental::wstring_view> 598 : public __hash_base<size_t, wstring> 599 { 600 size_t 601 operator()(const experimental::wstring_view& __s) const noexcept 602 { return std::_Hash_impl::hash(__s.data(), 603 __s.length() * sizeof(wchar_t)); } 604 }; 605 606 template<> 607 struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type 608 { }; 609#endif 610 611#ifdef _GLIBCXX_USE_CHAR8_T 612 template<> 613 struct hash<experimental::u8string_view> 614 : public __hash_base<size_t, experimental::u8string_view> 615 { 616 size_t 617 operator()(const experimental::u8string_view& __s) const noexcept 618 { return std::_Hash_impl::hash(__s.data(), __s.length()); } 619 }; 620 621 template<> 622 struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type 623 { }; 624#endif 625 626 template<> 627 struct hash<experimental::u16string_view> 628 : public __hash_base<size_t, experimental::u16string_view> 629 { 630 size_t 631 operator()(const experimental::u16string_view& __s) const noexcept 632 { return std::_Hash_impl::hash(__s.data(), 633 __s.length() * sizeof(char16_t)); } 634 }; 635 636 template<> 637 struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type 638 { }; 639 640 template<> 641 struct hash<experimental::u32string_view> 642 : public __hash_base<size_t, experimental::u32string_view> 643 { 644 size_t 645 operator()(const experimental::u32string_view& __s) const noexcept 646 { return std::_Hash_impl::hash(__s.data(), 647 __s.length() * sizeof(char32_t)); } 648 }; 649 650 template<> 651 struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type 652 { }; 653 654namespace experimental 655{ 656 // I added these EMSR. 657 inline namespace literals 658 { 659 inline namespace string_view_literals 660 { 661#pragma GCC diagnostic push 662#pragma GCC diagnostic ignored "-Wliteral-suffix" 663 inline constexpr basic_string_view<char> 664 operator""sv(const char* __str, size_t __len) noexcept 665 { return basic_string_view<char>{__str, __len}; } 666 667#ifdef _GLIBCXX_USE_WCHAR_T 668 inline constexpr basic_string_view<wchar_t> 669 operator""sv(const wchar_t* __str, size_t __len) noexcept 670 { return basic_string_view<wchar_t>{__str, __len}; } 671#endif 672 673#ifdef _GLIBCXX_USE_CHAR8_T 674 inline constexpr basic_string_view<char8_t> 675 operator""sv(const char8_t* __str, size_t __len) noexcept 676 { return basic_string_view<char8_t>{__str, __len}; } 677#endif 678 679 inline constexpr basic_string_view<char16_t> 680 operator""sv(const char16_t* __str, size_t __len) noexcept 681 { return basic_string_view<char16_t>{__str, __len}; } 682 683 inline constexpr basic_string_view<char32_t> 684 operator""sv(const char32_t* __str, size_t __len) noexcept 685 { return basic_string_view<char32_t>{__str, __len}; } 686#pragma GCC diagnostic pop 687 } // namespace string_literals 688 } // namespace literals 689} // namespace experimental 690 691#if __cpp_lib_concepts 692 namespace ranges 693 { 694 // Opt-in to borrowed_range concept 695 template<typename _CharT, typename _Traits> 696 inline constexpr bool 697 enable_borrowed_range<experimental::basic_string_view<_CharT, _Traits>> 698 = true; 699 700 // Opt-in to view concept 701 template<typename _CharT, typename _Traits> 702 inline constexpr bool 703 enable_view<experimental::basic_string_view<_CharT, _Traits>> = true; 704 } 705#endif 706 707_GLIBCXX_END_NAMESPACE_VERSION 708} // namespace std 709 710#include <experimental/bits/string_view.tcc> 711 712#endif // __cplusplus <= 201103L 713 714#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW 715