1 // Components for manipulating non-owning sequences of characters -*- C++ -*- 2 3 4 #ifndef COMMON_GDB_STRING_VIEW_H 5 #define COMMON_GDB_STRING_VIEW_H 6 7 // Note: This file has been stolen from the gcc repo 8 // (libstdc++-v3/include/experimental/string_view) and has local modifications. 9 10 // Copyright (C) 2013-2020 Free Software Foundation, Inc. 11 // 12 // This file is part of the GNU ISO C++ Library. This library is free 13 // software; you can redistribute it and/or modify it under the 14 // terms of the GNU General Public License as published by the 15 // Free Software Foundation; either version 3, or (at your option) 16 // any later version. 17 18 // This library is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU General Public License for more details. 22 23 // Under Section 7 of GPL version 3, you are granted additional 24 // permissions described in the GCC Runtime Library Exception, version 25 // 3.1, as published by the Free Software Foundation. 26 27 // You should have received a copy of the GNU General Public License and 28 // a copy of the GCC Runtime Library Exception along with this program; 29 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 30 // <http://www.gnu.org/licenses/>. 31 32 // 33 // N3762 basic_string_view library 34 // 35 36 37 #if __cplusplus >= 201703L 38 39 #include <string_view> 40 41 namespace gdb { 42 using string_view = std::string_view; 43 } /* namespace gdb */ 44 45 #else /* __cplusplus < 201703L */ 46 47 #include <string> 48 #include <limits> 49 #include "gdb_assert.h" 50 51 namespace gdb { 52 53 /** 54 * @class basic_string_view <experimental/string_view> 55 * @brief A non-owning reference to a string. 56 * 57 * @ingroup strings 58 * @ingroup sequences 59 * @ingroup experimental 60 * 61 * @tparam _CharT Type of character 62 * @tparam _Traits Traits for character type, defaults to 63 * char_traits<_CharT>. 64 * 65 * A basic_string_view looks like this: 66 * 67 * @code 68 * _CharT* _M_str 69 * size_t _M_len 70 * @endcode 71 */ 72 template<typename _CharT, typename _Traits = std::char_traits<_CharT>> 73 class basic_string_view 74 { 75 public: 76 77 // types 78 using traits_type = _Traits; 79 using value_type = _CharT; 80 using pointer = const _CharT*; 81 using const_pointer = const _CharT*; 82 using reference = const _CharT&; 83 using const_reference = const _CharT&; 84 using const_iterator = const _CharT*; 85 using iterator = const_iterator; 86 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 87 using reverse_iterator = const_reverse_iterator; 88 using size_type = size_t; 89 using difference_type = ptrdiff_t; 90 static constexpr size_type npos = size_type(-1); 91 92 // [string.view.cons], construct/copy 93 94 constexpr 95 basic_string_view() noexcept 96 : _M_len{0}, _M_str{nullptr} 97 { } 98 99 constexpr basic_string_view(const basic_string_view&) noexcept = default; 100 101 template<typename _Allocator> 102 basic_string_view(const std::basic_string<_CharT, _Traits, 103 _Allocator>& __str) noexcept 104 : _M_len{__str.length()}, _M_str{__str.data()} 105 { } 106 107 /*constexpr*/ basic_string_view(const _CharT* __str) 108 : _M_len{__str == nullptr ? 0 : traits_type::length(__str)}, 109 _M_str{__str} 110 { } 111 112 constexpr basic_string_view(const _CharT* __str, size_type __len) 113 : _M_len{__len}, 114 _M_str{__str} 115 { } 116 117 basic_string_view& 118 operator=(const basic_string_view&) noexcept = default; 119 120 // [string.view.iterators], iterators 121 122 constexpr const_iterator 123 begin() const noexcept 124 { return this->_M_str; } 125 126 constexpr const_iterator 127 end() const noexcept 128 { return this->_M_str + this->_M_len; } 129 130 constexpr const_iterator 131 cbegin() const noexcept 132 { return this->_M_str; } 133 134 constexpr const_iterator 135 cend() const noexcept 136 { return this->_M_str + this->_M_len; } 137 138 const_reverse_iterator 139 rbegin() const noexcept 140 { return const_reverse_iterator(this->end()); } 141 142 const_reverse_iterator 143 rend() const noexcept 144 { return const_reverse_iterator(this->begin()); } 145 146 const_reverse_iterator 147 crbegin() const noexcept 148 { return const_reverse_iterator(this->end()); } 149 150 const_reverse_iterator 151 crend() const noexcept 152 { return const_reverse_iterator(this->begin()); } 153 154 // [string.view.capacity], capacity 155 156 constexpr size_type 157 size() const noexcept 158 { return this->_M_len; } 159 160 constexpr size_type 161 length() const noexcept 162 { return _M_len; } 163 164 constexpr size_type 165 max_size() const noexcept 166 { 167 return (npos - sizeof(size_type) - sizeof(void*)) 168 / sizeof(value_type) / 4; 169 } 170 171 constexpr bool 172 empty() const noexcept 173 { return this->_M_len == 0; } 174 175 // [string.view.access], element access 176 177 constexpr const _CharT& 178 operator[](size_type __pos) const 179 { 180 // TODO: Assert to restore in a way compatible with the constexpr. 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 : (error (_("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 // TODO: Assert to restore in a way compatible with the constexpr. 201 // __glibcxx_assert(this->_M_len > 0); 202 return *this->_M_str; 203 } 204 205 constexpr const _CharT& 206 back() const 207 { 208 // TODO: Assert to restore in a way compatible with the constexpr. 209 // __glibcxx_assert(this->_M_len > 0); 210 return *(this->_M_str + this->_M_len - 1); 211 } 212 213 constexpr const _CharT* 214 data() const noexcept 215 { return this->_M_str; } 216 217 // [string.view.modifiers], modifiers: 218 219 /*constexpr*/ void 220 remove_prefix(size_type __n) 221 { 222 gdb_assert (this->_M_len >= __n); 223 this->_M_str += __n; 224 this->_M_len -= __n; 225 } 226 227 /*constexpr*/ void 228 remove_suffix(size_type __n) 229 { this->_M_len -= __n; } 230 231 /*constexpr*/ void 232 swap(basic_string_view& __sv) noexcept 233 { 234 auto __tmp = *this; 235 *this = __sv; 236 __sv = __tmp; 237 } 238 239 240 // [string.view.ops], string operations: 241 242 template<typename _Allocator> 243 explicit operator std::basic_string<_CharT, _Traits, _Allocator>() const 244 { 245 return { this->_M_str, this->_M_len }; 246 } 247 248 size_type 249 copy(_CharT* __str, size_type __n, size_type __pos = 0) const 250 { 251 gdb_assert (__str != nullptr || __n == 0); 252 if (__pos > this->_M_len) 253 error (_("basic_string_view::copy: __pos " 254 "(which is %zu) > this->size() " 255 "(which is %zu)"), 256 __pos, this->size()); 257 size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})}; 258 for (auto __begin = this->_M_str + __pos, 259 __end = __begin + __rlen; __begin != __end;) 260 *__str++ = *__begin++; 261 return __rlen; 262 } 263 264 265 // [string.view.ops], string operations: 266 267 /*constexpr*/ basic_string_view 268 substr(size_type __pos, size_type __n=npos) const 269 { 270 return __pos <= this->_M_len 271 ? basic_string_view{this->_M_str + __pos, 272 std::min(__n, size_type{this->_M_len - __pos})} 273 : (error (_("basic_string_view::substr: __pos " 274 "(which is %zu) > this->size() " 275 "(which is %zu)"), 276 __pos, this->size()), basic_string_view{}); 277 } 278 279 /*constexpr*/ int 280 compare(basic_string_view __str) const noexcept 281 { 282 int __ret = traits_type::compare(this->_M_str, __str._M_str, 283 std::min(this->_M_len, __str._M_len)); 284 if (__ret == 0) 285 __ret = _S_compare(this->_M_len, __str._M_len); 286 return __ret; 287 } 288 289 /*constexpr*/ int 290 compare(size_type __pos1, size_type __n1, basic_string_view __str) const 291 { return this->substr(__pos1, __n1).compare(__str); } 292 293 /*constexpr*/ int 294 compare(size_type __pos1, size_type __n1, 295 basic_string_view __str, size_type __pos2, size_type __n2) const 296 { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } 297 298 /*constexpr*/ int 299 compare(const _CharT* __str) const noexcept 300 { return this->compare(basic_string_view{__str}); } 301 302 /*constexpr*/ int 303 compare(size_type __pos1, size_type __n1, const _CharT* __str) const 304 { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } 305 306 /*constexpr*/ int 307 compare(size_type __pos1, size_type __n1, 308 const _CharT* __str, size_type __n2) const 309 { 310 return this->substr(__pos1, __n1) 311 .compare(basic_string_view(__str, __n2)); 312 } 313 314 /*constexpr*/ size_type 315 find(basic_string_view __str, size_type __pos = 0) const noexcept 316 { return this->find(__str._M_str, __pos, __str._M_len); } 317 318 /*constexpr*/ size_type 319 find(_CharT __c, size_type __pos=0) const noexcept; 320 321 /*constexpr*/ size_type 322 find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 323 324 /*constexpr*/ size_type 325 find(const _CharT* __str, size_type __pos=0) const noexcept 326 { return this->find(__str, __pos, traits_type::length(__str)); } 327 328 /*constexpr*/ size_type 329 rfind(basic_string_view __str, size_type __pos = npos) const noexcept 330 { return this->rfind(__str._M_str, __pos, __str._M_len); } 331 332 /*constexpr*/ size_type 333 rfind(_CharT __c, size_type __pos = npos) const noexcept; 334 335 /*constexpr*/ size_type 336 rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; 337 338 /*constexpr*/ size_type 339 rfind(const _CharT* __str, size_type __pos = npos) const noexcept 340 { return this->rfind(__str, __pos, traits_type::length(__str)); } 341 342 /*constexpr*/ size_type 343 find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept 344 { return this->find_first_of(__str._M_str, __pos, __str._M_len); } 345 346 /*constexpr*/ size_type 347 find_first_of(_CharT __c, size_type __pos = 0) const noexcept 348 { return this->find(__c, __pos); } 349 350 /*constexpr*/ size_type 351 find_first_of(const _CharT* __str, size_type __pos, size_type __n) const; 352 353 /*constexpr*/ size_type 354 find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept 355 { return this->find_first_of(__str, __pos, traits_type::length(__str)); } 356 357 /*constexpr*/ size_type 358 find_last_of(basic_string_view __str, 359 size_type __pos = npos) const noexcept 360 { return this->find_last_of(__str._M_str, __pos, __str._M_len); } 361 362 size_type 363 find_last_of(_CharT __c, size_type __pos=npos) const noexcept 364 { return this->rfind(__c, __pos); } 365 366 /*constexpr*/ size_type 367 find_last_of(const _CharT* __str, size_type __pos, size_type __n) const; 368 369 /*constexpr*/ size_type 370 find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept 371 { return this->find_last_of(__str, __pos, traits_type::length(__str)); } 372 373 /*constexpr*/ size_type 374 find_first_not_of(basic_string_view __str, 375 size_type __pos = 0) const noexcept 376 { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } 377 378 /*constexpr*/ size_type 379 find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; 380 381 /*constexpr*/ size_type 382 find_first_not_of(const _CharT* __str, 383 size_type __pos, size_type __n) const; 384 385 /*constexpr*/ size_type 386 find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept 387 { 388 return this->find_first_not_of(__str, __pos, 389 traits_type::length(__str)); 390 } 391 392 /*constexpr*/ size_type 393 find_last_not_of(basic_string_view __str, 394 size_type __pos = npos) const noexcept 395 { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } 396 397 /*constexpr*/ size_type 398 find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; 399 400 /*constexpr*/ size_type 401 find_last_not_of(const _CharT* __str, 402 size_type __pos, size_type __n) const; 403 404 /*constexpr*/ size_type 405 find_last_not_of(const _CharT* __str, 406 size_type __pos = npos) const noexcept 407 { 408 return this->find_last_not_of(__str, __pos, 409 traits_type::length(__str)); 410 } 411 412 private: 413 414 static constexpr int 415 _S_compare(size_type __n1, size_type __n2) noexcept 416 { 417 return difference_type(__n1 - __n2) > std::numeric_limits<int>::max() 418 ? std::numeric_limits<int>::max() 419 : difference_type(__n1 - __n2) < std::numeric_limits<int>::min() 420 ? std::numeric_limits<int>::min() 421 : static_cast<int>(difference_type(__n1 - __n2)); 422 } 423 424 size_t _M_len; 425 const _CharT* _M_str; 426 }; 427 428 // [string.view.comparison], non-member basic_string_view comparison functions 429 430 namespace __detail 431 { 432 // Identity transform to create a non-deduced context, so that only one 433 // argument participates in template argument deduction and the other 434 // argument gets implicitly converted to the deduced type. See n3766.html. 435 template<typename _Tp> 436 using __idt = typename std::common_type<_Tp>::type; 437 } 438 439 template<typename _CharT, typename _Traits> 440 /*constexpr*/ bool 441 operator==(basic_string_view<_CharT, _Traits> __x, 442 basic_string_view<_CharT, _Traits> __y) noexcept 443 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 444 445 template<typename _CharT, typename _Traits> 446 /*constexpr*/ bool 447 operator==(basic_string_view<_CharT, _Traits> __x, 448 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 449 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 450 451 template<typename _CharT, typename _Traits> 452 /*constexpr*/ bool 453 operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 454 basic_string_view<_CharT, _Traits> __y) noexcept 455 { return __x.size() == __y.size() && __x.compare(__y) == 0; } 456 457 template<typename _CharT, typename _Traits> 458 /*constexpr*/ bool 459 operator!=(basic_string_view<_CharT, _Traits> __x, 460 basic_string_view<_CharT, _Traits> __y) noexcept 461 { return !(__x == __y); } 462 463 template<typename _CharT, typename _Traits> 464 /*constexpr*/ bool 465 operator!=(basic_string_view<_CharT, _Traits> __x, 466 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 467 { return !(__x == __y); } 468 469 template<typename _CharT, typename _Traits> 470 /*constexpr*/ bool 471 operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 472 basic_string_view<_CharT, _Traits> __y) noexcept 473 { return !(__x == __y); } 474 475 template<typename _CharT, typename _Traits> 476 /*constexpr*/ bool 477 operator< (basic_string_view<_CharT, _Traits> __x, 478 basic_string_view<_CharT, _Traits> __y) noexcept 479 { return __x.compare(__y) < 0; } 480 481 template<typename _CharT, typename _Traits> 482 /*constexpr*/ bool 483 operator< (basic_string_view<_CharT, _Traits> __x, 484 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 485 { return __x.compare(__y) < 0; } 486 487 template<typename _CharT, typename _Traits> 488 /*constexpr*/ bool 489 operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 490 basic_string_view<_CharT, _Traits> __y) noexcept 491 { return __x.compare(__y) < 0; } 492 493 template<typename _CharT, typename _Traits> 494 /*constexpr*/ bool 495 operator> (basic_string_view<_CharT, _Traits> __x, 496 basic_string_view<_CharT, _Traits> __y) noexcept 497 { return __x.compare(__y) > 0; } 498 499 template<typename _CharT, typename _Traits> 500 /*constexpr*/ bool 501 operator> (basic_string_view<_CharT, _Traits> __x, 502 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 503 { return __x.compare(__y) > 0; } 504 505 template<typename _CharT, typename _Traits> 506 /*constexpr*/ bool 507 operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 508 basic_string_view<_CharT, _Traits> __y) noexcept 509 { return __x.compare(__y) > 0; } 510 511 template<typename _CharT, typename _Traits> 512 /*constexpr*/ bool 513 operator<=(basic_string_view<_CharT, _Traits> __x, 514 basic_string_view<_CharT, _Traits> __y) noexcept 515 { return __x.compare(__y) <= 0; } 516 517 template<typename _CharT, typename _Traits> 518 /*constexpr*/ bool 519 operator<=(basic_string_view<_CharT, _Traits> __x, 520 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 521 { return __x.compare(__y) <= 0; } 522 523 template<typename _CharT, typename _Traits> 524 /*constexpr*/ bool 525 operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 526 basic_string_view<_CharT, _Traits> __y) noexcept 527 { return __x.compare(__y) <= 0; } 528 529 template<typename _CharT, typename _Traits> 530 /*constexpr*/ bool 531 operator>=(basic_string_view<_CharT, _Traits> __x, 532 basic_string_view<_CharT, _Traits> __y) noexcept 533 { return __x.compare(__y) >= 0; } 534 535 template<typename _CharT, typename _Traits> 536 /*constexpr*/ bool 537 operator>=(basic_string_view<_CharT, _Traits> __x, 538 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept 539 { return __x.compare(__y) >= 0; } 540 541 template<typename _CharT, typename _Traits> 542 /*constexpr*/ bool 543 operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x, 544 basic_string_view<_CharT, _Traits> __y) noexcept 545 { return __x.compare(__y) >= 0; } 546 547 // basic_string_view typedef names 548 549 using string_view = basic_string_view<char>; 550 } /* namespace gdb */ 551 552 #include "gdb_string_view.tcc" 553 554 #endif // __cplusplus < 201703L 555 556 namespace gdb { 557 558 static inline std::string 559 to_string(const gdb::string_view &view) 560 { 561 return { view.data (), view.size () }; 562 } 563 564 } 565 566 #endif /* COMMON_GDB_STRING_VIEW_H */ 567