1// Components for manipulating non-owning sequences of characters -*- C++ -*- 2 3// Copyright (C) 2013-2015 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 45namespace std _GLIBCXX_VISIBILITY(default) 46{ 47namespace experimental 48{ 49inline namespace fundamentals_v1 50{ 51_GLIBCXX_BEGIN_NAMESPACE_VERSION 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 experimental 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 = const _CharT*; 83 using const_pointer = const _CharT*; 84 using reference = const _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 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 // TODO: Assert to restore in a way compatible with the constexpr. 183 // _GLIBCXX_DEBUG_ASSERT(__pos < this->_M_len); 184 return *(this->_M_str + __pos); 185 } 186 187 constexpr const _CharT& 188 at(size_type __pos) const 189 { 190 return __pos < this->_M_len 191 ? *(this->_M_str + __pos) 192 : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos " 193 "(which is %zu) >= this->size() " 194 "(which is %zu)"), 195 __pos, this->size()), 196 *this->_M_str); 197 } 198 199 constexpr const _CharT& 200 front() const 201 { 202 // TODO: Assert to restore in a way compatible with the constexpr. 203 // _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0); 204 return *this->_M_str; 205 } 206 207 constexpr const _CharT& 208 back() const 209 { 210 // TODO: Assert to restore in a way compatible with the constexpr. 211 // _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0); 212 return *(this->_M_str + this->_M_len - 1); 213 } 214 215 constexpr const _CharT* 216 data() const noexcept 217 { return this->_M_str; } 218 219 // [string.view.modifiers], modifiers: 220 221 void 222 remove_prefix(size_type __n) 223 { 224 _GLIBCXX_DEBUG_ASSERT(this->_M_len >= __n); 225 this->_M_str += __n; 226 this->_M_len -= __n; 227 } 228 229 void 230 remove_suffix(size_type __n) 231 { this->_M_len -= __n; } 232 233 void 234 swap(basic_string_view& __sv) noexcept 235 { 236 std::swap(this->_M_len, __sv._M_len); 237 std::swap(this->_M_str, __sv._M_str); 238 } 239 240 241 // [string.view.ops], string operations: 242 243 template<typename _Allocator> 244 explicit operator basic_string<_CharT, _Traits, _Allocator>() const 245 { 246 return { this->_M_str, this->_M_len }; 247 } 248 249 template<typename _Allocator = std::allocator<_CharT>> 250 basic_string<_CharT, _Traits, _Allocator> 251 to_string(const _Allocator& __alloc = _Allocator()) const 252 { 253 return { this->_M_str, this->_M_len, __alloc }; 254 } 255 256 size_type 257 copy(_CharT* __str, size_type __n, size_type __pos = 0) const 258 { 259 __glibcxx_requires_string_len(__str, __n); 260 if (__pos > this->_M_len) 261 __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos " 262 "(which is %zu) > this->size() " 263 "(which is %zu)"), 264 __pos, this->size()); 265 size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})}; 266 for (auto __begin = this->_M_str + __pos, 267 __end = __begin + __rlen; __begin != __end;) 268 *__str++ = *__begin++; 269 return __rlen; 270 } 271 272 273 // [string.view.ops], string operations: 274 275 constexpr basic_string_view 276 substr(size_type __pos, size_type __n=npos) const 277 { 278 return __pos <= this->_M_len 279 ? basic_string_view{this->_M_str + __pos, 280 std::min(__n, size_type{this->_M_len - __pos})} 281 : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos " 282 "(which is %zu) > this->size() " 283 "(which is %zu)"), 284 __pos, this->size()), basic_string_view{}); 285 } 286 287 int 288 compare(basic_string_view __str) const noexcept 289 { 290 int __ret = traits_type::compare(this->_M_str, __str._M_str, 291 std::min(this->_M_len, __str._M_len)); 292 if (__ret == 0) 293 __ret = _S_compare(this->_M_len, __str._M_len); 294 return __ret; 295 } 296 297 int 298 compare(size_type __pos1, size_type __n1, basic_string_view __str) const 299 { return this->substr(__pos1, __n1).compare(__str); } 300 301 int 302 compare(size_type __pos1, size_type __n1, 303 basic_string_view __str, size_type __pos2, size_type __n2) const 304 { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } 305 306 int 307 compare(const _CharT* __str) const noexcept 308 { return this->compare(basic_string_view{__str}); } 309 310 int 311 compare(size_type __pos1, size_type __n1, const _CharT* __str) const 312 { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } 313 314 int 315 compare(size_type __pos1, size_type __n1, 316 const _CharT* __str, size_type __n2) const 317 { 318 return this->substr(__pos1, __n1) 319 .compare(basic_string_view(__str, __n2)); 320 } 321 322 size_type 323 find(basic_string_view __str, size_type __pos = 0) const noexcept 324 { return this->find(__str._M_str, __pos, __str._M_len); } 325 326 size_type 327 find(_CharT __c, size_type __pos=0) const noexcept; 328 329 size_type 330 find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 331 332 size_type 333 find(const _CharT* __str, size_type __pos=0) const noexcept 334 { return this->find(__str, __pos, traits_type::length(__str)); } 335 336 size_type 337 rfind(basic_string_view __str, size_type __pos = npos) const noexcept 338 { return this->rfind(__str._M_str, __pos, __str._M_len); } 339 340 size_type 341 rfind(_CharT __c, size_type __pos = npos) const noexcept; 342 343 size_type 344 rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 345 346 size_type 347 rfind(const _CharT* __str, size_type __pos = npos) const noexcept 348 { return this->rfind(__str, __pos, traits_type::length(__str)); } 349 350 size_type 351 find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept 352 { return this->find_first_of(__str._M_str, __pos, __str._M_len); } 353 354 size_type 355 find_first_of(_CharT __c, size_type __pos = 0) const noexcept 356 { return this->find(__c, __pos); } 357 358 size_type 359 find_first_of(const _CharT* __str, size_type __pos, size_type __n) const; 360 361 size_type 362 find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept 363 { return this->find_first_of(__str, __pos, traits_type::length(__str)); } 364 365 size_type 366 find_last_of(basic_string_view __str, 367 size_type __pos = npos) const noexcept 368 { return this->find_last_of(__str._M_str, __pos, __str._M_len); } 369 370 size_type 371 find_last_of(_CharT __c, size_type __pos=npos) const noexcept 372 { return this->rfind(__c, __pos); } 373 374 size_type 375 find_last_of(const _CharT* __str, size_type __pos, size_type __n) const; 376 377 size_type 378 find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept 379 { return this->find_last_of(__str, __pos, traits_type::length(__str)); } 380 381 size_type 382 find_first_not_of(basic_string_view __str, 383 size_type __pos = 0) const noexcept 384 { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } 385 386 size_type 387 find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; 388 389 size_type 390 find_first_not_of(const _CharT* __str, 391 size_type __pos, size_type __n) const; 392 393 size_type 394 find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept 395 { 396 return this->find_first_not_of(__str, __pos, 397 traits_type::length(__str)); 398 } 399 400 size_type 401 find_last_not_of(basic_string_view __str, 402 size_type __pos = npos) const noexcept 403 { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } 404 405 size_type 406 find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; 407 408 size_type 409 find_last_not_of(const _CharT* __str, 410 size_type __pos, size_type __n) const; 411 412 size_type 413 find_last_not_of(const _CharT* __str, 414 size_type __pos = npos) const noexcept 415 { 416 return this->find_last_not_of(__str, __pos, 417 traits_type::length(__str)); 418 } 419 420 private: 421 422 static constexpr const int 423 _S_compare(size_type __n1, size_type __n2) noexcept 424 { 425 return difference_type{__n1 - __n2} > std::numeric_limits<int>::max() 426 ? std::numeric_limits<int>::max() 427 : difference_type{__n1 - __n2} < std::numeric_limits<int>::min() 428 ? std::numeric_limits<int>::min() 429 : static_cast<int>(difference_type{__n1 - __n2}); 430 } 431 432 size_t _M_len; 433 const _CharT* _M_str; 434 }; 435 436 437 // [string.view.comparison], non-member basic_string_view comparison functions 438 439 namespace __detail 440 { 441 // Identity transform to make ADL work with just one argument. 442 // See n3766.html. 443 template<typename _Tp = void> 444 struct __identity 445 { typedef _Tp type; }; 446 447 template<> 448 struct __identity<void>; 449 450 template<typename _Tp> 451 using __idt = typename __identity<_Tp>::type; 452 } 453 454 template<typename _CharT, typename _Traits> 455 inline bool 456 operator==(basic_string_view<_CharT, _Traits> __x, 457 basic_string_view<_CharT, _Traits> __y) noexcept 458 { return __x.compare(__y) == 0; } 459 460 template<typename _CharT, typename _Traits> 461 inline bool 462 operator==(basic_string_view<_CharT, _Traits> __x, 463 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 464 { return __x.compare(__y) == 0; } 465 466 template<typename _CharT, typename _Traits> 467 inline bool 468 operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 469 basic_string_view<_CharT, _Traits> __y) noexcept 470 { return __x.compare(__y) == 0; } 471 472 template<typename _CharT, typename _Traits> 473 inline bool 474 operator!=(basic_string_view<_CharT, _Traits> __x, 475 basic_string_view<_CharT, _Traits> __y) noexcept 476 { return !(__x == __y); } 477 478 template<typename _CharT, typename _Traits> 479 inline bool 480 operator!=(basic_string_view<_CharT, _Traits> __x, 481 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 482 { return !(__x == __y); } 483 484 template<typename _CharT, typename _Traits> 485 inline bool 486 operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 487 basic_string_view<_CharT, _Traits> __y) noexcept 488 { return !(__x == __y); } 489 490 template<typename _CharT, typename _Traits> 491 inline bool 492 operator< (basic_string_view<_CharT, _Traits> __x, 493 basic_string_view<_CharT, _Traits> __y) noexcept 494 { return __x.compare(__y) < 0; } 495 496 template<typename _CharT, typename _Traits> 497 inline bool 498 operator< (basic_string_view<_CharT, _Traits> __x, 499 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 500 { return __x.compare(__y) < 0; } 501 502 template<typename _CharT, typename _Traits> 503 inline bool 504 operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 505 basic_string_view<_CharT, _Traits> __y) noexcept 506 { return __x.compare(__y) < 0; } 507 508 template<typename _CharT, typename _Traits> 509 inline bool 510 operator> (basic_string_view<_CharT, _Traits> __x, 511 basic_string_view<_CharT, _Traits> __y) noexcept 512 { return __x.compare(__y) > 0; } 513 514 template<typename _CharT, typename _Traits> 515 inline bool 516 operator> (basic_string_view<_CharT, _Traits> __x, 517 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 518 { return __x.compare(__y) > 0; } 519 520 template<typename _CharT, typename _Traits> 521 inline bool 522 operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 523 basic_string_view<_CharT, _Traits> __y) noexcept 524 { return __x.compare(__y) > 0; } 525 526 template<typename _CharT, typename _Traits> 527 inline bool 528 operator<=(basic_string_view<_CharT, _Traits> __x, 529 basic_string_view<_CharT, _Traits> __y) noexcept 530 { return __x.compare(__y) <= 0; } 531 532 template<typename _CharT, typename _Traits> 533 inline bool 534 operator<=(basic_string_view<_CharT, _Traits> __x, 535 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 536 { return __x.compare(__y) <= 0; } 537 538 template<typename _CharT, typename _Traits> 539 inline bool 540 operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 541 basic_string_view<_CharT, _Traits> __y) noexcept 542 { return __x.compare(__y) <= 0; } 543 544 template<typename _CharT, typename _Traits> 545 inline bool 546 operator>=(basic_string_view<_CharT, _Traits> __x, 547 basic_string_view<_CharT, _Traits> __y) noexcept 548 { return __x.compare(__y) >= 0; } 549 550 template<typename _CharT, typename _Traits> 551 inline bool 552 operator>=(basic_string_view<_CharT, _Traits> __x, 553 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 554 { return __x.compare(__y) >= 0; } 555 556 template<typename _CharT, typename _Traits> 557 inline bool 558 operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 559 basic_string_view<_CharT, _Traits> __y) noexcept 560 { return __x.compare(__y) >= 0; } 561 562 // [string.view.io], Inserters and extractors 563 template<typename _CharT, typename _Traits> 564 inline basic_ostream<_CharT, _Traits>& 565 operator<<(basic_ostream<_CharT, _Traits>& __os, 566 basic_string_view<_CharT,_Traits> __str) 567 { return __ostream_insert(__os, __str.data(), __str.size()); } 568 569 570 // basic_string_view typedef names 571 572 using string_view = basic_string_view<char>; 573#ifdef _GLIBCXX_USE_WCHAR_T 574 using wstring_view = basic_string_view<wchar_t>; 575#endif 576#ifdef _GLIBCXX_USE_C99_STDINT_TR1 577 using u16string_view = basic_string_view<char16_t>; 578 using u32string_view = basic_string_view<char32_t>; 579#endif 580 581_GLIBCXX_END_NAMESPACE_VERSION 582} // namespace fundamentals_v1 583} // namespace experimental 584 585 586 // [string.view.hash], hash support: 587 588_GLIBCXX_BEGIN_NAMESPACE_VERSION 589 template<typename _Tp> 590 struct hash; 591 592 template<> 593 struct hash<experimental::string_view> 594 : public __hash_base<size_t, experimental::string_view> 595 { 596 size_t 597 operator()(const experimental::string_view& __str) const noexcept 598 { return std::_Hash_impl::hash(__str.data(), __str.length()); } 599 }; 600 601 template<> 602 struct __is_fast_hash<hash<experimental::string_view>> : std::false_type 603 { }; 604 605#ifdef _GLIBCXX_USE_WCHAR_T 606 template<> 607 struct hash<experimental::wstring_view> 608 : public __hash_base<size_t, wstring> 609 { 610 size_t 611 operator()(const experimental::wstring_view& __s) const noexcept 612 { return std::_Hash_impl::hash(__s.data(), 613 __s.length() * sizeof(wchar_t)); } 614 }; 615 616 template<> 617 struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type 618 { }; 619#endif 620 621#ifdef _GLIBCXX_USE_C99_STDINT_TR1 622 template<> 623 struct hash<experimental::u16string_view> 624 : public __hash_base<size_t, experimental::u16string_view> 625 { 626 size_t 627 operator()(const experimental::u16string_view& __s) const noexcept 628 { return std::_Hash_impl::hash(__s.data(), 629 __s.length() * sizeof(char16_t)); } 630 }; 631 632 template<> 633 struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type 634 { }; 635 636 template<> 637 struct hash<experimental::u32string_view> 638 : public __hash_base<size_t, experimental::u32string_view> 639 { 640 size_t 641 operator()(const experimental::u32string_view& __s) const noexcept 642 { return std::_Hash_impl::hash(__s.data(), 643 __s.length() * sizeof(char32_t)); } 644 }; 645 646 template<> 647 struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type 648 { }; 649#endif 650_GLIBCXX_END_NAMESPACE_VERSION 651 652namespace experimental 653{ 654_GLIBCXX_BEGIN_NAMESPACE_VERSION 655 656 // I added these EMSR. 657 inline namespace literals 658 { 659 inline namespace string_view_literals 660 { 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 } 683 } 684 685_GLIBCXX_END_NAMESPACE_VERSION 686} // namespace experimental 687} // namespace std 688 689#include <experimental/string_view.tcc> 690 691#endif // __cplusplus <= 201103L 692 693#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW 694