1#ifndef MSTL_CORE_STRING_BASIC_STRING_HPP__
2#define MSTL_CORE_STRING_BASIC_STRING_HPP__
3#include <initializer_list>
9#include "string_view.hpp"
12template <
typename CharT,
typename Traits,
typename Alloc>
15template <
bool IsConst,
typename String>
16struct basic_string_iterator {
18 using container_type = String;
19 using iterator = basic_string_iterator<false, container_type>;
20 using const_iterator = basic_string_iterator<true, container_type>;
23 using iterator_category = contiguous_iterator_tag;
24 using value_type =
typename container_type::value_type;
27 using difference_type =
typename container_type::difference_type;
28 using size_type =
typename container_type::size_type;
31 pointer ptr_ =
nullptr;
32 const container_type* str_ =
nullptr;
34 template <
typename,
typename,
typename>
friend class basic_string;
35 template <
bool,
typename>
friend struct basic_string_iterator;
38 MSTL_CONSTEXPR20 basic_string_iterator() =
default;
39 MSTL_CONSTEXPR20 basic_string_iterator(pointer ptr) : ptr_(ptr) {}
40 MSTL_CONSTEXPR20 basic_string_iterator(pointer ptr,
const container_type* vec) : ptr_(ptr), str_(vec) {}
42 MSTL_CONSTEXPR20 basic_string_iterator(
const iterator& x) noexcept
43 : ptr_(
const_cast<pointer
>(x.ptr_)), str_(x.str_) {}
45 MSTL_CONSTEXPR20 basic_string_iterator& operator =(
const iterator& rhs)
noexcept {
47 ptr_ =
const_cast<pointer
>(rhs.ptr_);
52 MSTL_CONSTEXPR20 basic_string_iterator(iterator&& x) noexcept
53 : ptr_(
const_cast<pointer
>(x.ptr_)), str_(x.str_) {
58 MSTL_CONSTEXPR20 basic_string_iterator& operator =(iterator&& rhs)
noexcept {
60 ptr_ =
const_cast<pointer
>(rhs.ptr_);
67 MSTL_CONSTEXPR20 basic_string_iterator(
const const_iterator& x) noexcept
68 : ptr_(
const_cast<pointer
>(x.ptr_)), str_(x.str_) {}
70 MSTL_CONSTEXPR20 basic_string_iterator& operator =(
const const_iterator& rhs)
noexcept {
72 ptr_ =
const_cast<pointer
>(rhs.ptr_);
77 MSTL_CONSTEXPR20 basic_string_iterator(const_iterator&& x) noexcept
78 : ptr_(
const_cast<pointer
>(x.ptr_)), str_(x.str_) {
83 MSTL_CONSTEXPR20 basic_string_iterator& operator =(const_iterator&& rhs)
noexcept {
85 ptr_ =
const_cast<pointer
>(rhs.ptr_);
92 MSTL_CONSTEXPR20 ~basic_string_iterator() noexcept = default;
94 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator *() const noexcept {
95 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
96 MSTL_DEBUG_VERIFY(str_->data() <= ptr_ && ptr_ <= str_->
data() + str_->size_,
97 __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
100 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer operator ->() const noexcept {
104 MSTL_CONSTEXPR20 basic_string_iterator& operator ++() noexcept {
105 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
106 MSTL_DEBUG_VERIFY(ptr_ < str_->
data() + str_->size_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
110 MSTL_CONSTEXPR20 basic_string_iterator operator ++(
int)
noexcept {
111 basic_string_iterator tmp = *
this;
116 MSTL_CONSTEXPR20 basic_string_iterator& operator --() noexcept {
117 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
118 MSTL_DEBUG_VERIFY(str_->data() < ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
122 MSTL_CONSTEXPR20 basic_string_iterator operator --(
int)
noexcept {
123 basic_string_iterator tmp = *
this;
128 MSTL_CONSTEXPR20 basic_string_iterator& operator +=(difference_type n)
noexcept {
130 MSTL_DEBUG_VERIFY((ptr_ && str_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
131 MSTL_DEBUG_VERIFY(n >= str_->data() - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
134 MSTL_DEBUG_VERIFY((ptr_ && str_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
135 MSTL_DEBUG_VERIFY(n <= str_->
data() + str_->size_ - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
140 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string_iterator operator +(
const difference_type n)
const noexcept {
141 basic_string_iterator tmp = *
this;
145 MSTL_NODISCARD
friend MSTL_CONSTEXPR20 basic_string_iterator operator +(
const difference_type n,
const basic_string_iterator& it)
noexcept {
149 MSTL_CONSTEXPR20 basic_string_iterator& operator -=(difference_type n)
noexcept {
153 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string_iterator operator -(difference_type n)
const noexcept {
158 MSTL_NODISCARD MSTL_CONSTEXPR20 difference_type operator -(
const basic_string_iterator& rhs)
const noexcept {
159 return static_cast<difference_type
>(ptr_ - rhs.ptr_);
162 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](difference_type n)
const noexcept {
166 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
const basic_string_iterator& rhs)
const noexcept {
167 MSTL_DEBUG_VERIFY(str_ == rhs.str_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
168 return ptr_ == rhs.ptr_;
170 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator !=(
const basic_string_iterator& rhs)
const noexcept {
171 return !(*
this == rhs);
173 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
const basic_string_iterator& rhs)
const noexcept {
174 MSTL_DEBUG_VERIFY(str_ == rhs.str_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
175 return ptr_ < rhs.ptr_;
177 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >(
const basic_string_iterator& rhs)
const noexcept {
180 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <=(
const basic_string_iterator& rhs)
const noexcept {
181 return !(*
this > rhs);
183 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >=(
const basic_string_iterator& rhs)
const noexcept {
184 return !(*
this < rhs);
188template <
typename CharT,
typename Traits =
char_traits<CharT>,
typename Alloc = allocator<CharT>>
189class basic_string :
public icommon<basic_string<CharT, Traits, Alloc>> {
190#ifdef MSTL_STANDARD_20__
191 static_assert(is_allocator_v<Alloc>,
"Alloc type is not a standard allocator type.");
193 static_assert(is_same_v<CharT, typename Alloc::value_type>,
"allocator type mismatch.");
194 static_assert(is_same_v<CharT, typename Traits::char_type>,
"trait type mismatch.");
195 static_assert(!is_array_v<CharT> && is_trivial_v<CharT> && is_standard_layout_v<CharT>,
196 "basic string only contains non-array trivial standard-layout types.");
201 using iterator = basic_string_iterator<false, basic_string>;
202 using const_iterator = basic_string_iterator<true, basic_string>;
203 using reverse_iterator =
_MSTL reverse_iterator<iterator>;
204 using const_reverse_iterator =
_MSTL reverse_iterator<const_iterator>;
206 using traits_type = Traits;
207 using view_type = basic_string_view<CharT, Traits>;
208 using allocator_type = Alloc;
210 static constexpr size_type npos = string_view::npos;
213 pointer data_ =
nullptr;
215 compressed_pair<allocator_type, size_type> capacity_pair_{ default_construct_tag{}, 0 };
217 template <
bool,
typename>
friend struct basic_string_iterator;
220 MSTL_CONSTEXPR20
void null_terminate() {
221 if (data_ && size_ < capacity_pair_.value) {
222 traits_type::assign(data_ + size_, 1, value_type());
223 }
else if (size_ == capacity_pair_.value) {
224 this->reserve(capacity_pair_.value * 1.5);
225 traits_type::assign(data_ + size_, 1, value_type());
229 template <
typename Iterator, enable_if_t<!is_ranges_fwd_iter_v<Iterator>,
int> = 0>
230 MSTL_CONSTEXPR20
void construct_from_iter(Iterator first, Iterator last) {
232 const size_type init_size =
_MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
233 pointer temp_data =
nullptr;
234 size_type temp_size = 0;
236 temp_data = capacity_pair_.get_base().allocate(init_size);
241 capacity_pair_.value = init_size;
246 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
253 template <
typename Iterator, enable_if_t<is_ranges_fwd_iter_v<Iterator>,
int> = 0>
254 MSTL_CONSTEXPR20
void construct_from_iter(Iterator first, Iterator last) {
256 const size_type init_size =
_MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
257 pointer temp_data =
nullptr;
259 temp_data = capacity_pair_.get_base().allocate(init_size);
261 capacity_pair_.value = init_size;
266 capacity_pair_.value = init_size;
271 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
278 MSTL_CONSTEXPR20
void construct_from_ptr(const_pointer str, size_type position, size_type n) {
279 pointer temp_data =
nullptr;
280 size_type temp_capacity = 0;
282 temp_capacity =
_MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
283 temp_data = capacity_pair_.get_base().allocate(temp_capacity);
284 traits_type::copy(temp_data, str + position, n);
288 capacity_pair_.value = temp_capacity;
292 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
296 capacity_pair_.value = 0;
301 MSTL_CONSTEXPR20
void destroy_buffer() noexcept {
303 if (capacity_pair_.value > 0) {
304 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
308 capacity_pair_.value = 0;
312 MSTL_CONSTEXPR20 basic_string& replace_fill(iterator first, size_type n1,
const size_type n2,
const value_type chr) {
313 if (
static_cast<size_type
>(end() - first) < n1) {
317 const size_type diff = n2 - n1;
318 MSTL_DEBUG_VERIFY(size_ + diff < max_size(),
"basic_string index out of range.");
319 if (size_ > capacity_pair_.value - diff)
321 pointer raw_ptr = &*first;
322 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
323 traits_type::assign(raw_ptr, n2, chr);
327 pointer raw_ptr = &*first;
328 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
329 traits_type::assign(raw_ptr, n2, chr);
336 template <
typename Iterator,
338 MSTL_CONSTEXPR20 basic_string& replace_copy(iterator first1, iterator last1, Iterator first2, Iterator last2) {
342 const size_type diff = len2 - len1;
343 MSTL_DEBUG_VERIFY(size_ + diff < max_size(),
"basic_string replace_copy index out of range.");
344 if (size_ > capacity_pair_.value - diff)
346 pointer raw_ptr = &*first1;
347 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
348 traits_type::copy(raw_ptr, &*first2, len2);
352 pointer raw_ptr = &*first1;
353 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
354 traits_type::copy(raw_ptr, &*first2, len2);
355 size_ -= len1 - len2;
361 template <
typename Iterator>
362 MSTL_CONSTEXPR20 basic_string& replace_copy(iterator first1,
const size_type n1, Iterator first2,
const size_type n2) {
363 return this->replace_copy(first1, first1 + n1, first2,
_MSTL next(first2, n2));
366 MSTL_CONSTEXPR20
void reallocate(size_type n) {
367 pointer new_buffer =
nullptr;
370 capacity_pair_.value + n,
371 capacity_pair_.value + (capacity_pair_.value >> 1)
373 new_buffer = capacity_pair_.get_base().allocate(new_cap);
374 traits_type::move(new_buffer, data_, size_);
376 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
378 capacity_pair_.value = new_cap;
382 capacity_pair_.get_base().deallocate(new_buffer, capacity_pair_.value);
388 MSTL_CONSTEXPR20 iterator reallocate_and_fill(iterator position, size_type n, value_type chr) {
389 const difference_type diff = (&*position) - data_;
390 const size_t old_cap = capacity_pair_.value;
391 const size_t new_cap =
_MSTL max(old_cap + n, old_cap + (old_cap >> 1));
392 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
393 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
394 pointer end2 = traits_type::assign(end1, n, chr) + n;
395 traits_type::move(end2, data_ + diff, size_ - diff);
396 capacity_pair_.get_base().deallocate(data_, old_cap);
399 capacity_pair_.value = new_cap;
401 return iterator(data_ + diff,
this);
404 MSTL_CONSTEXPR20 iterator reallocate_and_copy(iterator position, const_iterator first, const_iterator last) {
405 const difference_type diff = position - data_;
406 const size_type old_cap = capacity_pair_.value;
408 const size_t new_cap =
_MSTL max(old_cap + n, old_cap + (old_cap >> 1));
409 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
410 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
412 traits_type::move(end2, data_ + diff, size_ - diff);
413 capacity_pair_.get_base().deallocate(data_, old_cap);
416 capacity_pair_.value = new_cap;
418 return iterator(data_ + diff,
this);
422 MSTL_CONSTEXPR20 basic_string() {
426 MSTL_CONSTEXPR20
explicit basic_string(size_type n)
427 : basic_string(n, static_cast<value_type>(0)) {}
429 MSTL_CONSTEXPR20
explicit basic_string(size_type n,
int32_t chr)
430 : basic_string(n, static_cast<value_type>(chr)) {}
432 MSTL_CONSTEXPR20
explicit basic_string(size_type n, value_type chr) {
433 const size_type init_size =
_MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
434 data_ = capacity_pair_.get_base().allocate(init_size);
435 traits_type::assign(data_, n, chr);
437 capacity_pair_.value = init_size;
441 MSTL_CONSTEXPR20 basic_string& operator =(value_type chr) {
442 if (capacity_pair_.value < 1) {
443 pointer new_buffer = capacity_pair_.get_base().allocate(2);
444 capacity_pair_.get_base().deallocate(data_);
446 capacity_pair_.value = 2;
454 MSTL_CONSTEXPR20 basic_string(
const basic_string& str) {
455 this->construct_from_ptr(str.data(), 0, str.size_);
458 MSTL_CONSTEXPR20 basic_string& operator =(
const basic_string& str) {
461 this->construct_from_ptr(str.data(), 0, str.size_);
465 MSTL_CONSTEXPR20 basic_string(basic_string&& str) noexcept
466 : data_(str.data_), size_(str.size_),
467 capacity_pair_(
_MSTL move(str.capacity_pair_)) {
470 str.capacity_pair_.
value = 0;
473 MSTL_CONSTEXPR20 basic_string& operator =(basic_string&& str)
noexcept {
476 pointer new_data = str.data_;
477 const size_type new_size = str.size_;
478 auto new_capacity_pair =
_MSTL move(str.capacity_pair_);
482 str.capacity_pair_.
value = 0;
487 capacity_pair_ =
_MSTL move(new_capacity_pair);
492 MSTL_CONSTEXPR20 basic_string(view_type str) {
493 this->construct_from_ptr(str.data(), 0, str.size());
496 MSTL_CONSTEXPR20 basic_string(view_type str,
const size_type n) {
497 this->construct_from_ptr(str.data(), 0, n);
500 MSTL_CONSTEXPR20 basic_string& operator =(view_type str) {
501 const size_type len = str.size();
502 if (capacity_pair_.value < len) {
503 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
504 capacity_pair_.get_base().deallocate(data_);
506 capacity_pair_.value = len + 1;
508 traits_type::copy(data_, str.data(), len);
514 MSTL_CONSTEXPR20 basic_string(
const basic_string& str, size_type position) {
515 this->construct_from_ptr(str.data_, position, str.size_ - position);
518 MSTL_CONSTEXPR20 basic_string(
const basic_string& str,
const size_type position,
const size_type n) {
519 this->construct_from_ptr(str.data_, position, n);
522 MSTL_CONSTEXPR20 basic_string(const_pointer str) {
523 this->construct_from_ptr(str, 0, traits_type::length(str));
526 MSTL_CONSTEXPR20 basic_string(const_pointer str,
const size_type n) {
527 this->construct_from_ptr(str, 0, n);
530 MSTL_CONSTEXPR20 basic_string& operator =(const_pointer str) {
531 const size_type len = traits_type::length(str);
532 if (capacity_pair_.value < len) {
533 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
534 capacity_pair_.get_base().deallocate(data_);
536 capacity_pair_.value = len + 1;
538 traits_type::copy(data_, str, len);
544 template <
typename Iterator, enable_if_t<!is_convertible_v<Iterator, value_type>,
int> = 0>
545 MSTL_CONSTEXPR20 basic_string(Iterator first, Iterator last) {
546 this->construct_from_iter(first, last);
549 MSTL_CONSTEXPR20 basic_string(std::initializer_list<value_type> l) : basic_string(l.begin(), l.end()) {}
550 MSTL_CONSTEXPR20 basic_string& operator =(std::initializer_list<value_type> l) {
552 this->insert(begin(), l.begin(), l.end());
556 MSTL_CONSTEXPR20 ~basic_string() { destroy_buffer(); }
558 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator begin() noexcept {
return {data_,
this}; }
559 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator end() noexcept {
return {data_ + size_,
this}; }
560 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator begin() const noexcept {
return cbegin(); }
561 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator end() const noexcept {
return cend(); }
562 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cbegin() const noexcept {
return {data_,
this}; }
563 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cend() const noexcept {
return {data_ + size_,
this}; }
564 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rbegin() noexcept {
return reverse_iterator(end()); }
565 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rend() noexcept {
return reverse_iterator(begin()); }
566 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rbegin() const noexcept {
return crbegin(); }
567 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rend() const noexcept {
return crend(); }
568 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(cend()); }
569 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(cbegin()); }
571 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type size() const noexcept {
return size_; }
572 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type max_size() const noexcept {
return npos; }
573 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type capacity() const noexcept {
return capacity_pair_.value; }
574 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type length() const noexcept {
return size_; }
575 MSTL_NODISCARD MSTL_CONSTEXPR20
bool empty() const noexcept {
return size_ == 0; }
577 MSTL_NODISCARD MSTL_CONSTEXPR20 allocator_type get_allocator() const noexcept {
return allocator_type(); }
579 MSTL_CONSTEXPR20
void reserve_exact(
const size_type n) {
580 MSTL_DEBUG_VERIFY(n < max_size(),
"basic_string reserve index out of range.");
581 if (capacity_pair_.value >= n)
return;
583 pointer new_buffer = capacity_pair_.get_base().allocate(n);
584 traits_type::move(new_buffer, data_, size_);
585 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
588 capacity_pair_.value = n;
592 MSTL_CONSTEXPR20
void reserve(
const size_type n) {
593 reserve_exact(n + 1);
596 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](
const size_type n)
noexcept {
597 MSTL_DEBUG_VERIFY(n <= size_,
"basic_string [] index out of range.");
598 return *(data() + n);
600 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference operator [](
const size_type n)
const noexcept {
601 MSTL_DEBUG_VERIFY(n <= size_,
"basic_string [] index out of range.");
602 return *(data() + n);
605 MSTL_NODISCARD MSTL_CONSTEXPR20 reference at(
const size_type n)
noexcept {
606 MSTL_DEBUG_VERIFY(n < size_,
"basic_string index out of ranges.");
609 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference at(
const size_type n)
const noexcept {
610 MSTL_DEBUG_VERIFY(n < size_,
"basic_string index out of ranges.");
614 MSTL_NODISCARD MSTL_CONSTEXPR20 reference front() noexcept {
615 MSTL_DEBUG_VERIFY(!empty(),
"front called on empty basic_string");
618 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference front() const noexcept {
619 MSTL_DEBUG_VERIFY(!empty(),
"front called on empty basic_string");
622 MSTL_NODISCARD MSTL_CONSTEXPR20 reference back() noexcept {
623 MSTL_DEBUG_VERIFY(!empty(),
"back called on empty basic_string");
624 return *(data() + size_ - 1);
626 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference back() const noexcept {
627 MSTL_DEBUG_VERIFY(!empty(),
"back called on empty basic_string");
628 return *(data() + size_ - 1);
631 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer data() noexcept {
return data_; }
632 MSTL_NODISCARD MSTL_CONSTEXPR20 const_pointer data() const noexcept {
return data_; }
633 MSTL_NODISCARD MSTL_CONSTEXPR20 const_pointer c_str() const noexcept {
return data_; }
635 MSTL_CONSTEXPR20 iterator insert(iterator position, value_type chr) {
636 if (size_ == capacity_pair_.value) {
637 return this->reallocate_and_fill(position, 1, chr);
640 size_type offset = position - begin();
641 pointer p = data_ + offset;
642 size_type chars_after = size_ - offset;
643 if (chars_after > 0) {
644 traits_type::move(p + 1, p, chars_after);
650 return iterator(p,
this);
653 MSTL_CONSTEXPR20 basic_string& insert(size_type position, size_type n, value_type chr) {
654 this->insert(begin() + position, n, chr);
658 MSTL_CONSTEXPR20 iterator insert(iterator position, size_type n, value_type chr) {
659 if (n == 0)
return position;
660 if (capacity_pair_.value - size_ < n) {
661 return this->reallocate_and_fill(position, n, chr);
664 const size_type offset = position - begin();
665 pointer p = data_ + offset;
666 const size_type chars_after = size_ - offset;
668 if (chars_after > 0) {
669 traits_type::move(p + n, p, chars_after);
671 traits_type::assign(p, n, chr);
675 return iterator(p,
this);
678 template <
typename Iterator>
679 MSTL_CONSTEXPR20 iterator insert(iterator position, Iterator first, Iterator last) {
681 if (len == 0)
return position;
682 if (capacity_pair_.value - size_ < len) {
683 return reallocate_and_copy(position, first, last);
686 const size_type offset = position - begin();
687 pointer p = data_ + offset;
688 const size_type chars_after = size_ - offset;
690 if (chars_after > 0) {
691 traits_type::move(p + len, p, chars_after);
694 for (Iterator it = first; it != last; ++it, ++curr) {
703 MSTL_CONSTEXPR20
void push_back(value_type chr) {
704 this->append(1, chr);
707 MSTL_CONSTEXPR20
void pop_back() noexcept {
708 MSTL_DEBUG_VERIFY(!empty(),
"pop_back called on empty basic_string");
713 MSTL_CONSTEXPR20 basic_string& append(size_type n, value_type chr) {
714 MSTL_DEBUG_VERIFY(size_ + n < max_size(),
"basic_string append iterator out of ranges.");
715 if (capacity_pair_.value - size_ <= n) reallocate(n);
716 traits_type::assign(data_ + size_, n, chr);
721 MSTL_CONSTEXPR20 basic_string& append(value_type chr) {
return this->append(1, chr); }
723 MSTL_CONSTEXPR20 basic_string& append(
const basic_string& str, size_type position, size_type n) {
724 MSTL_DEBUG_VERIFY(size_ + n < max_size(),
"basic_string append iterator out of ranges.");
725 if (n == 0)
return *
this;
727 if (capacity_pair_.value - size_ <= n) reallocate(n);
728 traits_type::copy(data_ + size_, str.data_ + position, n);
734 MSTL_CONSTEXPR20 basic_string& append(
const basic_string& str) {
735 return this->append(str, 0, str.size_);
737 MSTL_CONSTEXPR20 basic_string& append(
const basic_string& str, size_type position) {
738 return this->append(str, position, str.size_ - position);
741 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str, size_type position, size_type n) {
742 MSTL_DEBUG_VERIFY(size_ + n < max_size(),
"basic_string append iterator out of ranges.");
743 if (n == 0)
return *
this;
745 if (capacity_pair_.value - size_ <= n) reallocate(n);
746 traits_type::move(data_ + size_, str.data_ + position, n);
752 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str) {
753 const size_type len = str.size_;
754 return this->append(
_MSTL move(str), 0, len);
756 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str, size_type position) {
757 const size_type len = str.size_;
758 return this->append(
_MSTL move(str), position, len - position);
761 MSTL_CONSTEXPR20 basic_string& append(view_type str, size_type n) {
762 return this->append(str.data(), n);
764 MSTL_CONSTEXPR20 basic_string& append(view_type str) {
765 return this->append(str.data(), str.size());
768 MSTL_CONSTEXPR20 basic_string& append(const_pointer str, size_type n) {
769 MSTL_DEBUG_VERIFY(size_ + n < max_size(),
"basic_string append iterator out of ranges.");
770 if (capacity_pair_.value - size_ <= n) reallocate(n);
771 traits_type::copy(data_ + size_, str, n);
776 MSTL_CONSTEXPR20 basic_string& append(const_pointer str) {
777 return this->append(str, traits_type::length(str));
780 template <
typename Iterator, enable_if_t<is_iter_v<Iterator>,
int> = 0>
781 MSTL_CONSTEXPR20 basic_string& append(Iterator first, Iterator last) {
783 MSTL_DEBUG_VERIFY(size_ + n < max_size(),
"basic_string append iterator out of ranges.");
785 if (capacity_pair_.value - size_ <= n) reallocate(n);
792 MSTL_CONSTEXPR20 basic_string& append(std::initializer_list<value_type> l) {
793 return this->append(l.begin(), l.end());
796 MSTL_CONSTEXPR20 basic_string& assign(
const basic_string& str) {
return *
this = str; }
797 MSTL_CONSTEXPR20 basic_string& assign(basic_string&& str) {
return *
this =
_MSTL move(str); }
798 MSTL_CONSTEXPR20 basic_string& assign(const_pointer str) {
return *
this = str; }
800 MSTL_CONSTEXPR20 basic_string& assign(const_pointer str,
const size_type n) {
802 return this->append(str, n);
804 MSTL_CONSTEXPR20 basic_string& assign(
const size_type n, value_type chr) {
806 return this->append(n, chr);
808 template <
typename Iterator>
809 MSTL_CONSTEXPR20 basic_string& assign(Iterator first, Iterator last) {
811 return this->append(first, last);
814 MSTL_CONSTEXPR20 basic_string& assign(std::initializer_list<value_type> ilist) {
815 return *
this = ilist;
817 MSTL_CONSTEXPR20 basic_string& assign(
const view_type& view) {
821 MSTL_CONSTEXPR20 basic_string& operator +=(
const basic_string& str) {
return this->append(str); }
822 MSTL_CONSTEXPR20 basic_string& operator +=(basic_string&& str) {
return this->append(
_MSTL move(str)); }
823 MSTL_CONSTEXPR20 basic_string& operator +=(value_type chr) {
return this->append(chr); }
824 MSTL_CONSTEXPR20 basic_string& operator +=(const_pointer str) {
return this->append(str); }
825 MSTL_CONSTEXPR20 basic_string& operator +=(std::initializer_list<value_type> lls) {
return this->append(lls); }
826 MSTL_CONSTEXPR20 basic_string& operator +=(view_type view) {
return this->append(view); }
828 MSTL_CONSTEXPR20 iterator erase(iterator position)
noexcept {
829 MSTL_DEBUG_VERIFY(position != end(),
"erase: cannot erase end() iterator");
831 pointer p = &*position;
832 const size_type chars_after = end() - position - 1;
833 if (chars_after > 0) {
834 traits_type::move(p, p + 1, chars_after);
842 MSTL_CONSTEXPR20 basic_string& erase(size_type pos = 0, size_type len = npos)
noexcept {
843 if (pos >= size_)
return *
this;
844 if (len == npos || pos + len >= size_) {
847 this->erase(begin() + pos, len);
851 MSTL_CONSTEXPR20 iterator erase(iterator first,
const size_type n)
noexcept {
852 if (n == 0)
return first;
853 iterator last = first +
_MSTL min(n,
static_cast<size_type
>(end() - first));
854 return this->erase(first, last);
857 MSTL_CONSTEXPR20 iterator erase(iterator first, iterator last)
noexcept {
858 if (first == last)
return first;
860 const size_type erase_count = last - first;
861 const size_type chars_after = end() - last;
863 if (chars_after > 0) {
864 pointer p_first = data_ + (first - begin());
865 pointer p_last = data_ + (last - begin());
866 traits_type::move(p_first, p_last, chars_after);
869 size_ -= erase_count;
875 MSTL_CONSTEXPR20
void resize(size_type count, value_type chr) {
877 this->erase({data_ + count,
this}, {data_ + size_,
this});
879 this->append(count - size_, chr);
882 MSTL_CONSTEXPR20
void resize(
const size_type count) {
883 this->resize(count, value_type());
886 template <
typename Operation>
887 MSTL_CONSTEXPR20
void resize_and_overwrite(size_type count, Operation op) {
888 MSTL_DEBUG_VERIFY(count < max_size(),
"resize_and_overwrite: count too large");
889 if (count >= capacity_pair_.value) {
890 this->reserve(count + 1);
892 const size_type old_size = size_;
896 const size_type actual_size = op(data_, count);
897 if (actual_size > count) {
899 throw_exception(value_exception(
"resize_and_overwrite: operation returned invalid size"));
910 MSTL_CONSTEXPR20
void clear() noexcept {
915 MSTL_CONSTEXPR20
void shrink_to_fit() {
916 const size_type new_cap = size_ + 1;
917 if (new_cap >= capacity_pair_.value)
return;
920 temp.reserve(new_cap);
925 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string repeat(size_type n)
const noexcept {
927 result.reserve(size() * n);
928 while (n--) result += *
this;
932 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string substr(
const size_type off = 0, size_type count = npos)
const {
933 MSTL_DEBUG_VERIFY(off < size_,
"basic_string index out of ranges.");
934 count =
_MSTL min(count, size_ - off);
935 return basic_string(data() + off, count);
938 MSTL_NODISCARD MSTL_CONSTEXPR20 view_type view() const noexcept {
939 return view_type(data(), size());
942 MSTL_NODISCARD MSTL_CONSTEXPR20 view_type view(
const size_type off, size_type count = npos)
const noexcept {
943 MSTL_DEBUG_VERIFY(off < size_,
"basic_string index out of ranges.");
944 count =
_MSTL min(count, size_ - off);
945 return view_type(data() + off, count);
949 MSTL_CONSTEXPR20 size_type copy(pointer dest,
const size_type count, size_type position = 0)
const {
950 MSTL_DEBUG_VERIFY(position <= size_,
"basic_string copy position out of range");
951 const size_type len =
_MSTL min(count, size_ - position);
952 traits_type::copy(dest, data() + position, len);
957 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const basic_string& str)
const noexcept {
958 return this->compare(str.view());
960 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const size_type off,
const size_type n,
const basic_string& str)
const {
961 return view(off, n).compare(str);
963 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const size_type off,
const size_type n,
const basic_string& str,
964 const size_type roff,
const size_type count)
const {
965 return view(off, n).compare(str.view(roff, count));
967 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const CharT*
const str)
const noexcept {
968 return this->compare(view_type(str));
970 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const string_view& str)
const noexcept {
971 return _MSTL char_traits_compare<Traits>(data(), size_, str.data(), str.size());
973 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const size_type off,
const size_type n,
const CharT*
const str)
const {
974 return view(off, n).compare(view_type(str));
976 MSTL_NODISCARD MSTL_CONSTEXPR20
int compare(
const size_type off,
const size_type n,
977 const CharT*
const str,
const size_type count)
const {
978 return view(off, n).compare(view_type(str, count));
981 MSTL_CONSTEXPR20 basic_string& replace(
const size_type position,
const size_type n,
const basic_string& str) {
982 MSTL_DEBUG_VERIFY(position < size_,
"basic_string index out of ranges.");
983 return this->replace_copy(begin() + position, n, str.data(), str.size_);
985 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last,
const basic_string& str) {
986 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
"basic_string replace iterator out of ranges.");
987 return this->replace_copy(first, last - first, str.data(), str.size_);
989 MSTL_CONSTEXPR20 basic_string& replace(
const size_type position,
const size_type n, const_pointer str) {
990 MSTL_DEBUG_VERIFY(position < size_,
"basic_string index out of ranges.");
991 return this->replace_copy({data() + position,
this}, n, str, traits_type::length(str));
993 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str) {
994 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
"basic_string replace iterator out of ranges.");
995 return this->replace_copy(first, last - first, str, traits_type::length(str));
997 MSTL_CONSTEXPR20 basic_string& replace(
const size_type position,
const size_type n1, const_pointer str,
const size_type n2) {
998 MSTL_DEBUG_VERIFY(position < size_,
"basic_string index out of ranges.");
999 return this->replace_copy(data() + position, n1, str, n2);
1001 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str,
const size_type n) {
1002 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
"basic_string replace iterator out of ranges.");
1003 return this->replace_copy(first, last - first, str, n);
1005 MSTL_CONSTEXPR20 basic_string& replace(
const size_type position,
const size_type n1,
const size_type n2,
const value_type chr) {
1006 MSTL_DEBUG_VERIFY(position < size_,
"basic_string index out of ranges.");
1007 return this->replace_fill(data() + position, n1, n2, chr);
1009 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last,
const size_type n,
const value_type chr) {
1010 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
"basic_string replace iterator out of ranges.");
1011 return this->replace_fill(first,
static_cast<size_type
>(last - first), n, chr);
1013 MSTL_CONSTEXPR20 basic_string& replace(
const size_type position1,
const size_type n1,
const basic_string& str,
1014 const size_type position2,
const size_type n2 = npos) {
1015 MSTL_DEBUG_VERIFY(position1 < size_,
"basic_string index out of ranges.");
1016 MSTL_DEBUG_VERIFY(position2 < size_,
"basic_string index out of ranges.");
1017 return this->replace_copy(data() + position1, n1, str.data_ + position2, n2);
1019 template <
typename Iterator>
1020 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, Iterator first2, Iterator last2) {
1021 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
"basic_string replace iterator out of ranges.");
1022 return this->replace_copy(first, last, first2, last2);
1025 MSTL_CONSTEXPR20
void reverse() noexcept {
1026 if (size() < 2)
return;
1027 for (iterator first = begin(), last = end(); first < last; ) {
1032 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
const basic_string& str,
const size_type n = 0) const noexcept {
1033 return (char_traits_find<Traits>)(data(), size_, n, str.data(), str.size_);
1035 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
const CharT chr,
const size_type n = 0) const noexcept {
1036 return (char_traits_find_char<Traits>)(data(), size_, n, chr);
1038 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
const CharT*
const str,
1039 const size_type off,
const size_type count)
const noexcept {
1040 return (char_traits_find<Traits>)(data(), size_, off, str, count);
1042 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
const CharT*
const str,
const size_type off = 0) const noexcept {
1043 return (char_traits_find<Traits>)(data(), size_, off, str, Traits::length(str));
1045 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
1046 const string_view& str,
const size_type off,
const size_type count)
const noexcept {
1047 return (char_traits_find<Traits>)(data(), size_, off, str.data(), count);
1049 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
const string_view& str,
const size_type off = 0) const noexcept {
1050 return _MSTL char_traits_find<Traits>(data(), size_, off, str.data(), str.size());
1053 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
const basic_string& str,
const size_type off = npos)
const noexcept {
1054 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), str.size_);
1056 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
const CharT chr,
const size_type n = npos)
const noexcept {
1057 return (char_traits_rfind_char<Traits>)(data(), size_, n, chr);
1059 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
const CharT*
const str,
const size_type off,
1060 const size_type n)
const noexcept {
1061 return (char_traits_rfind<Traits>)(data(), size_, off, str, n);
1063 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
const CharT*
const str,
const size_type off = npos)
const noexcept {
1064 return (char_traits_rfind<Traits>)(data(), size_, off, str, Traits::length(str));
1066 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
1067 const string_view& str,
const size_type off,
const size_type count)
const noexcept {
1068 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), count);
1070 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
const string_view& str,
const size_type off = 0) const noexcept {
1071 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), str.size());
1074 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
const basic_string& str,
const size_type off = 0) const noexcept {
1075 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data_, str.size_);
1077 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
const CharT chr,
const size_type off = 0) const noexcept {
1078 return (char_traits_find_char<Traits>)(data(), size_, off, chr);
1080 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
const CharT*
const str,
const size_type off,
1081 const size_type n)
const noexcept {
1082 return (char_traits_find_first_of<Traits>)(data(), size_, off, str, n);
1084 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
const CharT*
const str,
const size_type off = 0) const noexcept {
1085 return (char_traits_find_first_of<Traits>)(data(), size_, off, str, Traits::length(str));
1087 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
1088 const string_view& str,
const size_type off,
const size_type n)
const noexcept {
1089 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data(), n);
1091 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
const string_view& str,
const size_type off = 0) const noexcept {
1092 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data(), str.size());
1095 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
const basic_string& str,
const size_type off = npos)
const noexcept {
1096 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), str.size_);
1098 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
const CharT chr,
const size_type off = npos)
const noexcept {
1099 return (char_traits_rfind_char<Traits>)(data(), size_, off, chr);
1101 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
const CharT*
const str,
const size_type off,
1102 const size_type n)
const noexcept {
1103 return (char_traits_find_last_of<Traits>)(data(), size_, off, str, n);
1105 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
const CharT*
const str,
const size_type off = npos)
const noexcept {
1106 return (char_traits_find_last_of<Traits>)(data(), size_, off, str, Traits::length(str));
1108 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
1109 const string_view& str,
const size_type off,
const size_type n)
const noexcept {
1110 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), n);
1112 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
const string_view& str,
const size_type off = npos)
const noexcept {
1113 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), str.size());
1116 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
const basic_string& str,
const size_type off = 0) const noexcept {
1117 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), str.size_);
1119 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
const CharT chr,
const size_type off = 0) const noexcept {
1120 return (char_traits_find_not_char<Traits>)(data(), size_, off, chr);
1122 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
const CharT*
const str,
const size_type off,
1123 const size_type n)
const noexcept {
1124 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str, n);
1126 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
const CharT*
const str,
const size_type off = 0) const noexcept {
1127 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str, Traits::length(str));
1129 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
1130 const string_view& str,
const size_type off,
const size_type n)
const noexcept {
1131 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), n);
1133 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
const string_view& str,
const size_type off = 0) const noexcept {
1134 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), str.size());
1137 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
const basic_string& str,
const size_type off = npos)
const noexcept {
1138 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data_, str.size_);
1140 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
const CharT chr,
const size_type off = npos)
const noexcept {
1141 return (char_traits_rfind_not_char<Traits>)(data(), size_, off, chr);
1143 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1144 const CharT*
const str,
const size_type off,
const size_type n)
const noexcept {
1145 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str, n);
1147 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
const CharT*
const str,
1148 const size_type off = npos)
const noexcept {
1149 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str, Traits::length(str));
1151 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1152 const string_view& str,
const size_type off,
const size_type n)
const noexcept {
1153 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data(), n);
1155 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1156 const string_view& str,
const size_type off = npos)
const noexcept {
1157 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data(), str.size());
1161 MSTL_CONSTEXPR20 size_type count(value_type chr,
const size_type position = 0) const noexcept {
1163 for (size_type idx = position; idx < size_; ++idx) {
1164 if (*(data() + idx) == chr) ++n;
1169 MSTL_NODISCARD MSTL_CONSTEXPR20
bool starts_with(view_type view)
const noexcept {
1170 return view.size() <= size_ && traits_type::compare(data(), view.data(), view.size()) == 0;
1172 MSTL_NODISCARD MSTL_CONSTEXPR20
bool starts_with(value_type chr)
const noexcept {
1173 return !empty() && traits_type::eq(front(), chr);
1175 MSTL_NODISCARD MSTL_CONSTEXPR20
bool starts_with(const_pointer str)
const noexcept {
1176 return this->starts_with(view_type(str));
1179 MSTL_NODISCARD MSTL_CONSTEXPR20
bool ends_with(view_type view)
const noexcept {
1180 const size_type view_size = view.size();
1181 return view_size <= size_ && traits_type::compare(data_ + size_ - view_size, view.data(), view_size) == 0;
1183 MSTL_NODISCARD MSTL_CONSTEXPR20
bool ends_with(value_type chr)
const noexcept {
1184 return !empty() && traits_type::eq(back(), chr);
1186 MSTL_NODISCARD MSTL_CONSTEXPR20
bool ends_with(const_pointer str)
const noexcept {
1187 return this->ends_with(view_type(str));
1190 MSTL_NODISCARD MSTL_CONSTEXPR20
bool contains(view_type view)
const noexcept {
1191 return this->find(view) != npos;
1193 MSTL_NODISCARD MSTL_CONSTEXPR20
bool contains(value_type chr)
const noexcept {
1194 return this->find(chr) != npos;
1196 MSTL_NODISCARD MSTL_CONSTEXPR20
bool contains(const_pointer str)
const noexcept {
1197 return this->find(str) != npos;
1201 MSTL_CONSTEXPR20 basic_string& trim_left() noexcept {
1202 return this->trim_left_if([](value_type ch) {
return _MSTL is_space(ch); });
1204 MSTL_CONSTEXPR20 basic_string& trim_right() noexcept {
1205 return this->trim_right_if([](value_type ch) {
return _MSTL is_space(ch); });
1207 MSTL_CONSTEXPR20 basic_string& trim() noexcept {
return this->trim_left().trim_right(); }
1209 template <
typename Predicate>
1210 MSTL_CONSTEXPR20 basic_string& trim_left_if(Predicate pred)
1211 noexcept(
noexcept(pred(*cbegin()))) {
1212 if (empty())
return *
this;
1214 const_iterator it = cbegin();
1215 while (it != cend() && pred(*it))
1219 this->erase(begin(), it - begin());
1224 template <
typename Predicate>
1225 MSTL_CONSTEXPR20 basic_string& trim_right_if(Predicate pred)
1226 noexcept(
noexcept(pred(*crbegin()))) {
1227 if (empty())
return *
this;
1229 const_reverse_iterator rit = crbegin();
1230 while (rit != crend() && pred(*rit))
1233 if (rit != crbegin())
1234 this->erase(end() - (rit - crbegin()), end());
1239 template <
typename Predicate>
1240 MSTL_CONSTEXPR20 basic_string& trim_if(Predicate pred)
1241 noexcept(
noexcept(this->trim_right_if(pred)) &&
noexcept(this->trim_left_if(pred))) {
1242 return this->trim_left_if(pred).trim_right_if(pred);
1245 MSTL_CONSTEXPR20
bool equal_to(
const basic_string& str)
const noexcept {
1246 return this->equal_to(str.view());
1248 MSTL_CONSTEXPR20
bool equal_to(
const view_type str)
const noexcept {
1249 return _MSTL char_traits_equal<Traits>(data(), size_, str.data(), str.size());
1251 MSTL_CONSTEXPR20
bool equal_to(
const CharT* str)
const noexcept {
1252 return this->equal_to(view_type(str));
1255 MSTL_CONSTEXPR20
bool iequal_to(
const basic_string& str)
const noexcept {
1256 return this->iequal_to(str.view());
1258 MSTL_CONSTEXPR20
bool iequal_to(
const view_type str)
const noexcept {
1259 return _MSTL char_traits_equal<Traits>(data(), size_, str.data(), str.size());
1261 MSTL_CONSTEXPR20
bool iequal_to(
const CharT* str)
const noexcept {
1262 return this->iequal_to(view_type(str));
1265 MSTL_CONSTEXPR20
void lowercase()
1269 MSTL_CONSTEXPR20
void uppercase()
1274 MSTL_CONSTEXPR20
void swap(basic_string& x)
noexcept {
1278 _MSTL swap(capacity_pair_, x.capacity_pair_);
1281 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
const basic_string& rhs)
const noexcept {
return this->equal_to(rhs); }
1282 MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
const basic_string& rhs)
const noexcept {
return this->compare(rhs) < 0; }
1284 MSTL_NODISCARD MSTL_CONSTEXPR20
size_t to_hash() const noexcept {
1285 return _INNER FNV_hash_string(this->data(), this->length());
1288#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
1289template <
typename Iterator,
typename Alloc = allocator<iter_value_t<Iterator>>>
1290basic_string(Iterator, Iterator, Alloc = Alloc())
1291-> basic_string<iter_value_t<Iterator>, char_traits<iter_value_t<Iterator>>, Alloc>;
1293template <
typename CharT,
typename Traits,
typename Alloc = allocator<CharT>>
1294explicit basic_string(basic_string_view<CharT, Traits>,
const Alloc & = Alloc())
1295-> basic_string<CharT, Traits, Alloc>;
1297template <
typename CharT,
typename Traits,
typename Alloc = allocator<CharT>>
1298basic_string(basic_string_view<CharT, Traits>,
1301 const Alloc & = Alloc())
1302-> basic_string<CharT, Traits, Alloc>;
1305template <
typename CharT,
typename Traits,
typename Alloc>
1306MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1307 const basic_string<CharT, Traits, Alloc>& lhs,
const basic_string<CharT, Traits, Alloc>& rhs) {
1308 basic_string<CharT, Traits, Alloc> tmp(lhs);
1313template <
typename CharT,
typename Traits,
typename Alloc>
1314MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1315 const CharT* lhs,
const basic_string<CharT, Traits, Alloc>& rhs) {
1316 basic_string<CharT, Traits, Alloc> tmp(lhs);
1320template <
typename CharT,
typename Traits,
typename Alloc>
1321MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1322 const basic_string<CharT, Traits, Alloc>& lhs,
const CharT* rhs) {
1323 basic_string<CharT, Traits, Alloc> tmp(lhs);
1328template <
typename CharT,
typename Traits,
typename Alloc>
1329MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1330 const string_view& lhs,
const basic_string<CharT, Traits, Alloc>& rhs) {
1331 basic_string<CharT, Traits, Alloc> tmp(lhs);
1335template <
typename CharT,
typename Traits,
typename Alloc>
1336MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1337 const basic_string<CharT, Traits, Alloc>& lhs,
const string_view& rhs) {
1338 basic_string<CharT, Traits, Alloc> tmp(lhs);
1343template <
typename CharT,
typename Traits,
typename Alloc>
1344MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1345 CharT lhs,
const basic_string<CharT, Traits, Alloc>& rhs) {
1346 basic_string<CharT, Traits, Alloc> tmp(1, lhs);
1350template <
typename CharT,
typename Traits,
typename Alloc>
1351MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1352 const basic_string<CharT, Traits, Alloc>& lhs, CharT rhs) {
1353 basic_string<CharT, Traits, Alloc> tmp(lhs);
1358template <
typename CharT,
typename Traits,
typename Alloc>
1359MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1360 basic_string<CharT, Traits, Alloc>&& lhs,
const basic_string<CharT, Traits, Alloc>& rhs) {
1363template <
typename CharT,
typename Traits,
typename Alloc>
1364MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1365 const basic_string<CharT, Traits, Alloc>& lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1366 basic_string<CharT, Traits, Alloc> tmp(lhs);
1371template <
typename CharT,
typename Traits,
typename Alloc>
1372MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1373 basic_string<CharT, Traits, Alloc>&& lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1374 basic_string<CharT, Traits, Alloc> tmp(
_MSTL move(lhs));
1383template <
typename CharT,
typename Traits,
typename Alloc>
1384MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1385 const CharT* lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1386 basic_string<CharT, Traits, Alloc> tmp(lhs);
1390template <
typename CharT,
typename Traits,
typename Alloc>
1391MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1392 basic_string<CharT, Traits, Alloc>&& lhs,
const CharT* rhs) {
1396template <
typename CharT,
typename Traits,
typename Alloc>
1397MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1398 CharT lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1399 basic_string<CharT, Traits, Alloc> tmp(1, lhs);
1403template <
typename CharT,
typename Traits,
typename Alloc>
1404MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1405 basic_string<CharT, Traits, Alloc>&& lhs, CharT rhs) {
1409template <
typename CharT,
typename Traits,
typename Alloc>
1410MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
1411 const CharT*
const lhs,
1412 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1413 return rhs.equal_to(lhs);
1415template <
typename CharT,
typename Traits,
typename Alloc>
1416MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
1417 const basic_string<CharT, Traits, Alloc>& lhs,
1418 const CharT*
const rhs)
noexcept {
1419 return lhs.equal_to(rhs);
1421template <
typename CharT,
typename Traits,
typename Alloc>
1422MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
1423 const basic_string_view<CharT, Traits>& lhs,
1424 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1425 return rhs.equal_to(lhs);
1427template <
typename CharT,
typename Traits,
typename Alloc>
1428MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator ==(
1429 const basic_string<CharT, Traits, Alloc>& lhs,
1430 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1431 return lhs.equal_to(rhs);
1434template <
typename CharT,
typename Traits,
typename Alloc>
1435MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator !=(
1436 const CharT*
const lhs,
1437 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1438 return !(lhs == rhs);
1440template <
typename CharT,
typename Traits,
typename Alloc>
1441MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator !=(
1442 const basic_string<CharT, Traits, Alloc>& lhs,
1443 const CharT*
const rhs)
noexcept {
1444 return !(lhs == rhs);
1446template <
typename CharT,
typename Traits,
typename Alloc>
1447MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator !=(
1448 const basic_string_view<CharT, Traits>& lhs,
1449 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1450 return !(lhs == rhs);
1452template <
typename CharT,
typename Traits,
typename Alloc>
1453MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator !=(
1454 const basic_string<CharT, Traits, Alloc>& lhs,
1455 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1456 return !(lhs == rhs);
1459template <
typename CharT,
typename Traits,
typename Alloc>
1460MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
1461 const CharT*
const lhs,
1462 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1463 return 0 < rhs.compare(lhs);
1465template <
typename CharT,
typename Traits,
typename Alloc>
1466MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
1467 const basic_string<CharT, Traits, Alloc>& lhs,
1468 const CharT*
const rhs)
noexcept {
1469 return lhs.compare(rhs) < 0;
1471template <
typename CharT,
typename Traits,
typename Alloc>
1472MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
1473 const basic_string_view<CharT, Traits>& lhs,
1474 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1475 return 0 < rhs.compare(lhs);
1477template <
typename CharT,
typename Traits,
typename Alloc>
1478MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <(
1479 const basic_string<CharT, Traits, Alloc>& lhs,
1480 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1481 return lhs.compare(rhs) < 0;
1484template <
typename CharT,
typename Traits,
typename Alloc>
1485MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >(
1486 const CharT*
const lhs,
1487 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1490template <
typename CharT,
typename Traits,
typename Alloc>
1491MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >(
1492 const basic_string<CharT, Traits, Alloc>& lhs,
1493 const CharT*
const rhs)
noexcept {
1496template <
typename CharT,
typename Traits,
typename Alloc>
1497MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >(
1498 const basic_string_view<CharT, Traits>& lhs,
1499 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1502template <
typename CharT,
typename Traits,
typename Alloc>
1503MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >(
1504 const basic_string<CharT, Traits, Alloc>& lhs,
1505 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1509template <
typename CharT,
typename Traits,
typename Alloc>
1510MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <=(
1511 const CharT*
const lhs,
1512 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1513 return !(lhs > rhs);
1515template <
typename CharT,
typename Traits,
typename Alloc>
1516MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <=(
1517 const basic_string<CharT, Traits, Alloc>& lhs,
1518 const CharT*
const rhs)
noexcept {
1519 return !(lhs > rhs);
1521template <
typename CharT,
typename Traits,
typename Alloc>
1522MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <=(
1523 const basic_string_view<CharT, Traits>& lhs,
1524 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1525 return !(lhs > rhs);
1527template <
typename CharT,
typename Traits,
typename Alloc>
1528MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator <=(
1529 const basic_string<CharT, Traits, Alloc>& lhs,
1530 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1531 return !(lhs > rhs);
1534template <
typename CharT,
typename Traits,
typename Alloc>
1535MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >=(
1536 const CharT*
const lhs,
1537 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1538 return !(rhs < lhs);
1540template <
typename CharT,
typename Traits,
typename Alloc>
1541MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >=(
1542 const basic_string<CharT, Traits, Alloc>& lhs,
1543 const CharT*
const rhs)
noexcept {
1544 return !(rhs < lhs);
1546template <
typename CharT,
typename Traits,
typename Alloc>
1547MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >=(
1548 const basic_string_view<CharT, Traits>& lhs,
1549 const basic_string<CharT, Traits, Alloc>& rhs)
noexcept {
1550 return !(rhs < lhs);
1552template <
typename CharT,
typename Traits,
typename Alloc>
1553MSTL_NODISCARD MSTL_CONSTEXPR20
bool operator >=(
1554 const basic_string<CharT, Traits, Alloc>& lhs,
1555 const basic_string_view<CharT, Traits>& rhs)
noexcept {
1556 return !(rhs < lhs);
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 CharT to_uppercase(const CharT c) noexcept
将字符转换为大写
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 CharT to_lowercase(const CharT c) noexcept
将字符转换为小写
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 bool is_space(const CharT c) noexcept
检查字符是否为空白字符
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
constexpr const T & min(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(b, a)))
返回两个值中的较小者
MSTL_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
#define _MSTL
全局命名空间MSTL前缀
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
constexpr void iter_swap(Iterator1 a, Iterator2 b) noexcept(noexcept(_MSTL swap(*a, *b)))
交换迭代器指向的元素
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
constexpr Iterator2 transform(Iterator1 first, Iterator1 last, Iterator2 result, UnaryOperation op) noexcept(noexcept(++first) &&noexcept(++result) &&noexcept(*result=op(*first)))
对范围元素应用一元变换
void swap()=delete
删除无参数的swap重载
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL_CONSTEXPR20 pair< Iterator1, Iterator2 > uninitialized_copy_n(Iterator1 first, size_t count, Iterator2 result)
复制指定数量的元素到未初始化内存
MSTL_CONSTEXPR20 Iterator2 uninitialized_copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制元素到未初始化内存
typename real_size< Alloc, difference_type >::type size_type
大小类型
MSTL_NODISCARD constexpr size_t to_hash() const noexcept(noexcept(derived().to_hash()))
获取对象的哈希值