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