1// Components for manipulating non-owning sequences of characters -*- C++ -*- 2 3// Copyright (C) 2013-2017 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{ 46namespace experimental 47{ 48inline namespace fundamentals_v1 49{ 50_GLIBCXX_BEGIN_NAMESPACE_VERSION 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 = const _CharT*; 82 using const_pointer = const _CharT*; 83 using reference = const _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 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 // TODO: Assert to restore in a way compatible with the constexpr. 182 // __glibcxx_assert(__pos < this->_M_len); 183 return *(this->_M_str + __pos); 184 } 185 186 constexpr const _CharT& 187 at(size_type __pos) const 188 { 189 return __pos < this->_M_len 190 ? *(this->_M_str + __pos) 191 : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos " 192 "(which is %zu) >= this->size() " 193 "(which is %zu)"), 194 __pos, this->size()), 195 *this->_M_str); 196 } 197 198 constexpr const _CharT& 199 front() const 200 { 201 // TODO: Assert to restore in a way compatible with the constexpr. 202 // __glibcxx_assert(this->_M_len > 0); 203 return *this->_M_str; 204 } 205 206 constexpr const _CharT& 207 back() const 208 { 209 // TODO: Assert to restore in a way compatible with the constexpr. 210 // __glibcxx_assert(this->_M_len > 0); 211 return *(this->_M_str + this->_M_len - 1); 212 } 213 214 constexpr const _CharT* 215 data() const noexcept 216 { return this->_M_str; } 217 218 // [string.view.modifiers], modifiers: 219 220 constexpr void 221 remove_prefix(size_type __n) 222 { 223 __glibcxx_assert(this->_M_len >= __n); 224 this->_M_str += __n; 225 this->_M_len -= __n; 226 } 227 228 constexpr void 229 remove_suffix(size_type __n) 230 { this->_M_len -= __n; } 231 232 constexpr void 233 swap(basic_string_view& __sv) noexcept 234 { 235 auto __tmp = *this; 236 *this = __sv; 237 __sv = __tmp; 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 constexpr 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 constexpr int 298 compare(size_type __pos1, size_type __n1, basic_string_view __str) const 299 { return this->substr(__pos1, __n1).compare(__str); } 300 301 constexpr 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 constexpr int 307 compare(const _CharT* __str) const noexcept 308 { return this->compare(basic_string_view{__str}); } 309 310 constexpr 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 constexpr 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 constexpr 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 constexpr size_type 327 find(_CharT __c, size_type __pos=0) const noexcept; 328 329 constexpr size_type 330 find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 331 332 constexpr 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 constexpr 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 constexpr size_type 341 rfind(_CharT __c, size_type __pos = npos) const noexcept; 342 343 constexpr size_type 344 rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 345 346 constexpr 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 constexpr 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 constexpr size_type 355 find_first_of(_CharT __c, size_type __pos = 0) const noexcept 356 { return this->find(__c, __pos); } 357 358 constexpr size_type 359 find_first_of(const _CharT* __str, size_type __pos, size_type __n) const; 360 361 constexpr 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 constexpr 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 constexpr size_type 371 find_last_of(_CharT __c, size_type __pos=npos) const noexcept 372 { return this->rfind(__c, __pos); } 373 374 constexpr size_type 375 find_last_of(const _CharT* __str, size_type __pos, size_type __n) const; 376 377 constexpr 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 constexpr 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 constexpr size_type 387 find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; 388 389 constexpr size_type 390 find_first_not_of(const _CharT* __str, 391 size_type __pos, size_type __n) const; 392 393 constexpr 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 constexpr 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 constexpr size_type 406 find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; 407 408 constexpr size_type 409 find_last_not_of(const _CharT* __str, 410 size_type __pos, size_type __n) const; 411 412 constexpr 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 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_GLIBCXX_END_NAMESPACE_VERSION 437 438 // [string.view.comparison], non-member basic_string_view comparison functions 439 440 namespace __detail 441 { 442_GLIBCXX_BEGIN_NAMESPACE_VERSION 443 // Identity transform to create a non-deduced context, so that only one 444 // argument participates in template argument deduction and the other 445 // argument gets implicitly converted to the deduced type. See n3766.html. 446 template<typename _Tp> 447 using __idt = common_type_t<_Tp>; 448_GLIBCXX_END_NAMESPACE_VERSION 449 } 450 451_GLIBCXX_BEGIN_NAMESPACE_VERSION 452 453 template<typename _CharT, typename _Traits> 454 constexpr bool 455 operator==(basic_string_view<_CharT, _Traits> __x, 456 basic_string_view<_CharT, _Traits> __y) noexcept 457 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 458 459 template<typename _CharT, typename _Traits> 460 constexpr bool 461 operator==(basic_string_view<_CharT, _Traits> __x, 462 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 463 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 464 465 template<typename _CharT, typename _Traits> 466 constexpr bool 467 operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 468 basic_string_view<_CharT, _Traits> __y) noexcept 469 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 470 471 template<typename _CharT, typename _Traits> 472 constexpr bool 473 operator!=(basic_string_view<_CharT, _Traits> __x, 474 basic_string_view<_CharT, _Traits> __y) noexcept 475 { return !(__x == __y); } 476 477 template<typename _CharT, typename _Traits> 478 constexpr bool 479 operator!=(basic_string_view<_CharT, _Traits> __x, 480 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 481 { return !(__x == __y); } 482 483 template<typename _CharT, typename _Traits> 484 constexpr bool 485 operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 486 basic_string_view<_CharT, _Traits> __y) noexcept 487 { return !(__x == __y); } 488 489 template<typename _CharT, typename _Traits> 490 constexpr bool 491 operator< (basic_string_view<_CharT, _Traits> __x, 492 basic_string_view<_CharT, _Traits> __y) noexcept 493 { return __x.compare(__y) < 0; } 494 495 template<typename _CharT, typename _Traits> 496 constexpr bool 497 operator< (basic_string_view<_CharT, _Traits> __x, 498 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 499 { return __x.compare(__y) < 0; } 500 501 template<typename _CharT, typename _Traits> 502 constexpr bool 503 operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 504 basic_string_view<_CharT, _Traits> __y) noexcept 505 { return __x.compare(__y) < 0; } 506 507 template<typename _CharT, typename _Traits> 508 constexpr bool 509 operator> (basic_string_view<_CharT, _Traits> __x, 510 basic_string_view<_CharT, _Traits> __y) noexcept 511 { return __x.compare(__y) > 0; } 512 513 template<typename _CharT, typename _Traits> 514 constexpr bool 515 operator> (basic_string_view<_CharT, _Traits> __x, 516 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 517 { return __x.compare(__y) > 0; } 518 519 template<typename _CharT, typename _Traits> 520 constexpr bool 521 operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 522 basic_string_view<_CharT, _Traits> __y) noexcept 523 { return __x.compare(__y) > 0; } 524 525 template<typename _CharT, typename _Traits> 526 constexpr bool 527 operator<=(basic_string_view<_CharT, _Traits> __x, 528 basic_string_view<_CharT, _Traits> __y) noexcept 529 { return __x.compare(__y) <= 0; } 530 531 template<typename _CharT, typename _Traits> 532 constexpr bool 533 operator<=(basic_string_view<_CharT, _Traits> __x, 534 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 535 { return __x.compare(__y) <= 0; } 536 537 template<typename _CharT, typename _Traits> 538 constexpr bool 539 operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 540 basic_string_view<_CharT, _Traits> __y) noexcept 541 { return __x.compare(__y) <= 0; } 542 543 template<typename _CharT, typename _Traits> 544 constexpr bool 545 operator>=(basic_string_view<_CharT, _Traits> __x, 546 basic_string_view<_CharT, _Traits> __y) noexcept 547 { return __x.compare(__y) >= 0; } 548 549 template<typename _CharT, typename _Traits> 550 constexpr bool 551 operator>=(basic_string_view<_CharT, _Traits> __x, 552 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 553 { return __x.compare(__y) >= 0; } 554 555 template<typename _CharT, typename _Traits> 556 constexpr bool 557 operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 558 basic_string_view<_CharT, _Traits> __y) noexcept 559 { return __x.compare(__y) >= 0; } 560 561 // [string.view.io], Inserters and extractors 562 template<typename _CharT, typename _Traits> 563 inline basic_ostream<_CharT, _Traits>& 564 operator<<(basic_ostream<_CharT, _Traits>& __os, 565 basic_string_view<_CharT,_Traits> __str) 566 { return __ostream_insert(__os, __str.data(), __str.size()); } 567 568 569 // basic_string_view typedef names 570 571 using string_view = basic_string_view<char>; 572#ifdef _GLIBCXX_USE_WCHAR_T 573 using wstring_view = basic_string_view<wchar_t>; 574#endif 575#ifdef _GLIBCXX_USE_C99_STDINT_TR1 576 using u16string_view = basic_string_view<char16_t>; 577 using u32string_view = basic_string_view<char32_t>; 578#endif 579 580_GLIBCXX_END_NAMESPACE_VERSION 581} // namespace fundamentals_v1 582} // namespace experimental 583 584 585 // [string.view.hash], hash support: 586 587_GLIBCXX_BEGIN_NAMESPACE_VERSION 588 template<typename _Tp> 589 struct hash; 590 591 template<> 592 struct hash<experimental::string_view> 593 : public __hash_base<size_t, experimental::string_view> 594 { 595 size_t 596 operator()(const experimental::string_view& __str) const noexcept 597 { return std::_Hash_impl::hash(__str.data(), __str.length()); } 598 }; 599 600 template<> 601 struct __is_fast_hash<hash<experimental::string_view>> : std::false_type 602 { }; 603 604#ifdef _GLIBCXX_USE_WCHAR_T 605 template<> 606 struct hash<experimental::wstring_view> 607 : public __hash_base<size_t, wstring> 608 { 609 size_t 610 operator()(const experimental::wstring_view& __s) const noexcept 611 { return std::_Hash_impl::hash(__s.data(), 612 __s.length() * sizeof(wchar_t)); } 613 }; 614 615 template<> 616 struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type 617 { }; 618#endif 619 620#ifdef _GLIBCXX_USE_C99_STDINT_TR1 621 template<> 622 struct hash<experimental::u16string_view> 623 : public __hash_base<size_t, experimental::u16string_view> 624 { 625 size_t 626 operator()(const experimental::u16string_view& __s) const noexcept 627 { return std::_Hash_impl::hash(__s.data(), 628 __s.length() * sizeof(char16_t)); } 629 }; 630 631 template<> 632 struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type 633 { }; 634 635 template<> 636 struct hash<experimental::u32string_view> 637 : public __hash_base<size_t, experimental::u32string_view> 638 { 639 size_t 640 operator()(const experimental::u32string_view& __s) const noexcept 641 { return std::_Hash_impl::hash(__s.data(), 642 __s.length() * sizeof(char32_t)); } 643 }; 644 645 template<> 646 struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type 647 { }; 648#endif 649_GLIBCXX_END_NAMESPACE_VERSION 650 651namespace experimental 652{ 653 // I added these EMSR. 654 inline namespace literals 655 { 656 inline namespace string_view_literals 657 { 658 _GLIBCXX_BEGIN_NAMESPACE_VERSION 659 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_C99_STDINT_TR1 671 inline constexpr basic_string_view<char16_t> 672 operator""sv(const char16_t* __str, size_t __len) noexcept 673 { return basic_string_view<char16_t>{__str, __len}; } 674 675 inline constexpr basic_string_view<char32_t> 676 operator""sv(const char32_t* __str, size_t __len) noexcept 677 { return basic_string_view<char32_t>{__str, __len}; } 678#endif 679 680 _GLIBCXX_END_NAMESPACE_VERSION 681 } // namespace string_literals 682 } // namespace literals 683} // namespace experimental 684} // namespace std 685 686#include <experimental/bits/string_view.tcc> 687 688#endif // __cplusplus <= 201103L 689 690#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW 691