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