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