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