1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_STRING 11#define _LIBCPP_STRING 12 13// clang-format off 14 15/* 16 string synopsis 17 18#include <compare> 19#include <initializer_list> 20 21namespace std 22{ 23 24template <class stateT> 25class fpos 26{ 27private: 28 stateT st; 29public: 30 fpos(streamoff = streamoff()); 31 32 operator streamoff() const; 33 34 stateT state() const; 35 void state(stateT); 36 37 fpos& operator+=(streamoff); 38 fpos operator+ (streamoff) const; 39 fpos& operator-=(streamoff); 40 fpos operator- (streamoff) const; 41}; 42 43template <class stateT> streamoff operator-(const fpos<stateT>& x, const fpos<stateT>& y); 44 45template <class stateT> bool operator==(const fpos<stateT>& x, const fpos<stateT>& y); 46template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT>& y); 47 48template <class charT> 49struct char_traits 50{ 51 using char_type = charT; 52 using int_type = ...; 53 using off_type = streamoff; 54 using pos_type = streampos; 55 using state_type = mbstate_t; 56 using comparison_category = strong_ordering; // Since C++20 only for the specializations 57 // char, wchar_t, char8_t, char16_t, and char32_t. 58 59 static void assign(char_type& c1, const char_type& c2) noexcept; 60 static constexpr bool eq(char_type c1, char_type c2) noexcept; 61 static constexpr bool lt(char_type c1, char_type c2) noexcept; 62 63 static int compare(const char_type* s1, const char_type* s2, size_t n); 64 static size_t length(const char_type* s); 65 static const char_type* find(const char_type* s, size_t n, const char_type& a); 66 static char_type* move(char_type* s1, const char_type* s2, size_t n); 67 static char_type* copy(char_type* s1, const char_type* s2, size_t n); 68 static char_type* assign(char_type* s, size_t n, char_type a); 69 70 static constexpr int_type not_eof(int_type c) noexcept; 71 static constexpr char_type to_char_type(int_type c) noexcept; 72 static constexpr int_type to_int_type(char_type c) noexcept; 73 static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; 74 static constexpr int_type eof() noexcept; 75}; 76 77template <> struct char_traits<char>; 78template <> struct char_traits<wchar_t>; 79template <> struct char_traits<char8_t>; // C++20 80template <> struct char_traits<char16_t>; 81template <> struct char_traits<char32_t>; 82 83template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > 84class basic_string 85{ 86public: 87// types: 88 typedef traits traits_type; 89 typedef typename traits_type::char_type value_type; 90 typedef Allocator allocator_type; 91 typedef typename allocator_type::size_type size_type; 92 typedef typename allocator_type::difference_type difference_type; 93 typedef typename allocator_type::reference reference; 94 typedef typename allocator_type::const_reference const_reference; 95 typedef typename allocator_type::pointer pointer; 96 typedef typename allocator_type::const_pointer const_pointer; 97 typedef implementation-defined iterator; 98 typedef implementation-defined const_iterator; 99 typedef std::reverse_iterator<iterator> reverse_iterator; 100 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 101 102 static const size_type npos = -1; 103 104 basic_string() 105 noexcept(is_nothrow_default_constructible<allocator_type>::value); // constexpr since C++20 106 explicit basic_string(const allocator_type& a); // constexpr since C++20 107 basic_string(const basic_string& str); // constexpr since C++20 108 basic_string(basic_string&& str) 109 noexcept(is_nothrow_move_constructible<allocator_type>::value); // constexpr since C++20 110 basic_string(const basic_string& str, size_type pos, 111 const allocator_type& a = allocator_type()); // constexpr since C++20 112 basic_string(const basic_string& str, size_type pos, size_type n, 113 const Allocator& a = Allocator()); // constexpr since C++20 114 constexpr basic_string( 115 basic_string&& str, size_type pos, const Allocator& a = Allocator()); // since C++23 116 constexpr basic_string( 117 basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); // since C++23 118 template<class T> 119 basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20 120 template <class T> 121 explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17, constexpr since C++20 122 basic_string(const value_type* s, const allocator_type& a = allocator_type()); // constexpr since C++20 123 basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20 124 basic_string(nullptr_t) = delete; // C++23 125 basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); // constexpr since C++20 126 template<class InputIterator> 127 basic_string(InputIterator begin, InputIterator end, 128 const allocator_type& a = allocator_type()); // constexpr since C++20 129 template<container-compatible-range<charT> R> 130 constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); // since C++23 131 basic_string(initializer_list<value_type>, const Allocator& = Allocator()); // constexpr since C++20 132 basic_string(const basic_string&, const Allocator&); // constexpr since C++20 133 basic_string(basic_string&&, const Allocator&); // constexpr since C++20 134 135 ~basic_string(); // constexpr since C++20 136 137 operator basic_string_view<charT, traits>() const noexcept; // constexpr since C++20 138 139 basic_string& operator=(const basic_string& str); // constexpr since C++20 140 template <class T> 141 basic_string& operator=(const T& t); // C++17, constexpr since C++20 142 basic_string& operator=(basic_string&& str) 143 noexcept( 144 allocator_type::propagate_on_container_move_assignment::value || 145 allocator_type::is_always_equal::value ); // C++17, constexpr since C++20 146 basic_string& operator=(const value_type* s); // constexpr since C++20 147 basic_string& operator=(nullptr_t) = delete; // C++23 148 basic_string& operator=(value_type c); // constexpr since C++20 149 basic_string& operator=(initializer_list<value_type>); // constexpr since C++20 150 151 iterator begin() noexcept; // constexpr since C++20 152 const_iterator begin() const noexcept; // constexpr since C++20 153 iterator end() noexcept; // constexpr since C++20 154 const_iterator end() const noexcept; // constexpr since C++20 155 156 reverse_iterator rbegin() noexcept; // constexpr since C++20 157 const_reverse_iterator rbegin() const noexcept; // constexpr since C++20 158 reverse_iterator rend() noexcept; // constexpr since C++20 159 const_reverse_iterator rend() const noexcept; // constexpr since C++20 160 161 const_iterator cbegin() const noexcept; // constexpr since C++20 162 const_iterator cend() const noexcept; // constexpr since C++20 163 const_reverse_iterator crbegin() const noexcept; // constexpr since C++20 164 const_reverse_iterator crend() const noexcept; // constexpr since C++20 165 166 size_type size() const noexcept; // constexpr since C++20 167 size_type length() const noexcept; // constexpr since C++20 168 size_type max_size() const noexcept; // constexpr since C++20 169 size_type capacity() const noexcept; // constexpr since C++20 170 171 void resize(size_type n, value_type c); // constexpr since C++20 172 void resize(size_type n); // constexpr since C++20 173 174 template<class Operation> 175 constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23 176 177 void reserve(size_type res_arg); // constexpr since C++20 178 void reserve(); // deprecated in C++20, removed in C++26 179 void shrink_to_fit(); // constexpr since C++20 180 void clear() noexcept; // constexpr since C++20 181 bool empty() const noexcept; // constexpr since C++20 182 183 const_reference operator[](size_type pos) const; // constexpr since C++20 184 reference operator[](size_type pos); // constexpr since C++20 185 186 const_reference at(size_type n) const; // constexpr since C++20 187 reference at(size_type n); // constexpr since C++20 188 189 basic_string& operator+=(const basic_string& str); // constexpr since C++20 190 template <class T> 191 basic_string& operator+=(const T& t); // C++17, constexpr since C++20 192 basic_string& operator+=(const value_type* s); // constexpr since C++20 193 basic_string& operator+=(value_type c); // constexpr since C++20 194 basic_string& operator+=(initializer_list<value_type>); // constexpr since C++20 195 196 basic_string& append(const basic_string& str); // constexpr since C++20 197 template <class T> 198 basic_string& append(const T& t); // C++17, constexpr since C++20 199 basic_string& append(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 200 template <class T> 201 basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 202 basic_string& append(const value_type* s, size_type n); // constexpr since C++20 203 basic_string& append(const value_type* s); // constexpr since C++20 204 basic_string& append(size_type n, value_type c); // constexpr since C++20 205 template<class InputIterator> 206 basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20 207 template<container-compatible-range<charT> R> 208 constexpr basic_string& append_range(R&& rg); // C++23 209 basic_string& append(initializer_list<value_type>); // constexpr since C++20 210 211 void push_back(value_type c); // constexpr since C++20 212 void pop_back(); // constexpr since C++20 213 reference front(); // constexpr since C++20 214 const_reference front() const; // constexpr since C++20 215 reference back(); // constexpr since C++20 216 const_reference back() const; // constexpr since C++20 217 218 basic_string& assign(const basic_string& str); // constexpr since C++20 219 template <class T> 220 basic_string& assign(const T& t); // C++17, constexpr since C++20 221 basic_string& assign(basic_string&& str); // constexpr since C++20 222 basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 223 template <class T> 224 basic_string& assign(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 225 basic_string& assign(const value_type* s, size_type n); // constexpr since C++20 226 basic_string& assign(const value_type* s); // constexpr since C++20 227 basic_string& assign(size_type n, value_type c); // constexpr since C++20 228 template<class InputIterator> 229 basic_string& assign(InputIterator first, InputIterator last); // constexpr since C++20 230 template<container-compatible-range<charT> R> 231 constexpr basic_string& assign_range(R&& rg); // C++23 232 basic_string& assign(initializer_list<value_type>); // constexpr since C++20 233 234 basic_string& insert(size_type pos1, const basic_string& str); // constexpr since C++20 235 template <class T> 236 basic_string& insert(size_type pos1, const T& t); // constexpr since C++20 237 basic_string& insert(size_type pos1, const basic_string& str, 238 size_type pos2, size_type n); // constexpr since C++20 239 template <class T> 240 basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20 241 basic_string& insert(size_type pos, const value_type* s, size_type n=npos); // C++14, constexpr since C++20 242 basic_string& insert(size_type pos, const value_type* s); // constexpr since C++20 243 basic_string& insert(size_type pos, size_type n, value_type c); // constexpr since C++20 244 iterator insert(const_iterator p, value_type c); // constexpr since C++20 245 iterator insert(const_iterator p, size_type n, value_type c); // constexpr since C++20 246 template<class InputIterator> 247 iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20 248 template<container-compatible-range<charT> R> 249 constexpr iterator insert_range(const_iterator p, R&& rg); // C++23 250 iterator insert(const_iterator p, initializer_list<value_type>); // constexpr since C++20 251 252 basic_string& erase(size_type pos = 0, size_type n = npos); // constexpr since C++20 253 iterator erase(const_iterator position); // constexpr since C++20 254 iterator erase(const_iterator first, const_iterator last); // constexpr since C++20 255 256 basic_string& replace(size_type pos1, size_type n1, const basic_string& str); // constexpr since C++20 257 template <class T> 258 basic_string& replace(size_type pos1, size_type n1, const T& t); // C++17, constexpr since C++20 259 basic_string& replace(size_type pos1, size_type n1, const basic_string& str, 260 size_type pos2, size_type n2=npos); // C++14, constexpr since C++20 261 template <class T> 262 basic_string& replace(size_type pos1, size_type n1, const T& t, 263 size_type pos2, size_type n); // C++17, constexpr since C++20 264 basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2); // constexpr since C++20 265 basic_string& replace(size_type pos, size_type n1, const value_type* s); // constexpr since C++20 266 basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); // constexpr since C++20 267 basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); // constexpr since C++20 268 template <class T> 269 basic_string& replace(const_iterator i1, const_iterator i2, const T& t); // C++17, constexpr since C++20 270 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20 271 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s); // constexpr since C++20 272 basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); // constexpr since C++20 273 template<class InputIterator> 274 basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20 275 template<container-compatible-range<charT> R> 276 constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23 277 basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>); // constexpr since C++20 278 279 size_type copy(value_type* s, size_type n, size_type pos = 0) const; // constexpr since C++20 280 basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr in C++20, removed in C++23 281 basic_string substr(size_type pos = 0, size_type n = npos) const&; // since C++23 282 constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; // since C++23 283 void swap(basic_string& str) 284 noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || 285 allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20 286 287 const value_type* c_str() const noexcept; // constexpr since C++20 288 const value_type* data() const noexcept; // constexpr since C++20 289 value_type* data() noexcept; // C++17, constexpr since C++20 290 291 allocator_type get_allocator() const noexcept; // constexpr since C++20 292 293 size_type find(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 294 template <class T> 295 size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 296 size_type find(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 297 size_type find(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 298 size_type find(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 299 300 size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 301 template <class T> 302 size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 303 size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 304 size_type rfind(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 305 size_type rfind(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 306 307 size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 308 template <class T> 309 size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 310 size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 311 size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 312 size_type find_first_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 313 314 size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 315 template <class T> 316 size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension, constexpr since C++20 317 size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 318 size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 319 size_type find_last_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 320 321 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 322 template <class T> 323 size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 324 size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 325 size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 326 size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 327 328 size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 329 template <class T> 330 size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 331 size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 332 size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 333 size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 334 335 int compare(const basic_string& str) const noexcept; // constexpr since C++20 336 template <class T> 337 int compare(const T& t) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 338 int compare(size_type pos1, size_type n1, const basic_string& str) const; // constexpr since C++20 339 template <class T> 340 int compare(size_type pos1, size_type n1, const T& t) const; // C++17, constexpr since C++20 341 int compare(size_type pos1, size_type n1, const basic_string& str, 342 size_type pos2, size_type n2=npos) const; // C++14, constexpr since C++20 343 template <class T> 344 int compare(size_type pos1, size_type n1, const T& t, 345 size_type pos2, size_type n2=npos) const; // C++17, constexpr since C++20 346 int compare(const value_type* s) const noexcept; // constexpr since C++20 347 int compare(size_type pos1, size_type n1, const value_type* s) const; // constexpr since C++20 348 int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const; // constexpr since C++20 349 350 constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 351 constexpr bool starts_with(charT c) const noexcept; // C++20 352 constexpr bool starts_with(const charT* s) const; // C++20 353 constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 354 constexpr bool ends_with(charT c) const noexcept; // C++20 355 constexpr bool ends_with(const charT* s) const; // C++20 356 357 constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++23 358 constexpr bool contains(charT c) const noexcept; // C++23 359 constexpr bool contains(const charT* s) const; // C++23 360}; 361 362template<class InputIterator, 363 class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> 364basic_string(InputIterator, InputIterator, Allocator = Allocator()) 365 -> basic_string<typename iterator_traits<InputIterator>::value_type, 366 char_traits<typename iterator_traits<InputIterator>::value_type>, 367 Allocator>; // C++17 368 369template<ranges::input_range R, 370 class Allocator = allocator<ranges::range_value_t<R>>> 371 basic_string(from_range_t, R&&, Allocator = Allocator()) 372 -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>, 373 Allocator>; // C++23 374 375template<class charT, 376 class traits, 377 class Allocator = allocator<charT>> 378 explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) 379 -> basic_string<charT, traits, Allocator>; // C++17 380 381template<class charT, 382 class traits, 383 class Allocator = allocator<charT>> 384 basic_string(basic_string_view<charT, traits>, 385 typename see below::size_type, typename see below::size_type, 386 const Allocator& = Allocator()) 387 -> basic_string<charT, traits, Allocator>; // C++17 388 389template<class charT, class traits, class Allocator> 390basic_string<charT, traits, Allocator> 391operator+(const basic_string<charT, traits, Allocator>& lhs, 392 const basic_string<charT, traits, Allocator>& rhs); // constexpr since C++20 393 394template<class charT, class traits, class Allocator> 395basic_string<charT, traits, Allocator> 396operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs); // constexpr since C++20 397 398template<class charT, class traits, class Allocator> 399basic_string<charT, traits, Allocator> 400operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs); // constexpr since C++20 401 402template<class charT, class traits, class Allocator> 403basic_string<charT, traits, Allocator> 404operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); // constexpr since C++20 405 406template<class charT, class traits, class Allocator> 407basic_string<charT, traits, Allocator> 408operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); // constexpr since C++20 409 410template<class charT, class traits, class Allocator> 411bool operator==(const basic_string<charT, traits, Allocator>& lhs, 412 const basic_string<charT, traits, Allocator>& rhs) noexcept; // constexpr since C++20 413 414template<class charT, class traits, class Allocator> 415bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 416 417template<class charT, class traits, class Allocator> 418bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept; // constexpr since C++20 419 420template<class charT, class traits, class Allocator> 421bool operator!=(const basic_string<charT,traits,Allocator>& lhs, 422 const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 423 424template<class charT, class traits, class Allocator> 425bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 426 427template<class charT, class traits, class Allocator> 428bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 429 430template<class charT, class traits, class Allocator> 431bool operator< (const basic_string<charT, traits, Allocator>& lhs, 432 const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 433 434template<class charT, class traits, class Allocator> 435bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 436 437template<class charT, class traits, class Allocator> 438bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 439 440template<class charT, class traits, class Allocator> 441bool operator> (const basic_string<charT, traits, Allocator>& lhs, 442 const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 443 444template<class charT, class traits, class Allocator> 445bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 446 447template<class charT, class traits, class Allocator> 448bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 449 450template<class charT, class traits, class Allocator> 451bool operator<=(const basic_string<charT, traits, Allocator>& lhs, 452 const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 453 454template<class charT, class traits, class Allocator> 455bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 456 457template<class charT, class traits, class Allocator> 458bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 459 460template<class charT, class traits, class Allocator> 461bool operator>=(const basic_string<charT, traits, Allocator>& lhs, 462 const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 463 464template<class charT, class traits, class Allocator> 465bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 466 467template<class charT, class traits, class Allocator> 468bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 469 470template<class charT, class traits, class Allocator> // since C++20 471constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, 472 const basic_string<charT, traits, Allocator>& rhs) noexcept; 473 474template<class charT, class traits, class Allocator> // since C++20 475constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, 476 const charT* rhs) noexcept; 477 478template<class charT, class traits, class Allocator> 479void swap(basic_string<charT, traits, Allocator>& lhs, 480 basic_string<charT, traits, Allocator>& rhs) 481 noexcept(noexcept(lhs.swap(rhs))); // constexpr since C++20 482 483template<class charT, class traits, class Allocator> 484basic_istream<charT, traits>& 485operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); 486 487template<class charT, class traits, class Allocator> 488basic_ostream<charT, traits>& 489operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str); 490 491template<class charT, class traits, class Allocator> 492basic_istream<charT, traits>& 493getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, 494 charT delim); 495 496template<class charT, class traits, class Allocator> 497basic_istream<charT, traits>& 498getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); 499 500template<class charT, class traits, class Allocator, class U> 501typename basic_string<charT, traits, Allocator>::size_type 502erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20 503template<class charT, class traits, class Allocator, class Predicate> 504typename basic_string<charT, traits, Allocator>::size_type 505erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 506 507typedef basic_string<char> string; 508typedef basic_string<wchar_t> wstring; 509typedef basic_string<char8_t> u8string; // C++20 510typedef basic_string<char16_t> u16string; 511typedef basic_string<char32_t> u32string; 512 513int stoi (const string& str, size_t* idx = nullptr, int base = 10); 514long stol (const string& str, size_t* idx = nullptr, int base = 10); 515unsigned long stoul (const string& str, size_t* idx = nullptr, int base = 10); 516long long stoll (const string& str, size_t* idx = nullptr, int base = 10); 517unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); 518 519float stof (const string& str, size_t* idx = nullptr); 520double stod (const string& str, size_t* idx = nullptr); 521long double stold(const string& str, size_t* idx = nullptr); 522 523string to_string(int val); 524string to_string(unsigned val); 525string to_string(long val); 526string to_string(unsigned long val); 527string to_string(long long val); 528string to_string(unsigned long long val); 529string to_string(float val); 530string to_string(double val); 531string to_string(long double val); 532 533int stoi (const wstring& str, size_t* idx = nullptr, int base = 10); 534long stol (const wstring& str, size_t* idx = nullptr, int base = 10); 535unsigned long stoul (const wstring& str, size_t* idx = nullptr, int base = 10); 536long long stoll (const wstring& str, size_t* idx = nullptr, int base = 10); 537unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); 538 539float stof (const wstring& str, size_t* idx = nullptr); 540double stod (const wstring& str, size_t* idx = nullptr); 541long double stold(const wstring& str, size_t* idx = nullptr); 542 543wstring to_wstring(int val); 544wstring to_wstring(unsigned val); 545wstring to_wstring(long val); 546wstring to_wstring(unsigned long val); 547wstring to_wstring(long long val); 548wstring to_wstring(unsigned long long val); 549wstring to_wstring(float val); 550wstring to_wstring(double val); 551wstring to_wstring(long double val); 552 553template <> struct hash<string>; 554template <> struct hash<u8string>; // C++20 555template <> struct hash<u16string>; 556template <> struct hash<u32string>; 557template <> struct hash<wstring>; 558 559basic_string<char> operator""s( const char *str, size_t len ); // C++14, constexpr since C++20 560basic_string<wchar_t> operator""s( const wchar_t *str, size_t len ); // C++14, constexpr since C++20 561constexpr basic_string<char8_t> operator""s( const char8_t *str, size_t len ); // C++20 562basic_string<char16_t> operator""s( const char16_t *str, size_t len ); // C++14, constexpr since C++20 563basic_string<char32_t> operator""s( const char32_t *str, size_t len ); // C++14, constexpr since C++20 564 565} // std 566 567*/ 568 569// clang-format on 570 571#include <__algorithm/max.h> 572#include <__algorithm/min.h> 573#include <__algorithm/remove.h> 574#include <__algorithm/remove_if.h> 575#include <__assert> // all public C++ headers provide the assertion handler 576#include <__config> 577#include <__format/enable_insertable.h> 578#include <__functional/hash.h> 579#include <__functional/unary_function.h> 580#include <__fwd/string.h> 581#include <__ios/fpos.h> 582#include <__iterator/distance.h> 583#include <__iterator/iterator_traits.h> 584#include <__iterator/reverse_iterator.h> 585#include <__iterator/wrap_iter.h> 586#include <__memory/addressof.h> 587#include <__memory/allocate_at_least.h> 588#include <__memory/allocator.h> 589#include <__memory/allocator_traits.h> 590#include <__memory/compressed_pair.h> 591#include <__memory/construct_at.h> 592#include <__memory/pointer_traits.h> 593#include <__memory/swap_allocator.h> 594#include <__memory_resource/polymorphic_allocator.h> 595#include <__ranges/access.h> 596#include <__ranges/concepts.h> 597#include <__ranges/container_compatible_range.h> 598#include <__ranges/from_range.h> 599#include <__ranges/size.h> 600#include <__string/char_traits.h> 601#include <__string/extern_template_lists.h> 602#include <__type_traits/is_allocator.h> 603#include <__type_traits/is_array.h> 604#include <__type_traits/is_convertible.h> 605#include <__type_traits/is_nothrow_default_constructible.h> 606#include <__type_traits/is_nothrow_move_assignable.h> 607#include <__type_traits/is_same.h> 608#include <__type_traits/is_standard_layout.h> 609#include <__type_traits/is_trivial.h> 610#include <__type_traits/noexcept_move_assign_container.h> 611#include <__type_traits/remove_cvref.h> 612#include <__type_traits/void_t.h> 613#include <__utility/auto_cast.h> 614#include <__utility/declval.h> 615#include <__utility/forward.h> 616#include <__utility/is_pointer_in_range.h> 617#include <__utility/move.h> 618#include <__utility/swap.h> 619#include <__utility/unreachable.h> 620#include <climits> 621#include <cstdio> // EOF 622#include <cstring> 623#include <limits> 624#include <stdexcept> 625#include <string_view> 626#include <version> 627 628#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 629# include <cwchar> 630#endif 631 632// standard-mandated includes 633 634// [iterator.range] 635#include <__iterator/access.h> 636#include <__iterator/data.h> 637#include <__iterator/empty.h> 638#include <__iterator/reverse_access.h> 639#include <__iterator/size.h> 640 641// [string.syn] 642#include <compare> 643#include <initializer_list> 644 645#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 646# pragma GCC system_header 647#endif 648 649_LIBCPP_PUSH_MACROS 650#include <__undef_macros> 651 652#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 653# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS __attribute__((__no_sanitize__("address"))) 654// This macro disables AddressSanitizer (ASan) instrumentation for a specific function, 655// allowing memory accesses that would normally trigger ASan errors to proceed without crashing. 656// This is useful for accessing parts of objects memory, which should not be accessed, 657// such as unused bytes in short strings, that should never be accessed 658// by other parts of the program. 659#else 660# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS 661#endif 662#define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false 663 664_LIBCPP_BEGIN_NAMESPACE_STD 665 666// basic_string 667 668template <class _CharT, class _Traits, class _Allocator> 669basic_string<_CharT, _Traits, _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 670operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const basic_string<_CharT, _Traits, _Allocator>& __y); 671 672template <class _CharT, class _Traits, class _Allocator> 673_LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 674operator+(const _CharT* __x, const basic_string<_CharT, _Traits, _Allocator>& __y); 675 676template <class _CharT, class _Traits, class _Allocator> 677_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 678operator+(_CharT __x, const basic_string<_CharT, _Traits, _Allocator>& __y); 679 680template <class _CharT, class _Traits, class _Allocator> 681inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 682operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y); 683 684template <class _CharT, class _Traits, class _Allocator> 685_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 686operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y); 687 688extern template _LIBCPP_EXPORTED_FROM_ABI string operator+ 689 <char, char_traits<char>, allocator<char> >(char const*, string const&); 690 691template <class _Iter> 692struct __string_is_trivial_iterator : public false_type {}; 693 694template <class _Tp> 695struct __string_is_trivial_iterator<_Tp*> : public is_arithmetic<_Tp> {}; 696 697template <class _Iter> 698struct __string_is_trivial_iterator<__wrap_iter<_Iter> > : public __string_is_trivial_iterator<_Iter> {}; 699 700template <class _CharT, class _Traits, class _Tp> 701struct __can_be_converted_to_string_view 702 : public _BoolConstant< is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value && 703 !is_convertible<const _Tp&, const _CharT*>::value > {}; 704 705struct __uninitialized_size_tag {}; 706struct __init_with_sentinel_tag {}; 707 708template <class _CharT, class _Traits, class _Allocator> 709class basic_string { 710private: 711 using __default_allocator_type = allocator<_CharT>; 712 713public: 714 typedef basic_string __self; 715 typedef basic_string_view<_CharT, _Traits> __self_view; 716 typedef _Traits traits_type; 717 typedef _CharT value_type; 718 typedef _Allocator allocator_type; 719 typedef allocator_traits<allocator_type> __alloc_traits; 720 typedef typename __alloc_traits::size_type size_type; 721 typedef typename __alloc_traits::difference_type difference_type; 722 typedef value_type& reference; 723 typedef const value_type& const_reference; 724 typedef typename __alloc_traits::pointer pointer; 725 typedef typename __alloc_traits::const_pointer const_pointer; 726 727 static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array"); 728 static_assert((is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout"); 729 static_assert((is_trivial<value_type>::value), "Character type of basic_string must be trivial"); 730 static_assert((is_same<_CharT, typename traits_type::char_type>::value), 731 "traits_type::char_type must be the same type as CharT"); 732 static_assert((is_same<typename allocator_type::value_type, value_type>::value), 733 "Allocator::value_type must be same type as value_type"); 734 735 static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value, 736 "[allocator.requirements] states that rebinding an allocator to the same type should result in the " 737 "original allocator"); 738 739 // TODO: Implement iterator bounds checking without requiring the global database. 740 typedef __wrap_iter<pointer> iterator; 741 typedef __wrap_iter<const_pointer> const_iterator; 742 typedef std::reverse_iterator<iterator> reverse_iterator; 743 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 744 745private: 746 static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits"); 747 748#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT 749 750 struct __long { 751 pointer __data_; 752 size_type __size_; 753 size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; 754 size_type __is_long_ : 1; 755 }; 756 757 enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 }; 758 759 struct __short { 760 value_type __data_[__min_cap]; 761 unsigned char __padding_[sizeof(value_type) - 1]; 762 unsigned char __size_ : 7; 763 unsigned char __is_long_ : 1; 764 }; 765 766 // The __endian_factor is required because the field we use to store the size 767 // has one fewer bit than it would if it were not a bitfield. 768 // 769 // If the LSB is used to store the short-flag in the short string representation, 770 // we have to multiply the size by two when it is stored and divide it by two when 771 // it is loaded to make sure that we always store an even number. In the long string 772 // representation, we can ignore this because we can assume that we always allocate 773 // an even amount of value_types. 774 // 775 // If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2. 776 // This does not impact the short string representation, since we never need the MSB 777 // for representing the size of a short string anyway. 778 779# ifdef _LIBCPP_BIG_ENDIAN 780 static const size_type __endian_factor = 2; 781# else 782 static const size_type __endian_factor = 1; 783# endif 784 785#else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT 786 787# ifdef _LIBCPP_BIG_ENDIAN 788 static const size_type __endian_factor = 1; 789# else 790 static const size_type __endian_factor = 2; 791# endif 792 793 // Attribute 'packed' is used to keep the layout compatible with the 794 // previous definition that did not use bit fields. This is because on 795 // some platforms bit fields have a default size rather than the actual 796 // size used, e.g., it is 4 bytes on AIX. See D128285 for details. 797 struct __long { 798 struct _LIBCPP_PACKED { 799 size_type __is_long_ : 1; 800 size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; 801 }; 802 size_type __size_; 803 pointer __data_; 804 }; 805 806 enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 }; 807 808 struct __short { 809 struct _LIBCPP_PACKED { 810 unsigned char __is_long_ : 1; 811 unsigned char __size_ : 7; 812 }; 813 char __padding_[sizeof(value_type) - 1]; 814 value_type __data_[__min_cap]; 815 }; 816 817#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT 818 819 static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size."); 820 821 union __ulx { 822 __long __lx; 823 __short __lxx; 824 }; 825 826 enum { __n_words = sizeof(__ulx) / sizeof(size_type) }; 827 828 struct __raw { 829 size_type __words[__n_words]; 830 }; 831 832 struct __rep { 833 union { 834 __short __s; 835 __long __l; 836 __raw __r; 837 }; 838 }; 839 840 __compressed_pair<__rep, allocator_type> __r_; 841 842 // Construct a string with the given allocator and enough storage to hold `__size` characters, but 843 // don't initialize the characters. The contents of the string, including the null terminator, must be 844 // initialized separately. 845 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( 846 __uninitialized_size_tag, size_type __size, const allocator_type& __a) 847 : __r_(__default_init_tag(), __a) { 848 if (__size > max_size()) 849 __throw_length_error(); 850 if (__fits_in_sso(__size)) { 851 __r_.first() = __rep(); 852 __set_short_size(__size); 853 } else { 854 auto __capacity = __recommend(__size) + 1; 855 auto __allocation = __alloc_traits::allocate(__alloc(), __capacity); 856 __begin_lifetime(__allocation, __capacity); 857 __set_long_cap(__capacity); 858 __set_long_pointer(__allocation); 859 __set_long_size(__size); 860 } 861 __annotate_new(__size); 862 } 863 864 template <class _Iter, class _Sent> 865 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 866 basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a) 867 : __r_(__default_init_tag(), __a) { 868 __init_with_sentinel(std::move(__first), std::move(__last)); 869 } 870 871 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iterator(pointer __p) { return iterator(__p); } 872 873 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_const_iterator(const_pointer __p) const { 874 return const_iterator(__p); 875 } 876 877public: 878 _LIBCPP_TEMPLATE_DATA_VIS static const size_type npos = -1; 879 880 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() 881 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) 882 : __r_(__value_init_tag(), __default_init_tag()) { 883 __annotate_new(0); 884 } 885 886 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) 887#if _LIBCPP_STD_VER <= 14 888 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value) 889#else 890 _NOEXCEPT 891#endif 892 : __r_(__value_init_tag(), __a) { 893 __annotate_new(0); 894 } 895 896 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str) 897 : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) { 898 if (!__str.__is_long()) { 899 __r_.first() = __str.__r_.first(); 900 __annotate_new(__get_short_size()); 901 } else 902 __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); 903 } 904 905 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS 906 basic_string(const basic_string& __str, const allocator_type& __a) 907 : __r_(__default_init_tag(), __a) { 908 if (!__str.__is_long()) { 909 __r_.first() = __str.__r_.first(); 910 __annotate_new(__get_short_size()); 911 } else 912 __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); 913 } 914 915#ifndef _LIBCPP_CXX03_LANG 916 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str) 917# if _LIBCPP_STD_VER <= 14 918 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) 919# else 920 _NOEXCEPT 921# endif 922 // Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS 923 // does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first. 924 // __str's memory needs to be unpoisoned only in the case where it's a short string. 925 : __r_([](basic_string &__s) -> decltype(__s.__r_)&& { if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_); }(__str)) { 926 __str.__r_.first() = __rep(); 927 __str.__annotate_new(0); 928 if (!__is_long()) 929 __annotate_new(size()); 930 } 931 932 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a) 933 : __r_(__default_init_tag(), __a) { 934 if (__str.__is_long() && __a != __str.__alloc()) // copy, not move 935 __init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); 936 else { 937 if (__libcpp_is_constant_evaluated()) 938 __r_.first() = __rep(); 939 if (!__str.__is_long()) 940 __str.__annotate_delete(); 941 __r_.first() = __str.__r_.first(); 942 __str.__r_.first() = __rep(); 943 __str.__annotate_new(0); 944 if (!__is_long() && this != &__str) 945 __annotate_new(size()); 946 } 947 } 948#endif // _LIBCPP_CXX03_LANG 949 950 template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> 951 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) 952 : __r_(__default_init_tag(), __default_init_tag()) { 953 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*) detected nullptr"); 954 __init(__s, traits_type::length(__s)); 955 } 956 957 template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> 958 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a) 959 : __r_(__default_init_tag(), __a) { 960 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); 961 __init(__s, traits_type::length(__s)); 962 } 963 964#if _LIBCPP_STD_VER >= 23 965 basic_string(nullptr_t) = delete; 966#endif 967 968 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) 969 : __r_(__default_init_tag(), __default_init_tag()) { 970 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); 971 __init(__s, __n); 972 } 973 974 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 975 basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) 976 : __r_(__default_init_tag(), __a) { 977 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); 978 __init(__s, __n); 979 } 980 981 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c) 982 : __r_(__default_init_tag(), __default_init_tag()) { 983 __init(__n, __c); 984 } 985 986#if _LIBCPP_STD_VER >= 23 987 _LIBCPP_HIDE_FROM_ABI constexpr basic_string( 988 basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator()) 989 : basic_string(std::move(__str), __pos, npos, __alloc) {} 990 991 _LIBCPP_HIDE_FROM_ABI constexpr basic_string( 992 basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator()) 993 : __r_(__default_init_tag(), __alloc) { 994 if (__pos > __str.size()) 995 __throw_out_of_range(); 996 997 auto __len = std::min<size_type>(__n, __str.size() - __pos); 998 if (__alloc_traits::is_always_equal::value || __alloc == __str.__alloc()) { 999 __move_assign(std::move(__str), __pos, __len); 1000 } else { 1001 // Perform a copy because the allocators are not compatible. 1002 __init(__str.data() + __pos, __len); 1003 } 1004 } 1005#endif 1006 1007 template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> 1008 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a) 1009 : __r_(__default_init_tag(), __a) { 1010 __init(__n, __c); 1011 } 1012 1013 _LIBCPP_CONSTEXPR_SINCE_CXX20 1014 basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()) 1015 : __r_(__default_init_tag(), __a) { 1016 size_type __str_sz = __str.size(); 1017 if (__pos > __str_sz) 1018 __throw_out_of_range(); 1019 __init(__str.data() + __pos, std::min(__n, __str_sz - __pos)); 1020 } 1021 1022 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 1023 basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()) 1024 : __r_(__default_init_tag(), __a) { 1025 size_type __str_sz = __str.size(); 1026 if (__pos > __str_sz) 1027 __throw_out_of_range(); 1028 __init(__str.data() + __pos, __str_sz - __pos); 1029 } 1030 1031 template <class _Tp, 1032 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1033 !__is_same_uncvref<_Tp, basic_string>::value, 1034 int> = 0> 1035 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 1036 basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()) 1037 : __r_(__default_init_tag(), __a) { 1038 __self_view __sv0 = __t; 1039 __self_view __sv = __sv0.substr(__pos, __n); 1040 __init(__sv.data(), __sv.size()); 1041 } 1042 1043 template <class _Tp, 1044 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1045 !__is_same_uncvref<_Tp, basic_string>::value, 1046 int> = 0> 1047 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) 1048 : __r_(__default_init_tag(), __default_init_tag()) { 1049 __self_view __sv = __t; 1050 __init(__sv.data(), __sv.size()); 1051 } 1052 1053 template <class _Tp, 1054 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1055 !__is_same_uncvref<_Tp, basic_string>::value, 1056 int> = 0> 1057 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( 1058 const _Tp& __t, const allocator_type& __a) 1059 : __r_(__default_init_tag(), __a) { 1060 __self_view __sv = __t; 1061 __init(__sv.data(), __sv.size()); 1062 } 1063 1064 template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> 1065 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last) 1066 : __r_(__default_init_tag(), __default_init_tag()) { 1067 __init(__first, __last); 1068 } 1069 1070 template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> 1071 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 1072 basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) 1073 : __r_(__default_init_tag(), __a) { 1074 __init(__first, __last); 1075 } 1076 1077#if _LIBCPP_STD_VER >= 23 1078 template <_ContainerCompatibleRange<_CharT> _Range> 1079 _LIBCPP_HIDE_FROM_ABI constexpr basic_string( 1080 from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) 1081 : __r_(__default_init_tag(), __a) { 1082 if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { 1083 __init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range)); 1084 } else { 1085 __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); 1086 } 1087 } 1088#endif 1089 1090#ifndef _LIBCPP_CXX03_LANG 1091 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) 1092 : __r_(__default_init_tag(), __default_init_tag()) { 1093 __init(__il.begin(), __il.end()); 1094 } 1095 1096 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a) 1097 : __r_(__default_init_tag(), __a) { 1098 __init(__il.begin(), __il.end()); 1099 } 1100#endif // _LIBCPP_CXX03_LANG 1101 1102 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { 1103 __annotate_delete(); 1104 if (__is_long()) 1105 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); 1106 } 1107 1108 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator __self_view() const _NOEXCEPT { 1109 return __self_view(data(), size()); 1110 } 1111 1112 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& 1113 operator=(const basic_string& __str); 1114 1115 template <class _Tp, 1116 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1117 !__is_same_uncvref<_Tp, basic_string>::value, 1118 int> = 0> 1119 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const _Tp& __t) { 1120 __self_view __sv = __t; 1121 return assign(__sv); 1122 } 1123 1124#ifndef _LIBCPP_CXX03_LANG 1125 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(basic_string&& __str) 1126 _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { 1127 __move_assign(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); 1128 return *this; 1129 } 1130 1131 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(initializer_list<value_type> __il) { 1132 return assign(__il.begin(), __il.size()); 1133 } 1134#endif 1135 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* __s) { 1136 return assign(__s); 1137 } 1138#if _LIBCPP_STD_VER >= 23 1139 basic_string& operator=(nullptr_t) = delete; 1140#endif 1141 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(value_type __c); 1142 1143 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT { 1144 return __make_iterator(__get_pointer()); 1145 } 1146 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT { 1147 return __make_const_iterator(__get_pointer()); 1148 } 1149 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT { 1150 return __make_iterator(__get_pointer() + size()); 1151 } 1152 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT { 1153 return __make_const_iterator(__get_pointer() + size()); 1154 } 1155 1156 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT { 1157 return reverse_iterator(end()); 1158 } 1159 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT { 1160 return const_reverse_iterator(end()); 1161 } 1162 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT { 1163 return reverse_iterator(begin()); 1164 } 1165 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT { 1166 return const_reverse_iterator(begin()); 1167 } 1168 1169 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT { return begin(); } 1170 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT { return end(); } 1171 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT { 1172 return rbegin(); 1173 } 1174 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } 1175 1176 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { 1177 return __is_long() ? __get_long_size() : __get_short_size(); 1178 } 1179 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT { return size(); } 1180 1181 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT { 1182 size_type __m = __alloc_traits::max_size(__alloc()); 1183 if (__m <= std::numeric_limits<size_type>::max() / 2) { 1184 return __m - __alignment; 1185 } else { 1186 bool __uses_lsb = __endian_factor == 2; 1187 return __uses_lsb ? __m - __alignment : (__m / 2) - __alignment; 1188 } 1189 } 1190 1191 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { 1192 return (__is_long() ? __get_long_cap() : static_cast<size_type>(__min_cap)) - 1; 1193 } 1194 1195 _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n, value_type __c); 1196 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n) { resize(__n, value_type()); } 1197 1198 _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity); 1199 1200#if _LIBCPP_STD_VER >= 23 1201 template <class _Op> 1202 _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { 1203 __resize_default_init(__n); 1204 __erase_to_end(std::move(__op)(data(), _LIBCPP_AUTO_CAST(__n))); 1205 } 1206#endif 1207 1208 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __resize_default_init(size_type __n); 1209 1210#if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE) 1211 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve() _NOEXCEPT { shrink_to_fit(); } 1212#endif 1213 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT; 1214 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT; 1215 1216 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT { 1217 return size() == 0; 1218 } 1219 1220 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT { 1221 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); 1222 if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { 1223 return *(__get_long_pointer() + __pos); 1224 } 1225 return *(data() + __pos); 1226 } 1227 1228 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT { 1229 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); 1230 if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { 1231 return *(__get_long_pointer() + __pos); 1232 } 1233 return *(__get_pointer() + __pos); 1234 } 1235 1236 _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; 1237 _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); 1238 1239 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const basic_string& __str) { 1240 return append(__str); 1241 } 1242 1243 template <class _Tp, 1244 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1245 !__is_same_uncvref<_Tp, basic_string >::value, 1246 int> = 0> 1247 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1248 operator+=(const _Tp& __t) { 1249 __self_view __sv = __t; 1250 return append(__sv); 1251 } 1252 1253 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const value_type* __s) { 1254 return append(__s); 1255 } 1256 1257 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(value_type __c) { 1258 push_back(__c); 1259 return *this; 1260 } 1261 1262#ifndef _LIBCPP_CXX03_LANG 1263 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(initializer_list<value_type> __il) { 1264 return append(__il); 1265 } 1266#endif // _LIBCPP_CXX03_LANG 1267 1268 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str) { 1269 return append(__str.data(), __str.size()); 1270 } 1271 1272 template <class _Tp, 1273 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1274 !__is_same_uncvref<_Tp, basic_string>::value, 1275 int> = 0> 1276 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1277 append(const _Tp& __t) { 1278 __self_view __sv = __t; 1279 return append(__sv.data(), __sv.size()); 1280 } 1281 1282 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str, size_type __pos, size_type __n = npos); 1283 1284 template <class _Tp, 1285 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1286 !__is_same_uncvref<_Tp, basic_string>::value, 1287 int> = 0> 1288 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 1289 1290 basic_string& 1291 append(const _Tp& __t, size_type __pos, size_type __n = npos); 1292 1293 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n); 1294 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s); 1295 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c); 1296 1297 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n); 1298 1299 template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> 1300 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1301 append(_InputIterator __first, _InputIterator __last) { 1302 const basic_string __temp(__first, __last, __alloc()); 1303 append(__temp.data(), __temp.size()); 1304 return *this; 1305 } 1306 1307 template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 1308 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1309 append(_ForwardIterator __first, _ForwardIterator __last); 1310 1311#if _LIBCPP_STD_VER >= 23 1312 template <_ContainerCompatibleRange<_CharT> _Range> 1313 _LIBCPP_HIDE_FROM_ABI constexpr basic_string& append_range(_Range&& __range) { 1314 insert_range(end(), std::forward<_Range>(__range)); 1315 return *this; 1316 } 1317#endif 1318 1319#ifndef _LIBCPP_CXX03_LANG 1320 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(initializer_list<value_type> __il) { 1321 return append(__il.begin(), __il.size()); 1322 } 1323#endif // _LIBCPP_CXX03_LANG 1324 1325 _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c); 1326 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back(); 1327 1328 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { 1329 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); 1330 return *__get_pointer(); 1331 } 1332 1333 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { 1334 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); 1335 return *data(); 1336 } 1337 1338 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { 1339 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); 1340 return *(__get_pointer() + size() - 1); 1341 } 1342 1343 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { 1344 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); 1345 return *(data() + size() - 1); 1346 } 1347 1348 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1349 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1350 assign(const _Tp& __t) { 1351 __self_view __sv = __t; 1352 return assign(__sv.data(), __sv.size()); 1353 } 1354 1355#if _LIBCPP_STD_VER >= 20 1356 _LIBCPP_HIDE_FROM_ABI constexpr void __move_assign(basic_string&& __str, size_type __pos, size_type __len) { 1357 // Pilfer the allocation from __str. 1358 _LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator"); 1359 size_type __old_sz = __str.size(); 1360 if (!__str.__is_long()) 1361 __str.__annotate_delete(); 1362 __r_.first() = __str.__r_.first(); 1363 __str.__r_.first() = __rep(); 1364 __str.__annotate_new(0); 1365 1366 _Traits::move(data(), data() + __pos, __len); 1367 __set_size(__len); 1368 _Traits::assign(data()[__len], value_type()); 1369 1370 if (!__is_long()) { 1371 __annotate_new(__len); 1372 } else if (__old_sz > __len) { 1373 __annotate_shrink(__old_sz); 1374 } 1375 } 1376#endif 1377 1378 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str) { 1379 return *this = __str; 1380 } 1381#ifndef _LIBCPP_CXX03_LANG 1382 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(basic_string&& __str) 1383 _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { 1384 *this = std::move(__str); 1385 return *this; 1386 } 1387#endif 1388 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n = npos); 1389 1390 template <class _Tp, 1391 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1392 !__is_same_uncvref<_Tp, basic_string>::value, 1393 int> = 0> 1394 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1395 assign(const _Tp& __t, size_type __pos, size_type __n = npos); 1396 1397 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n); 1398 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s); 1399 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c); 1400 template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> 1401 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1402 assign(_InputIterator __first, _InputIterator __last); 1403 1404 template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 1405 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1406 assign(_ForwardIterator __first, _ForwardIterator __last); 1407 1408#if _LIBCPP_STD_VER >= 23 1409 template <_ContainerCompatibleRange<_CharT> _Range> 1410 _LIBCPP_HIDE_FROM_ABI constexpr basic_string& assign_range(_Range&& __range) { 1411 if constexpr (__string_is_trivial_iterator<ranges::iterator_t<_Range>>::value && 1412 (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) { 1413 size_type __n = static_cast<size_type>(ranges::distance(__range)); 1414 __assign_trivial(ranges::begin(__range), ranges::end(__range), __n); 1415 1416 } else { 1417 __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); 1418 } 1419 1420 return *this; 1421 } 1422#endif 1423 1424#ifndef _LIBCPP_CXX03_LANG 1425 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(initializer_list<value_type> __il) { 1426 return assign(__il.begin(), __il.size()); 1427 } 1428#endif // _LIBCPP_CXX03_LANG 1429 1430 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1431 insert(size_type __pos1, const basic_string& __str) { 1432 return insert(__pos1, __str.data(), __str.size()); 1433 } 1434 1435 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1436 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1437 insert(size_type __pos1, const _Tp& __t) { 1438 __self_view __sv = __t; 1439 return insert(__pos1, __sv.data(), __sv.size()); 1440 } 1441 1442 template <class _Tp, 1443 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1444 !__is_same_uncvref<_Tp, basic_string>::value, 1445 int> = 0> 1446 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1447 insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos); 1448 1449 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1450 insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos); 1451 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n); 1452 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s); 1453 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c); 1454 _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c); 1455 1456#if _LIBCPP_STD_VER >= 23 1457 template <_ContainerCompatibleRange<_CharT> _Range> 1458 _LIBCPP_HIDE_FROM_ABI constexpr iterator insert_range(const_iterator __position, _Range&& __range) { 1459 if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { 1460 auto __n = static_cast<size_type>(ranges::distance(__range)); 1461 return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); 1462 1463 } else { 1464 basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); 1465 return insert(__position, __temp.data(), __temp.data() + __temp.size()); 1466 } 1467 } 1468#endif 1469 1470 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator 1471 insert(const_iterator __pos, size_type __n, value_type __c) { 1472 difference_type __p = __pos - begin(); 1473 insert(static_cast<size_type>(__p), __n, __c); 1474 return begin() + __p; 1475 } 1476 1477 template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> 1478 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator 1479 insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); 1480 1481 template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 1482 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator 1483 insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); 1484 1485#ifndef _LIBCPP_CXX03_LANG 1486 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator 1487 insert(const_iterator __pos, initializer_list<value_type> __il) { 1488 return insert(__pos, __il.begin(), __il.end()); 1489 } 1490#endif // _LIBCPP_CXX03_LANG 1491 1492 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& erase(size_type __pos = 0, size_type __n = npos); 1493 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __pos); 1494 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __first, const_iterator __last); 1495 1496 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1497 replace(size_type __pos1, size_type __n1, const basic_string& __str) { 1498 return replace(__pos1, __n1, __str.data(), __str.size()); 1499 } 1500 1501 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1502 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1503 replace(size_type __pos1, size_type __n1, const _Tp& __t) { 1504 __self_view __sv = __t; 1505 return replace(__pos1, __n1, __sv.data(), __sv.size()); 1506 } 1507 1508 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1509 replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos); 1510 1511 template <class _Tp, 1512 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1513 !__is_same_uncvref<_Tp, basic_string>::value, 1514 int> = 0> 1515 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1516 replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos); 1517 1518 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1519 replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); 1520 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); 1521 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); 1522 1523 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1524 replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { 1525 return replace( 1526 static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __str.data(), __str.size()); 1527 } 1528 1529 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1530 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1531 replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { 1532 __self_view __sv = __t; 1533 return replace(__i1 - begin(), __i2 - __i1, __sv); 1534 } 1535 1536 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1537 replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { 1538 return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s, __n); 1539 } 1540 1541 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1542 replace(const_iterator __i1, const_iterator __i2, const value_type* __s) { 1543 return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s); 1544 } 1545 1546 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1547 replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) { 1548 return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c); 1549 } 1550 1551 template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> 1552 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1553 replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); 1554 1555#if _LIBCPP_STD_VER >= 23 1556 template <_ContainerCompatibleRange<_CharT> _Range> 1557 _LIBCPP_HIDE_FROM_ABI constexpr basic_string& 1558 replace_with_range(const_iterator __i1, const_iterator __i2, _Range&& __range) { 1559 basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); 1560 return replace(__i1, __i2, __temp); 1561 } 1562#endif 1563 1564#ifndef _LIBCPP_CXX03_LANG 1565 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 1566 replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il) { 1567 return replace(__i1, __i2, __il.begin(), __il.end()); 1568 } 1569#endif // _LIBCPP_CXX03_LANG 1570 1571 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; 1572 1573#if _LIBCPP_STD_VER <= 20 1574 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string 1575 substr(size_type __pos = 0, size_type __n = npos) const { 1576 return basic_string(*this, __pos, __n); 1577 } 1578#else 1579 _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) const& { 1580 return basic_string(*this, __pos, __n); 1581 } 1582 1583 _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) && { 1584 return basic_string(std::move(*this), __pos, __n); 1585 } 1586#endif 1587 1588 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str) 1589#if _LIBCPP_STD_VER >= 14 1590 _NOEXCEPT; 1591#else 1592 _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value); 1593#endif 1594 1595 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* c_str() const _NOEXCEPT { return data(); } 1596 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT { 1597 return std::__to_address(__get_pointer()); 1598 } 1599#if _LIBCPP_STD_VER >= 17 1600 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT { 1601 return std::__to_address(__get_pointer()); 1602 } 1603#endif 1604 1605 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT { 1606 return __alloc(); 1607 } 1608 1609 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1610 find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; 1611 1612 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1613 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1614 find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; 1615 1616 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1617 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1618 find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; 1619 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT; 1620 1621 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1622 rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; 1623 1624 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1625 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1626 rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; 1627 1628 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1629 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1630 rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; 1631 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT; 1632 1633 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1634 find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; 1635 1636 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1637 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1638 find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; 1639 1640 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1641 find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1642 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1643 find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; 1644 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1645 find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; 1646 1647 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1648 find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; 1649 1650 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1651 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1652 find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; 1653 1654 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1655 find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1656 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1657 find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; 1658 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1659 find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; 1660 1661 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1662 find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; 1663 1664 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1665 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1666 find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; 1667 1668 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1669 find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1670 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1671 find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; 1672 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1673 find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; 1674 1675 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1676 find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; 1677 1678 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1679 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1680 find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; 1681 1682 _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1683 find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; 1684 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1685 find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; 1686 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type 1687 find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; 1688 1689 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const basic_string& __str) const _NOEXCEPT; 1690 1691 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1692 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1693 compare(const _Tp& __t) const _NOEXCEPT; 1694 1695 template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> 1696 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1697 compare(size_type __pos1, size_type __n1, const _Tp& __t) const; 1698 1699 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1700 compare(size_type __pos1, size_type __n1, const basic_string& __str) const; 1701 _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1702 compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const; 1703 1704 template <class _Tp, 1705 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 1706 !__is_same_uncvref<_Tp, basic_string>::value, 1707 int> = 0> 1708 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1709 compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const; 1710 1711 _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* __s) const _NOEXCEPT; 1712 _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s) const; 1713 _LIBCPP_CONSTEXPR_SINCE_CXX20 int 1714 compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const; 1715 1716#if _LIBCPP_STD_VER >= 20 1717 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { 1718 return __self_view(data(), size()).starts_with(__sv); 1719 } 1720 1721 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept { 1722 return !empty() && _Traits::eq(front(), __c); 1723 } 1724 1725 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(const value_type* __s) const noexcept { 1726 return starts_with(__self_view(__s)); 1727 } 1728 1729 constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(__self_view __sv) const noexcept { 1730 return __self_view(data(), size()).ends_with(__sv); 1731 } 1732 1733 constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept { 1734 return !empty() && _Traits::eq(back(), __c); 1735 } 1736 1737 constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(const value_type* __s) const noexcept { 1738 return ends_with(__self_view(__s)); 1739 } 1740#endif 1741 1742#if _LIBCPP_STD_VER >= 23 1743 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { 1744 return __self_view(data(), size()).contains(__sv); 1745 } 1746 1747 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept { 1748 return __self_view(data(), size()).contains(__c); 1749 } 1750 1751 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(const value_type* __s) const { 1752 return __self_view(data(), size()).contains(__s); 1753 } 1754#endif 1755 1756 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const; 1757 1758 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __clear_and_shrink() _NOEXCEPT; 1759 1760private: 1761 template <class _Alloc> 1762 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool friend 1763 operator==(const basic_string<char, char_traits<char>, _Alloc>& __lhs, 1764 const basic_string<char, char_traits<char>, _Alloc>& __rhs) _NOEXCEPT; 1765 1766 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __shrink_or_extend(size_type __target_capacity); 1767 1768 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS bool 1769 __is_long() const _NOEXCEPT { 1770 if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) { 1771 return __r_.first().__l.__is_long_; 1772 } 1773 return __r_.first().__s.__is_long_; 1774 } 1775 1776 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) { 1777#if _LIBCPP_STD_VER >= 20 1778 if (__libcpp_is_constant_evaluated()) { 1779 for (size_type __i = 0; __i != __n; ++__i) 1780 std::construct_at(std::addressof(__begin[__i])); 1781 } 1782#else 1783 (void)__begin; 1784 (void)__n; 1785#endif // _LIBCPP_STD_VER >= 20 1786 } 1787 1788 _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) { return __sz < __min_cap; } 1789 1790 template <class _Iterator, class _Sentinel> 1791 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void 1792 __assign_trivial(_Iterator __first, _Sentinel __last, size_type __n); 1793 1794 template <class _Iterator, class _Sentinel> 1795 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last); 1796 1797 template <class _ForwardIterator, class _Sentinel> 1798 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 iterator 1799 __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) { 1800 size_type __sz = size(); 1801 size_type __cap = capacity(); 1802 value_type* __p; 1803 if (__cap - __sz >= __n) { 1804 __annotate_increase(__n); 1805 __p = std::__to_address(__get_pointer()); 1806 size_type __n_move = __sz - __ip; 1807 if (__n_move != 0) 1808 traits_type::move(__p + __ip + __n, __p + __ip, __n_move); 1809 } else { 1810 __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); 1811 __p = std::__to_address(__get_long_pointer()); 1812 } 1813 __sz += __n; 1814 __set_size(__sz); 1815 traits_type::assign(__p[__sz], value_type()); 1816 for (__p += __ip; __first != __last; ++__p, ++__first) 1817 traits_type::assign(*__p, *__first); 1818 1819 return begin() + __ip; 1820 } 1821 1822 template <class _Iterator, class _Sentinel> 1823 _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator 1824 __insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n); 1825 1826 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); } 1827 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); } 1828 1829 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void 1830 __set_short_size(size_type __s) _NOEXCEPT { 1831 _LIBCPP_ASSERT_INTERNAL(__s < __min_cap, "__s should never be greater than or equal to the short string capacity"); 1832 __r_.first().__s.__size_ = __s; 1833 __r_.first().__s.__is_long_ = false; 1834 } 1835 1836 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS size_type 1837 __get_short_size() const _NOEXCEPT { 1838 _LIBCPP_ASSERT_INTERNAL(!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size"); 1839 return __r_.first().__s.__size_; 1840 } 1841 1842 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_size(size_type __s) _NOEXCEPT { 1843 __r_.first().__l.__size_ = __s; 1844 } 1845 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_size() const _NOEXCEPT { 1846 return __r_.first().__l.__size_; 1847 } 1848 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_size(size_type __s) _NOEXCEPT { 1849 if (__is_long()) 1850 __set_long_size(__s); 1851 else 1852 __set_short_size(__s); 1853 } 1854 1855 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_cap(size_type __s) _NOEXCEPT { 1856 __r_.first().__l.__cap_ = __s / __endian_factor; 1857 __r_.first().__l.__is_long_ = true; 1858 } 1859 1860 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_cap() const _NOEXCEPT { 1861 return __r_.first().__l.__cap_ * __endian_factor; 1862 } 1863 1864 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_pointer(pointer __p) _NOEXCEPT { 1865 __r_.first().__l.__data_ = __p; 1866 } 1867 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer() _NOEXCEPT { 1868 return __r_.first().__l.__data_; 1869 } 1870 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer() const _NOEXCEPT { 1871 return __r_.first().__l.__data_; 1872 } 1873 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_short_pointer() _NOEXCEPT { 1874 return pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]); 1875 } 1876 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_short_pointer() const _NOEXCEPT { 1877 return pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]); 1878 } 1879 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer() _NOEXCEPT { 1880 return __is_long() ? __get_long_pointer() : __get_short_pointer(); 1881 } 1882 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_pointer() const _NOEXCEPT { 1883 return __is_long() ? __get_long_pointer() : __get_short_pointer(); 1884 } 1885 1886 // The following functions are no-ops outside of AddressSanitizer mode. 1887 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 1888 __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const { 1889 (void)__old_mid; 1890 (void)__new_mid; 1891#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 1892 const void* __begin = data(); 1893 const void* __end = data() + capacity() + 1; 1894 if (__asan_annotate_container_with_allocator<allocator_type>::value && !__libcpp_is_constant_evaluated()) 1895 __sanitizer_annotate_contiguous_container(__begin, __end, __old_mid, __new_mid); 1896#endif 1897 } 1898 1899 // ASan: short string is poisoned if and only if this function returns true. 1900 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __asan_short_string_is_annotated() const _NOEXCEPT { 1901 return _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED && !__libcpp_is_constant_evaluated(); 1902 } 1903 1904 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_new(size_type __current_size) const _NOEXCEPT { 1905 (void) __current_size; 1906#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 1907 if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) 1908 __annotate_contiguous_container(data() + capacity() + 1, data() + __current_size + 1); 1909#endif 1910 } 1911 1912 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT { 1913#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 1914 if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) 1915 __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1); 1916#endif 1917 } 1918 1919 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_increase(size_type __n) const _NOEXCEPT { 1920 (void) __n; 1921#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 1922 if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) 1923 __annotate_contiguous_container(data() + size() + 1, data() + size() + 1 + __n); 1924#endif 1925 } 1926 1927 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_shrink(size_type __old_size) const _NOEXCEPT { 1928 (void) __old_size; 1929#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) 1930 if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) 1931 __annotate_contiguous_container(data() + __old_size + 1, data() + size() + 1); 1932#endif 1933 } 1934 1935 template <size_type __a> 1936 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __align_it(size_type __s) _NOEXCEPT { 1937 return (__s + (__a - 1)) & ~(__a - 1); 1938 } 1939 enum { 1940 __alignment = 1941#ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT 1942 8 1943#else 1944 16 1945#endif 1946 }; 1947 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT { 1948 if (__s < __min_cap) { 1949 return static_cast<size_type>(__min_cap) - 1; 1950 } 1951 size_type __guess = 1952 __align_it < sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : 1 > (__s + 1) - 1; 1953 if (__guess == __min_cap) 1954 ++__guess; 1955 return __guess; 1956 } 1957 1958 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz, size_type __reserve); 1959 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz); 1960 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(size_type __n, value_type __c); 1961 1962 // Slow path for the (inlined) copy constructor for 'long' strings. 1963 // Always externally instantiated and not inlined. 1964 // Requires that __s is zero terminated. 1965 // The main reason for this function to exist is because for unstable, we 1966 // want to allow inlining of the copy constructor. However, we don't want 1967 // to call the __init() functions as those are marked as inline which may 1968 // result in over-aggressive inlining by the compiler, where our aim is 1969 // to only inline the fast path code directly in the ctor. 1970 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __init_copy_ctor_external(const value_type* __s, size_type __sz); 1971 1972 template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> 1973 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_InputIterator __first, _InputIterator __last); 1974 1975 template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 1976 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_ForwardIterator __first, _ForwardIterator __last); 1977 1978 template <class _InputIterator, class _Sentinel> 1979 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 1980 __init_with_sentinel(_InputIterator __first, _Sentinel __last); 1981 template <class _InputIterator, class _Sentinel> 1982 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 1983 __init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz); 1984 1985 _LIBCPP_CONSTEXPR_SINCE_CXX20 1986#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 1987 _LIBCPP_HIDE_FROM_ABI 1988#endif 1989 _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by( 1990 size_type __old_cap, 1991 size_type __delta_cap, 1992 size_type __old_sz, 1993 size_type __n_copy, 1994 size_type __n_del, 1995 size_type __n_add = 0); 1996 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __grow_by_without_replace( 1997 size_type __old_cap, 1998 size_type __delta_cap, 1999 size_type __old_sz, 2000 size_type __n_copy, 2001 size_type __n_del, 2002 size_type __n_add = 0); 2003 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __grow_by_and_replace( 2004 size_type __old_cap, 2005 size_type __delta_cap, 2006 size_type __old_sz, 2007 size_type __n_copy, 2008 size_type __n_del, 2009 size_type __n_add, 2010 const value_type* __p_new_stuff); 2011 2012 // __assign_no_alias is invoked for assignment operations where we 2013 // have proof that the input does not alias the current instance. 2014 // For example, operator=(basic_string) performs a 'self' check. 2015 template <bool __is_short> 2016 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_no_alias(const value_type* __s, size_type __n); 2017 2018 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) { 2019 __null_terminate_at(std::__to_address(__get_pointer()), __pos); 2020 } 2021 2022 // __erase_external_with_move is invoked for erase() invocations where 2023 // `n ~= npos`, likely requiring memory moves on the string data. 2024 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __erase_external_with_move(size_type __pos, size_type __n); 2025 2026 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str) { 2027 __copy_assign_alloc( 2028 __str, integral_constant<bool, __alloc_traits::propagate_on_container_copy_assignment::value>()); 2029 } 2030 2031 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str, true_type) { 2032 if (__alloc() == __str.__alloc()) 2033 __alloc() = __str.__alloc(); 2034 else { 2035 if (!__str.__is_long()) { 2036 __clear_and_shrink(); 2037 __alloc() = __str.__alloc(); 2038 } else { 2039 __annotate_delete(); 2040 allocator_type __a = __str.__alloc(); 2041 auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap()); 2042 __begin_lifetime(__allocation.ptr, __allocation.count); 2043 if (__is_long()) 2044 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); 2045 __alloc() = std::move(__a); 2046 __set_long_pointer(__allocation.ptr); 2047 __set_long_cap(__allocation.count); 2048 __set_long_size(__str.size()); 2049 __annotate_new(__get_long_size()); 2050 } 2051 } 2052 } 2053 2054 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 2055 __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT {} 2056 2057#ifndef _LIBCPP_CXX03_LANG 2058 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(basic_string& __str, false_type) 2059 _NOEXCEPT_(__alloc_traits::is_always_equal::value); 2060 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void 2061 __move_assign(basic_string& __str, true_type) 2062# if _LIBCPP_STD_VER >= 17 2063 _NOEXCEPT; 2064# else 2065 _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); 2066# endif 2067#endif 2068 2069 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __str) 2070 _NOEXCEPT_(!__alloc_traits::propagate_on_container_move_assignment::value || 2071 is_nothrow_move_assignable<allocator_type>::value) { 2072 __move_assign_alloc( 2073 __str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); 2074 } 2075 2076 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __c, true_type) 2077 _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { 2078 __alloc() = std::move(__c.__alloc()); 2079 } 2080 2081 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string&, false_type) _NOEXCEPT {} 2082 2083 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s); 2084 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s, size_type __n); 2085 2086 // Assigns the value in __s, guaranteed to be __n < __min_cap in length. 2087 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) { 2088 size_type __old_size = size(); 2089 if (__n > __old_size) 2090 __annotate_increase(__n - __old_size); 2091 pointer __p = 2092 __is_long() ? (__set_long_size(__n), __get_long_pointer()) : (__set_short_size(__n), __get_short_pointer()); 2093 traits_type::move(std::__to_address(__p), __s, __n); 2094 traits_type::assign(__p[__n], value_type()); 2095 if (__old_size > __n) 2096 __annotate_shrink(__old_size); 2097 return *this; 2098 } 2099 2100 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& 2101 __null_terminate_at(value_type* __p, size_type __newsz) { 2102 size_type __old_size = size(); 2103 if (__newsz > __old_size) 2104 __annotate_increase(__newsz - __old_size); 2105 __set_size(__newsz); 2106 traits_type::assign(__p[__newsz], value_type()); 2107 if (__old_size > __newsz) 2108 __annotate_shrink(__old_size); 2109 return *this; 2110 } 2111 2112 template <class _Tp> 2113 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const { 2114 return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v)); 2115 } 2116 2117 _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { 2118 std::__throw_length_error("basic_string"); 2119 } 2120 2121 _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { 2122 std::__throw_out_of_range("basic_string"); 2123 } 2124 2125 friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const basic_string&); 2126 friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const value_type*, const basic_string&); 2127 friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(value_type, const basic_string&); 2128 friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const value_type*); 2129 friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, value_type); 2130}; 2131 2132// These declarations must appear before any functions are implicitly used 2133// so that they have the correct visibility specifier. 2134#define _LIBCPP_DECLARE(...) extern template __VA_ARGS__; 2135#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION 2136_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) 2137# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2138_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) 2139# endif 2140#else 2141_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) 2142# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2143_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) 2144# endif 2145#endif 2146#undef _LIBCPP_DECLARE 2147 2148#if _LIBCPP_STD_VER >= 17 2149template <class _InputIterator, 2150 class _CharT = __iter_value_type<_InputIterator>, 2151 class _Allocator = allocator<_CharT>, 2152 class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, 2153 class = enable_if_t<__is_allocator<_Allocator>::value> > 2154basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) 2155 -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; 2156 2157template <class _CharT, 2158 class _Traits, 2159 class _Allocator = allocator<_CharT>, 2160 class = enable_if_t<__is_allocator<_Allocator>::value> > 2161explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator()) 2162 -> basic_string<_CharT, _Traits, _Allocator>; 2163 2164template <class _CharT, 2165 class _Traits, 2166 class _Allocator = allocator<_CharT>, 2167 class = enable_if_t<__is_allocator<_Allocator>::value>, 2168 class _Sz = typename allocator_traits<_Allocator>::size_type > 2169basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator()) 2170 -> basic_string<_CharT, _Traits, _Allocator>; 2171#endif 2172 2173#if _LIBCPP_STD_VER >= 23 2174template <ranges::input_range _Range, 2175 class _Allocator = allocator<ranges::range_value_t<_Range>>, 2176 class = enable_if_t<__is_allocator<_Allocator>::value> > 2177basic_string(from_range_t, _Range&&, _Allocator = _Allocator()) 2178 -> basic_string<ranges::range_value_t<_Range>, char_traits<ranges::range_value_t<_Range>>, _Allocator>; 2179#endif 2180 2181template <class _CharT, class _Traits, class _Allocator> 2182_LIBCPP_CONSTEXPR_SINCE_CXX20 void 2183basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) { 2184 if (__libcpp_is_constant_evaluated()) 2185 __r_.first() = __rep(); 2186 if (__reserve > max_size()) 2187 __throw_length_error(); 2188 pointer __p; 2189 if (__fits_in_sso(__reserve)) { 2190 __set_short_size(__sz); 2191 __p = __get_short_pointer(); 2192 } else { 2193 auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1); 2194 __p = __allocation.ptr; 2195 __begin_lifetime(__p, __allocation.count); 2196 __set_long_pointer(__p); 2197 __set_long_cap(__allocation.count); 2198 __set_long_size(__sz); 2199 } 2200 traits_type::copy(std::__to_address(__p), __s, __sz); 2201 traits_type::assign(__p[__sz], value_type()); 2202 __annotate_new(__sz); 2203} 2204 2205template <class _CharT, class _Traits, class _Allocator> 2206_LIBCPP_CONSTEXPR_SINCE_CXX20 void 2207basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz) { 2208 if (__libcpp_is_constant_evaluated()) 2209 __r_.first() = __rep(); 2210 if (__sz > max_size()) 2211 __throw_length_error(); 2212 pointer __p; 2213 if (__fits_in_sso(__sz)) { 2214 __set_short_size(__sz); 2215 __p = __get_short_pointer(); 2216 } else { 2217 auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); 2218 __p = __allocation.ptr; 2219 __begin_lifetime(__p, __allocation.count); 2220 __set_long_pointer(__p); 2221 __set_long_cap(__allocation.count); 2222 __set_long_size(__sz); 2223 } 2224 traits_type::copy(std::__to_address(__p), __s, __sz); 2225 traits_type::assign(__p[__sz], value_type()); 2226 __annotate_new(__sz); 2227} 2228 2229template <class _CharT, class _Traits, class _Allocator> 2230_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void 2231basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value_type* __s, size_type __sz) { 2232 if (__libcpp_is_constant_evaluated()) 2233 __r_.first() = __rep(); 2234 2235 pointer __p; 2236 if (__fits_in_sso(__sz)) { 2237 __p = __get_short_pointer(); 2238 __set_short_size(__sz); 2239 } else { 2240 if (__sz > max_size()) 2241 __throw_length_error(); 2242 auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); 2243 __p = __allocation.ptr; 2244 __begin_lifetime(__p, __allocation.count); 2245 __set_long_pointer(__p); 2246 __set_long_cap(__allocation.count); 2247 __set_long_size(__sz); 2248 } 2249 traits_type::copy(std::__to_address(__p), __s, __sz + 1); 2250 __annotate_new(__sz); 2251} 2252 2253template <class _CharT, class _Traits, class _Allocator> 2254_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) { 2255 if (__libcpp_is_constant_evaluated()) 2256 __r_.first() = __rep(); 2257 2258 if (__n > max_size()) 2259 __throw_length_error(); 2260 pointer __p; 2261 if (__fits_in_sso(__n)) { 2262 __set_short_size(__n); 2263 __p = __get_short_pointer(); 2264 } else { 2265 auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1); 2266 __p = __allocation.ptr; 2267 __begin_lifetime(__p, __allocation.count); 2268 __set_long_pointer(__p); 2269 __set_long_cap(__allocation.count); 2270 __set_long_size(__n); 2271 } 2272 traits_type::assign(std::__to_address(__p), __n, __c); 2273 traits_type::assign(__p[__n], value_type()); 2274 __annotate_new(__n); 2275} 2276 2277template <class _CharT, class _Traits, class _Allocator> 2278template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > 2279_LIBCPP_CONSTEXPR_SINCE_CXX20 void 2280basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) { 2281 __init_with_sentinel(std::move(__first), std::move(__last)); 2282} 2283 2284template <class _CharT, class _Traits, class _Allocator> 2285template <class _InputIterator, class _Sentinel> 2286_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 2287basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) { 2288 __r_.first() = __rep(); 2289 __annotate_new(0); 2290 2291#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2292 try { 2293#endif // _LIBCPP_HAS_NO_EXCEPTIONS 2294 for (; __first != __last; ++__first) 2295 push_back(*__first); 2296#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2297 } catch (...) { 2298 __annotate_delete(); 2299 if (__is_long()) 2300 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); 2301 throw; 2302 } 2303#endif // _LIBCPP_HAS_NO_EXCEPTIONS 2304} 2305 2306template <class _CharT, class _Traits, class _Allocator> 2307template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 2308_LIBCPP_CONSTEXPR_SINCE_CXX20 void 2309basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last) { 2310 size_type __sz = static_cast<size_type>(std::distance(__first, __last)); 2311 __init_with_size(__first, __last, __sz); 2312} 2313 2314template <class _CharT, class _Traits, class _Allocator> 2315template <class _InputIterator, class _Sentinel> 2316_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 2317basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz) { 2318 if (__libcpp_is_constant_evaluated()) 2319 __r_.first() = __rep(); 2320 2321 if (__sz > max_size()) 2322 __throw_length_error(); 2323 2324 pointer __p; 2325 if (__fits_in_sso(__sz)) { 2326 __set_short_size(__sz); 2327 __p = __get_short_pointer(); 2328 2329 } else { 2330 auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); 2331 __p = __allocation.ptr; 2332 __begin_lifetime(__p, __allocation.count); 2333 __set_long_pointer(__p); 2334 __set_long_cap(__allocation.count); 2335 __set_long_size(__sz); 2336 } 2337 2338#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2339 try { 2340#endif // _LIBCPP_HAS_NO_EXCEPTIONS 2341 for (; __first != __last; ++__first, (void)++__p) 2342 traits_type::assign(*__p, *__first); 2343 traits_type::assign(*__p, value_type()); 2344#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2345 } catch (...) { 2346 if (__is_long()) 2347 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); 2348 throw; 2349 } 2350#endif // _LIBCPP_HAS_NO_EXCEPTIONS 2351 __annotate_new(__sz); 2352} 2353 2354template <class _CharT, class _Traits, class _Allocator> 2355_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace( 2356 size_type __old_cap, 2357 size_type __delta_cap, 2358 size_type __old_sz, 2359 size_type __n_copy, 2360 size_type __n_del, 2361 size_type __n_add, 2362 const value_type* __p_new_stuff) { 2363 size_type __ms = max_size(); 2364 if (__delta_cap > __ms - __old_cap - 1) 2365 __throw_length_error(); 2366 pointer __old_p = __get_pointer(); 2367 size_type __cap = 2368 __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; 2369 __annotate_delete(); 2370 auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); 2371 pointer __p = __allocation.ptr; 2372 __begin_lifetime(__p, __allocation.count); 2373 if (__n_copy != 0) 2374 traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); 2375 if (__n_add != 0) 2376 traits_type::copy(std::__to_address(__p) + __n_copy, __p_new_stuff, __n_add); 2377 size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; 2378 if (__sec_cp_sz != 0) 2379 traits_type::copy( 2380 std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); 2381 if (__old_cap + 1 != __min_cap) 2382 __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1); 2383 __set_long_pointer(__p); 2384 __set_long_cap(__allocation.count); 2385 __old_sz = __n_copy + __n_add + __sec_cp_sz; 2386 __set_long_size(__old_sz); 2387 traits_type::assign(__p[__old_sz], value_type()); 2388 __annotate_new(__old_cap + __delta_cap); 2389} 2390 2391// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it 2392// may also not set the size at all when the string was short initially. This leads to unpredictable size value. It is 2393// not removed or changed to avoid breaking the ABI. 2394template <class _CharT, class _Traits, class _Allocator> 2395void _LIBCPP_CONSTEXPR_SINCE_CXX20 2396#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 2397 _LIBCPP_HIDE_FROM_ABI 2398#endif 2399 _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by( 2400 size_type __old_cap, 2401 size_type __delta_cap, 2402 size_type __old_sz, 2403 size_type __n_copy, 2404 size_type __n_del, 2405 size_type __n_add) { 2406 size_type __ms = max_size(); 2407 if (__delta_cap > __ms - __old_cap) 2408 __throw_length_error(); 2409 pointer __old_p = __get_pointer(); 2410 size_type __cap = 2411 __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; 2412 __annotate_delete(); 2413 auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); 2414 pointer __p = __allocation.ptr; 2415 __begin_lifetime(__p, __allocation.count); 2416 if (__n_copy != 0) 2417 traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); 2418 size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; 2419 if (__sec_cp_sz != 0) 2420 traits_type::copy( 2421 std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); 2422 if (__old_cap + 1 != __min_cap) 2423 __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1); 2424 __set_long_pointer(__p); 2425 __set_long_cap(__allocation.count); 2426} 2427 2428template <class _CharT, class _Traits, class _Allocator> 2429void _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 2430basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace( 2431 size_type __old_cap, 2432 size_type __delta_cap, 2433 size_type __old_sz, 2434 size_type __n_copy, 2435 size_type __n_del, 2436 size_type __n_add) { 2437 _LIBCPP_SUPPRESS_DEPRECATED_PUSH 2438 __grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add); 2439 _LIBCPP_SUPPRESS_DEPRECATED_POP 2440 __set_long_size(__old_sz - __n_del + __n_add); 2441 __annotate_new(__old_sz - __n_del + __n_add); 2442} 2443 2444// assign 2445 2446template <class _CharT, class _Traits, class _Allocator> 2447template <bool __is_short> 2448_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& 2449basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) { 2450 size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap(); 2451 if (__n < __cap) { 2452 size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); 2453 if (__n > __old_size) 2454 __annotate_increase(__n - __old_size); 2455 pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); 2456 __is_short ? __set_short_size(__n) : __set_long_size(__n); 2457 traits_type::copy(std::__to_address(__p), __s, __n); 2458 traits_type::assign(__p[__n], value_type()); 2459 if (__old_size > __n) 2460 __annotate_shrink(__old_size); 2461 } else { 2462 size_type __sz = __is_short ? __get_short_size() : __get_long_size(); 2463 __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); 2464 } 2465 return *this; 2466} 2467 2468template <class _CharT, class _Traits, class _Allocator> 2469_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& 2470basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s, size_type __n) { 2471 size_type __cap = capacity(); 2472 if (__cap >= __n) { 2473 size_type __old_size = size(); 2474 if (__n > __old_size) 2475 __annotate_increase(__n - __old_size); 2476 value_type* __p = std::__to_address(__get_pointer()); 2477 traits_type::move(__p, __s, __n); 2478 return __null_terminate_at(__p, __n); 2479 } else { 2480 size_type __sz = size(); 2481 __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); 2482 return *this; 2483 } 2484} 2485 2486template <class _CharT, class _Traits, class _Allocator> 2487_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2488basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { 2489 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::assign received nullptr"); 2490 return (__builtin_constant_p(__n) && __fits_in_sso(__n)) ? __assign_short(__s, __n) : __assign_external(__s, __n); 2491} 2492 2493template <class _CharT, class _Traits, class _Allocator> 2494_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2495basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) { 2496 size_type __cap = capacity(); 2497 size_type __old_size = size(); 2498 if (__cap < __n) { 2499 size_type __sz = size(); 2500 __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); 2501 __annotate_increase(__n); 2502 } else if (__n > __old_size) 2503 __annotate_increase(__n - __old_size); 2504 value_type* __p = std::__to_address(__get_pointer()); 2505 traits_type::assign(__p, __n, __c); 2506 return __null_terminate_at(__p, __n); 2507} 2508 2509template <class _CharT, class _Traits, class _Allocator> 2510_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2511basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { 2512 pointer __p; 2513 size_type __old_size = size(); 2514 if (__old_size == 0) 2515 __annotate_increase(1); 2516 if (__is_long()) { 2517 __p = __get_long_pointer(); 2518 __set_long_size(1); 2519 } else { 2520 __p = __get_short_pointer(); 2521 __set_short_size(1); 2522 } 2523 traits_type::assign(*__p, __c); 2524 traits_type::assign(*++__p, value_type()); 2525 if (__old_size > 1) 2526 __annotate_shrink(__old_size); 2527 return *this; 2528} 2529 2530template <class _CharT, class _Traits, class _Allocator> 2531_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string<_CharT, _Traits, _Allocator>& 2532basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { 2533 if (this != std::addressof(__str)) { 2534 __copy_assign_alloc(__str); 2535 if (!__is_long()) { 2536 if (!__str.__is_long()) { 2537 size_type __old_size = __get_short_size(); 2538 if (__get_short_size() < __str.__get_short_size()) 2539 __annotate_increase(__str.__get_short_size() - __get_short_size()); 2540 __r_.first() = __str.__r_.first(); 2541 if (__old_size > __get_short_size()) 2542 __annotate_shrink(__old_size); 2543 } else { 2544 return __assign_no_alias<true>(__str.data(), __str.size()); 2545 } 2546 } else { 2547 return __assign_no_alias<false>(__str.data(), __str.size()); 2548 } 2549 } 2550 return *this; 2551} 2552 2553#ifndef _LIBCPP_CXX03_LANG 2554 2555template <class _CharT, class _Traits, class _Allocator> 2556inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void 2557basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type) 2558 _NOEXCEPT_(__alloc_traits::is_always_equal::value) { 2559 if (__alloc() != __str.__alloc()) 2560 assign(__str); 2561 else 2562 __move_assign(__str, true_type()); 2563} 2564 2565template <class _CharT, class _Traits, class _Allocator> 2566inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void 2567basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) 2568# if _LIBCPP_STD_VER >= 17 2569 _NOEXCEPT 2570# else 2571 _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) 2572# endif 2573{ 2574 __annotate_delete(); 2575 if (__is_long()) { 2576 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); 2577# if _LIBCPP_STD_VER <= 14 2578 if (!is_nothrow_move_assignable<allocator_type>::value) { 2579 __set_short_size(0); 2580 traits_type::assign(__get_short_pointer()[0], value_type()); 2581 __annotate_new(0); 2582 } 2583# endif 2584 } 2585 size_type __str_old_size = __str.size(); 2586 bool __str_was_short = !__str.__is_long(); 2587 2588 __move_assign_alloc(__str); 2589 __r_.first() = __str.__r_.first(); 2590 __str.__set_short_size(0); 2591 traits_type::assign(__str.__get_short_pointer()[0], value_type()); 2592 2593 if (__str_was_short && this != &__str) 2594 __str.__annotate_shrink(__str_old_size); 2595 else 2596 // ASan annotations: was long, so object memory is unpoisoned as new. 2597 // Or is same as *this, and __annotate_delete() was called. 2598 __str.__annotate_new(0); 2599 2600 // ASan annotations: Guard against `std::string s; s = std::move(s);` 2601 // You can find more here: https://en.cppreference.com/w/cpp/utility/move 2602 // Quote: "Unless otherwise specified, all standard library objects that have been moved 2603 // from are placed in a "valid but unspecified state", meaning the object's class 2604 // invariants hold (so functions without preconditions, such as the assignment operator, 2605 // can be safely used on the object after it was moved from):" 2606 // Quote: "v = std::move(v); // the value of v is unspecified" 2607 if (!__is_long() && &__str != this) 2608 // If it is long string, delete was never called on original __str's buffer. 2609 __annotate_new(__get_short_size()); 2610} 2611 2612#endif 2613 2614template <class _CharT, class _Traits, class _Allocator> 2615template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > 2616_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2617basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { 2618 __assign_with_sentinel(__first, __last); 2619 return *this; 2620} 2621 2622template <class _CharT, class _Traits, class _Allocator> 2623template <class _InputIterator, class _Sentinel> 2624_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 2625basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator __first, _Sentinel __last) { 2626 const basic_string __temp(__init_with_sentinel_tag(), std::move(__first), std::move(__last), __alloc()); 2627 assign(__temp.data(), __temp.size()); 2628} 2629 2630template <class _CharT, class _Traits, class _Allocator> 2631template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 2632_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2633basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { 2634 if (__string_is_trivial_iterator<_ForwardIterator>::value) { 2635 size_type __n = static_cast<size_type>(std::distance(__first, __last)); 2636 __assign_trivial(__first, __last, __n); 2637 } else { 2638 __assign_with_sentinel(__first, __last); 2639 } 2640 2641 return *this; 2642} 2643 2644template <class _CharT, class _Traits, class _Allocator> 2645template <class _Iterator, class _Sentinel> 2646_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void 2647basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) { 2648 _LIBCPP_ASSERT_INTERNAL( 2649 __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial"); 2650 2651 size_type __old_size = size(); 2652 size_type __cap = capacity(); 2653 if (__cap < __n) { 2654 // Unlike `append` functions, if the input range points into the string itself, there is no case that the input 2655 // range could get invalidated by reallocation: 2656 // 1. If the input range is a subset of the string itself, its size cannot exceed the capacity of the string, 2657 // thus no reallocation would happen. 2658 // 2. In the exotic case where the input range is the byte representation of the string itself, the string 2659 // object itself stays valid even if reallocation happens. 2660 size_type __sz = size(); 2661 __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); 2662 __annotate_increase(__n); 2663 } else if (__n > __old_size) 2664 __annotate_increase(__n - __old_size); 2665 pointer __p = __get_pointer(); 2666 for (; __first != __last; ++__p, (void)++__first) 2667 traits_type::assign(*__p, *__first); 2668 traits_type::assign(*__p, value_type()); 2669 __set_size(__n); 2670 if (__n < __old_size) 2671 __annotate_shrink(__old_size); 2672} 2673 2674template <class _CharT, class _Traits, class _Allocator> 2675_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2676basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n) { 2677 size_type __sz = __str.size(); 2678 if (__pos > __sz) 2679 __throw_out_of_range(); 2680 return assign(__str.data() + __pos, std::min(__n, __sz - __pos)); 2681} 2682 2683template <class _CharT, class _Traits, class _Allocator> 2684template <class _Tp, 2685 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 2686 !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, 2687 int> > 2688_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2689basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) { 2690 __self_view __sv = __t; 2691 size_type __sz = __sv.size(); 2692 if (__pos > __sz) 2693 __throw_out_of_range(); 2694 return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); 2695} 2696 2697template <class _CharT, class _Traits, class _Allocator> 2698_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& 2699basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { 2700 return __assign_external(__s, traits_type::length(__s)); 2701} 2702 2703template <class _CharT, class _Traits, class _Allocator> 2704_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2705basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { 2706 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr"); 2707 return __builtin_constant_p(*__s) 2708 ? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s)) 2709 : __assign_external(__s, traits_type::length(__s))) 2710 : __assign_external(__s); 2711} 2712// append 2713 2714template <class _CharT, class _Traits, class _Allocator> 2715_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2716basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { 2717 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::append received nullptr"); 2718 size_type __cap = capacity(); 2719 size_type __sz = size(); 2720 if (__cap - __sz >= __n) { 2721 if (__n) { 2722 __annotate_increase(__n); 2723 value_type* __p = std::__to_address(__get_pointer()); 2724 traits_type::copy(__p + __sz, __s, __n); 2725 __sz += __n; 2726 __set_size(__sz); 2727 traits_type::assign(__p[__sz], value_type()); 2728 } 2729 } else 2730 __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s); 2731 return *this; 2732} 2733 2734template <class _CharT, class _Traits, class _Allocator> 2735_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2736basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) { 2737 if (__n) { 2738 size_type __cap = capacity(); 2739 size_type __sz = size(); 2740 if (__cap - __sz < __n) 2741 __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); 2742 __annotate_increase(__n); 2743 pointer __p = __get_pointer(); 2744 traits_type::assign(std::__to_address(__p) + __sz, __n, __c); 2745 __sz += __n; 2746 __set_size(__sz); 2747 traits_type::assign(__p[__sz], value_type()); 2748 } 2749 return *this; 2750} 2751 2752template <class _CharT, class _Traits, class _Allocator> 2753_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void 2754basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) { 2755 if (__n) { 2756 size_type __cap = capacity(); 2757 size_type __sz = size(); 2758 if (__cap - __sz < __n) 2759 __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); 2760 __annotate_increase(__n); 2761 pointer __p = __get_pointer(); 2762 __sz += __n; 2763 __set_size(__sz); 2764 traits_type::assign(__p[__sz], value_type()); 2765 } 2766} 2767 2768template <class _CharT, class _Traits, class _Allocator> 2769_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) { 2770 bool __is_short = !__is_long(); 2771 size_type __cap; 2772 size_type __sz; 2773 if (__is_short) { 2774 __cap = __min_cap - 1; 2775 __sz = __get_short_size(); 2776 } else { 2777 __cap = __get_long_cap() - 1; 2778 __sz = __get_long_size(); 2779 } 2780 if (__sz == __cap) { 2781 __grow_by_without_replace(__cap, 1, __sz, __sz, 0); 2782 __annotate_increase(1); 2783 __is_short = false; // the string is always long after __grow_by 2784 } else 2785 __annotate_increase(1); 2786 pointer __p = __get_pointer(); 2787 if (__is_short) { 2788 __p = __get_short_pointer() + __sz; 2789 __set_short_size(__sz + 1); 2790 } else { 2791 __p = __get_long_pointer() + __sz; 2792 __set_long_size(__sz + 1); 2793 } 2794 traits_type::assign(*__p, __c); 2795 traits_type::assign(*++__p, value_type()); 2796} 2797 2798template <class _CharT, class _Traits, class _Allocator> 2799template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 2800_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2801basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _ForwardIterator __last) { 2802 size_type __sz = size(); 2803 size_type __cap = capacity(); 2804 size_type __n = static_cast<size_type>(std::distance(__first, __last)); 2805 if (__n) { 2806 if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { 2807 if (__cap - __sz < __n) 2808 __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); 2809 __annotate_increase(__n); 2810 pointer __p = __get_pointer() + __sz; 2811 for (; __first != __last; ++__p, (void)++__first) 2812 traits_type::assign(*__p, *__first); 2813 traits_type::assign(*__p, value_type()); 2814 __set_size(__sz + __n); 2815 } else { 2816 const basic_string __temp(__first, __last, __alloc()); 2817 append(__temp.data(), __temp.size()); 2818 } 2819 } 2820 return *this; 2821} 2822 2823template <class _CharT, class _Traits, class _Allocator> 2824_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2825basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) { 2826 size_type __sz = __str.size(); 2827 if (__pos > __sz) 2828 __throw_out_of_range(); 2829 return append(__str.data() + __pos, std::min(__n, __sz - __pos)); 2830} 2831 2832template <class _CharT, class _Traits, class _Allocator> 2833template <class _Tp, 2834 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 2835 !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, 2836 int> > 2837_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2838basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) { 2839 __self_view __sv = __t; 2840 size_type __sz = __sv.size(); 2841 if (__pos > __sz) 2842 __throw_out_of_range(); 2843 return append(__sv.data() + __pos, std::min(__n, __sz - __pos)); 2844} 2845 2846template <class _CharT, class _Traits, class _Allocator> 2847_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2848basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { 2849 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::append received nullptr"); 2850 return append(__s, traits_type::length(__s)); 2851} 2852 2853// insert 2854 2855template <class _CharT, class _Traits, class _Allocator> 2856_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2857basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { 2858 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::insert received nullptr"); 2859 size_type __sz = size(); 2860 if (__pos > __sz) 2861 __throw_out_of_range(); 2862 size_type __cap = capacity(); 2863 if (__cap - __sz >= __n) { 2864 if (__n) { 2865 __annotate_increase(__n); 2866 value_type* __p = std::__to_address(__get_pointer()); 2867 size_type __n_move = __sz - __pos; 2868 if (__n_move != 0) { 2869 if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s)) 2870 __s += __n; 2871 traits_type::move(__p + __pos + __n, __p + __pos, __n_move); 2872 } 2873 traits_type::move(__p + __pos, __s, __n); 2874 __sz += __n; 2875 __set_size(__sz); 2876 traits_type::assign(__p[__sz], value_type()); 2877 } 2878 } else 2879 __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s); 2880 return *this; 2881} 2882 2883template <class _CharT, class _Traits, class _Allocator> 2884_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2885basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c) { 2886 size_type __sz = size(); 2887 if (__pos > __sz) 2888 __throw_out_of_range(); 2889 if (__n) { 2890 size_type __cap = capacity(); 2891 value_type* __p; 2892 if (__cap - __sz >= __n) { 2893 __annotate_increase(__n); 2894 __p = std::__to_address(__get_pointer()); 2895 size_type __n_move = __sz - __pos; 2896 if (__n_move != 0) 2897 traits_type::move(__p + __pos + __n, __p + __pos, __n_move); 2898 } else { 2899 __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); 2900 __p = std::__to_address(__get_long_pointer()); 2901 } 2902 traits_type::assign(__p + __pos, __n, __c); 2903 __sz += __n; 2904 __set_size(__sz); 2905 traits_type::assign(__p[__sz], value_type()); 2906 } 2907 return *this; 2908} 2909 2910template <class _CharT, class _Traits, class _Allocator> 2911template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > 2912_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 2913basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { 2914 const basic_string __temp(__first, __last, __alloc()); 2915 return insert(__pos, __temp.data(), __temp.data() + __temp.size()); 2916} 2917 2918template <class _CharT, class _Traits, class _Allocator> 2919template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 2920_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 2921basic_string<_CharT, _Traits, _Allocator>::insert( 2922 const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { 2923 auto __n = static_cast<size_type>(std::distance(__first, __last)); 2924 return __insert_with_size(__pos, __first, __last, __n); 2925} 2926 2927template <class _CharT, class _Traits, class _Allocator> 2928template <class _Iterator, class _Sentinel> 2929_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 2930basic_string<_CharT, _Traits, _Allocator>::__insert_with_size( 2931 const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n) { 2932 size_type __ip = static_cast<size_type>(__pos - begin()); 2933 if (__n == 0) 2934 return begin() + __ip; 2935 2936 if (__string_is_trivial_iterator<_Iterator>::value && !__addr_in_range(*__first)) { 2937 return __insert_from_safe_copy(__n, __ip, __first, __last); 2938 } else { 2939 const basic_string __temp(__init_with_sentinel_tag(), __first, __last, __alloc()); 2940 return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end()); 2941 } 2942} 2943 2944template <class _CharT, class _Traits, class _Allocator> 2945_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2946basic_string<_CharT, _Traits, _Allocator>::insert( 2947 size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n) { 2948 size_type __str_sz = __str.size(); 2949 if (__pos2 > __str_sz) 2950 __throw_out_of_range(); 2951 return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2)); 2952} 2953 2954template <class _CharT, class _Traits, class _Allocator> 2955template <class _Tp, 2956 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 2957 !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, 2958 int> > 2959_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2960basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { 2961 __self_view __sv = __t; 2962 size_type __str_sz = __sv.size(); 2963 if (__pos2 > __str_sz) 2964 __throw_out_of_range(); 2965 return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2)); 2966} 2967 2968template <class _CharT, class _Traits, class _Allocator> 2969_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 2970basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { 2971 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::insert received nullptr"); 2972 return insert(__pos, __s, traits_type::length(__s)); 2973} 2974 2975template <class _CharT, class _Traits, class _Allocator> 2976_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 2977basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c) { 2978 size_type __ip = static_cast<size_type>(__pos - begin()); 2979 size_type __sz = size(); 2980 size_type __cap = capacity(); 2981 value_type* __p; 2982 if (__cap == __sz) { 2983 __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1); 2984 __p = std::__to_address(__get_long_pointer()); 2985 } else { 2986 __annotate_increase(1); 2987 __p = std::__to_address(__get_pointer()); 2988 size_type __n_move = __sz - __ip; 2989 if (__n_move != 0) 2990 traits_type::move(__p + __ip + 1, __p + __ip, __n_move); 2991 } 2992 traits_type::assign(__p[__ip], __c); 2993 traits_type::assign(__p[++__sz], value_type()); 2994 __set_size(__sz); 2995 return begin() + static_cast<difference_type>(__ip); 2996} 2997 2998// replace 2999 3000template <class _CharT, class _Traits, class _Allocator> 3001_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3002basic_string<_CharT, _Traits, _Allocator>::replace( 3003 size_type __pos, size_type __n1, const value_type* __s, size_type __n2) 3004 _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { 3005 _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); 3006 size_type __sz = size(); 3007 if (__pos > __sz) 3008 __throw_out_of_range(); 3009 __n1 = std::min(__n1, __sz - __pos); 3010 size_type __cap = capacity(); 3011 if (__cap - __sz + __n1 >= __n2) { 3012 value_type* __p = std::__to_address(__get_pointer()); 3013 if (__n1 != __n2) { 3014 if (__n2 > __n1) 3015 __annotate_increase(__n2 - __n1); 3016 size_type __n_move = __sz - __pos - __n1; 3017 if (__n_move != 0) { 3018 if (__n1 > __n2) { 3019 traits_type::move(__p + __pos, __s, __n2); 3020 traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); 3021 return __null_terminate_at(__p, __sz + (__n2 - __n1)); 3022 } 3023 if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) { 3024 if (__p + __pos + __n1 <= __s) 3025 __s += __n2 - __n1; 3026 else // __p + __pos < __s < __p + __pos + __n1 3027 { 3028 traits_type::move(__p + __pos, __s, __n1); 3029 __pos += __n1; 3030 __s += __n2; 3031 __n2 -= __n1; 3032 __n1 = 0; 3033 } 3034 } 3035 traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); 3036 } 3037 } 3038 traits_type::move(__p + __pos, __s, __n2); 3039 return __null_terminate_at(__p, __sz + (__n2 - __n1)); 3040 } else 3041 __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s); 3042 return *this; 3043} 3044 3045template <class _CharT, class _Traits, class _Allocator> 3046_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3047basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c) { 3048 size_type __sz = size(); 3049 if (__pos > __sz) 3050 __throw_out_of_range(); 3051 __n1 = std::min(__n1, __sz - __pos); 3052 size_type __cap = capacity(); 3053 value_type* __p; 3054 if (__cap - __sz + __n1 >= __n2) { 3055 __p = std::__to_address(__get_pointer()); 3056 if (__n1 != __n2) { 3057 if (__n2 > __n1) 3058 __annotate_increase(__n2 - __n1); 3059 size_type __n_move = __sz - __pos - __n1; 3060 if (__n_move != 0) 3061 traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); 3062 } 3063 } else { 3064 __grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); 3065 __p = std::__to_address(__get_long_pointer()); 3066 } 3067 traits_type::assign(__p + __pos, __n2, __c); 3068 return __null_terminate_at(__p, __sz - (__n1 - __n2)); 3069} 3070 3071template <class _CharT, class _Traits, class _Allocator> 3072template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > 3073_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3074basic_string<_CharT, _Traits, _Allocator>::replace( 3075 const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { 3076 const basic_string __temp(__j1, __j2, __alloc()); 3077 return replace(__i1, __i2, __temp); 3078} 3079 3080template <class _CharT, class _Traits, class _Allocator> 3081_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3082basic_string<_CharT, _Traits, _Allocator>::replace( 3083 size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) { 3084 size_type __str_sz = __str.size(); 3085 if (__pos2 > __str_sz) 3086 __throw_out_of_range(); 3087 return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2)); 3088} 3089 3090template <class _CharT, class _Traits, class _Allocator> 3091template <class _Tp, 3092 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 3093 !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, 3094 int> > 3095_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3096basic_string<_CharT, _Traits, _Allocator>::replace( 3097 size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { 3098 __self_view __sv = __t; 3099 size_type __str_sz = __sv.size(); 3100 if (__pos2 > __str_sz) 3101 __throw_out_of_range(); 3102 return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2)); 3103} 3104 3105template <class _CharT, class _Traits, class _Allocator> 3106_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3107basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { 3108 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::replace received nullptr"); 3109 return replace(__pos, __n1, __s, traits_type::length(__s)); 3110} 3111 3112// erase 3113 3114// 'externally instantiated' erase() implementation, called when __n != npos. 3115// Does not check __pos against size() 3116template <class _CharT, class _Traits, class _Allocator> 3117_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void 3118basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(size_type __pos, size_type __n) { 3119 if (__n) { 3120 size_type __sz = size(); 3121 value_type* __p = std::__to_address(__get_pointer()); 3122 __n = std::min(__n, __sz - __pos); 3123 size_type __n_move = __sz - __pos - __n; 3124 if (__n_move != 0) 3125 traits_type::move(__p + __pos, __p + __pos + __n, __n_move); 3126 __null_terminate_at(__p, __sz - __n); 3127 } 3128} 3129 3130template <class _CharT, class _Traits, class _Allocator> 3131_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& 3132basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) { 3133 if (__pos > size()) 3134 __throw_out_of_range(); 3135 if (__n == npos) { 3136 __erase_to_end(__pos); 3137 } else { 3138 __erase_external_with_move(__pos, __n); 3139 } 3140 return *this; 3141} 3142 3143template <class _CharT, class _Traits, class _Allocator> 3144inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 3145basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { 3146 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 3147 __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); 3148 iterator __b = begin(); 3149 size_type __r = static_cast<size_type>(__pos - __b); 3150 erase(__r, 1); 3151 return __b + static_cast<difference_type>(__r); 3152} 3153 3154template <class _CharT, class _Traits, class _Allocator> 3155inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator 3156basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { 3157 _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range"); 3158 iterator __b = begin(); 3159 size_type __r = static_cast<size_type>(__first - __b); 3160 erase(__r, static_cast<size_type>(__last - __first)); 3161 return __b + static_cast<difference_type>(__r); 3162} 3163 3164template <class _CharT, class _Traits, class _Allocator> 3165inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() { 3166 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty"); 3167 __erase_to_end(size() - 1); 3168} 3169 3170template <class _CharT, class _Traits, class _Allocator> 3171inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { 3172 size_type __old_size = size(); 3173 if (__is_long()) { 3174 traits_type::assign(*__get_long_pointer(), value_type()); 3175 __set_long_size(0); 3176 } else { 3177 traits_type::assign(*__get_short_pointer(), value_type()); 3178 __set_short_size(0); 3179 } 3180 __annotate_shrink(__old_size); 3181} 3182 3183template <class _CharT, class _Traits, class _Allocator> 3184_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c) { 3185 size_type __sz = size(); 3186 if (__n > __sz) 3187 append(__n - __sz, __c); 3188 else 3189 __erase_to_end(__n); 3190} 3191 3192template <class _CharT, class _Traits, class _Allocator> 3193_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void 3194basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n) { 3195 size_type __sz = size(); 3196 if (__n > __sz) { 3197 __append_default_init(__n - __sz); 3198 } else 3199 __erase_to_end(__n); 3200} 3201 3202template <class _CharT, class _Traits, class _Allocator> 3203_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity) { 3204 if (__requested_capacity > max_size()) 3205 __throw_length_error(); 3206 3207 // Make sure reserve(n) never shrinks. This is technically only required in C++20 3208 // and later (since P0966R1), however we provide consistent behavior in all Standard 3209 // modes because this function is instantiated in the shared library. 3210 if (__requested_capacity <= capacity()) 3211 return; 3212 3213 size_type __target_capacity = std::max(__requested_capacity, size()); 3214 __target_capacity = __recommend(__target_capacity); 3215 if (__target_capacity == capacity()) 3216 return; 3217 3218 __shrink_or_extend(__target_capacity); 3219} 3220 3221template <class _CharT, class _Traits, class _Allocator> 3222inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT { 3223 size_type __target_capacity = __recommend(size()); 3224 if (__target_capacity == capacity()) 3225 return; 3226 3227 __shrink_or_extend(__target_capacity); 3228} 3229 3230template <class _CharT, class _Traits, class _Allocator> 3231inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void 3232basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) { 3233 __annotate_delete(); 3234 size_type __cap = capacity(); 3235 size_type __sz = size(); 3236 3237 pointer __new_data, __p; 3238 bool __was_long, __now_long; 3239 if (__fits_in_sso(__target_capacity)) { 3240 __was_long = true; 3241 __now_long = false; 3242 __new_data = __get_short_pointer(); 3243 __p = __get_long_pointer(); 3244 } else { 3245 if (__target_capacity > __cap) { 3246 auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); 3247 __new_data = __allocation.ptr; 3248 __target_capacity = __allocation.count - 1; 3249 } else { 3250#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 3251 try { 3252#endif // _LIBCPP_HAS_NO_EXCEPTIONS 3253 auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); 3254 __new_data = __allocation.ptr; 3255 __target_capacity = __allocation.count - 1; 3256#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 3257 } catch (...) { 3258 return; 3259 } 3260#else // _LIBCPP_HAS_NO_EXCEPTIONS 3261 if (__new_data == nullptr) 3262 return; 3263#endif // _LIBCPP_HAS_NO_EXCEPTIONS 3264 } 3265 __begin_lifetime(__new_data, __target_capacity + 1); 3266 __now_long = true; 3267 __was_long = __is_long(); 3268 __p = __get_pointer(); 3269 } 3270 traits_type::copy(std::__to_address(__new_data), std::__to_address(__p), size() + 1); 3271 if (__was_long) 3272 __alloc_traits::deallocate(__alloc(), __p, __cap + 1); 3273 if (__now_long) { 3274 __set_long_cap(__target_capacity + 1); 3275 __set_long_size(__sz); 3276 __set_long_pointer(__new_data); 3277 } else 3278 __set_short_size(__sz); 3279 __annotate_new(__sz); 3280} 3281 3282template <class _CharT, class _Traits, class _Allocator> 3283_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::const_reference 3284basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const { 3285 if (__n >= size()) 3286 __throw_out_of_range(); 3287 return (*this)[__n]; 3288} 3289 3290template <class _CharT, class _Traits, class _Allocator> 3291_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::reference 3292basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) { 3293 if (__n >= size()) 3294 __throw_out_of_range(); 3295 return (*this)[__n]; 3296} 3297 3298template <class _CharT, class _Traits, class _Allocator> 3299_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3300basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const { 3301 size_type __sz = size(); 3302 if (__pos > __sz) 3303 __throw_out_of_range(); 3304 size_type __rlen = std::min(__n, __sz - __pos); 3305 traits_type::copy(__s, data() + __pos, __rlen); 3306 return __rlen; 3307} 3308 3309template <class _CharT, class _Traits, class _Allocator> 3310inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) 3311#if _LIBCPP_STD_VER >= 14 3312 _NOEXCEPT 3313#else 3314 _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value) 3315#endif 3316{ 3317 _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( 3318 __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value || 3319 __alloc() == __str.__alloc(), 3320 "swapping non-equal allocators"); 3321 if (!__is_long()) 3322 __annotate_delete(); 3323 if (this != &__str && !__str.__is_long()) 3324 __str.__annotate_delete(); 3325 std::swap(__r_.first(), __str.__r_.first()); 3326 std::__swap_allocator(__alloc(), __str.__alloc()); 3327 if (!__is_long()) 3328 __annotate_new(__get_short_size()); 3329 if (this != &__str && !__str.__is_long()) 3330 __str.__annotate_new(__str.__get_short_size()); 3331} 3332 3333// find 3334 3335template <class _Traits> 3336struct _LIBCPP_HIDDEN __traits_eq { 3337 typedef typename _Traits::char_type char_type; 3338 _LIBCPP_HIDE_FROM_ABI bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT { 3339 return _Traits::eq(__x, __y); 3340 } 3341}; 3342 3343template <class _CharT, class _Traits, class _Allocator> 3344_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3345basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3346 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr"); 3347 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3348} 3349 3350template <class _CharT, class _Traits, class _Allocator> 3351inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3352basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT { 3353 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __str.data(), __pos, __str.size()); 3354} 3355 3356template <class _CharT, class _Traits, class _Allocator> 3357template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3358_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3359basic_string<_CharT, _Traits, _Allocator>::find(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3360 __self_view __sv = __t; 3361 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size()); 3362} 3363 3364template <class _CharT, class _Traits, class _Allocator> 3365inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3366basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { 3367 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find(): received nullptr"); 3368 return std::__str_find<value_type, size_type, traits_type, npos>( 3369 data(), size(), __s, __pos, traits_type::length(__s)); 3370} 3371 3372template <class _CharT, class _Traits, class _Allocator> 3373_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3374basic_string<_CharT, _Traits, _Allocator>::find(value_type __c, size_type __pos) const _NOEXCEPT { 3375 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); 3376} 3377 3378// rfind 3379 3380template <class _CharT, class _Traits, class _Allocator> 3381_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3382basic_string<_CharT, _Traits, _Allocator>::rfind( 3383 const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3384 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); 3385 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3386} 3387 3388template <class _CharT, class _Traits, class _Allocator> 3389inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3390basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT { 3391 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __str.data(), __pos, __str.size()); 3392} 3393 3394template <class _CharT, class _Traits, class _Allocator> 3395template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3396_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3397basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3398 __self_view __sv = __t; 3399 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size()); 3400} 3401 3402template <class _CharT, class _Traits, class _Allocator> 3403inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3404basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { 3405 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::rfind(): received nullptr"); 3406 return std::__str_rfind<value_type, size_type, traits_type, npos>( 3407 data(), size(), __s, __pos, traits_type::length(__s)); 3408} 3409 3410template <class _CharT, class _Traits, class _Allocator> 3411_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3412basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c, size_type __pos) const _NOEXCEPT { 3413 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); 3414} 3415 3416// find_first_of 3417 3418template <class _CharT, class _Traits, class _Allocator> 3419_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3420basic_string<_CharT, _Traits, _Allocator>::find_first_of( 3421 const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3422 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); 3423 return std::__str_find_first_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3424} 3425 3426template <class _CharT, class _Traits, class _Allocator> 3427inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3428basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { 3429 return std::__str_find_first_of<value_type, size_type, traits_type, npos>( 3430 data(), size(), __str.data(), __pos, __str.size()); 3431} 3432 3433template <class _CharT, class _Traits, class _Allocator> 3434template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3435_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3436basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3437 __self_view __sv = __t; 3438 return std::__str_find_first_of<value_type, size_type, traits_type, npos>( 3439 data(), size(), __sv.data(), __pos, __sv.size()); 3440} 3441 3442template <class _CharT, class _Traits, class _Allocator> 3443inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3444basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { 3445 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_of(): received nullptr"); 3446 return std::__str_find_first_of<value_type, size_type, traits_type, npos>( 3447 data(), size(), __s, __pos, traits_type::length(__s)); 3448} 3449 3450template <class _CharT, class _Traits, class _Allocator> 3451inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3452basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c, size_type __pos) const _NOEXCEPT { 3453 return find(__c, __pos); 3454} 3455 3456// find_last_of 3457 3458template <class _CharT, class _Traits, class _Allocator> 3459inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3460basic_string<_CharT, _Traits, _Allocator>::find_last_of( 3461 const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3462 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); 3463 return std::__str_find_last_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3464} 3465 3466template <class _CharT, class _Traits, class _Allocator> 3467inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3468basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { 3469 return std::__str_find_last_of<value_type, size_type, traits_type, npos>( 3470 data(), size(), __str.data(), __pos, __str.size()); 3471} 3472 3473template <class _CharT, class _Traits, class _Allocator> 3474template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3475_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3476basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3477 __self_view __sv = __t; 3478 return std::__str_find_last_of<value_type, size_type, traits_type, npos>( 3479 data(), size(), __sv.data(), __pos, __sv.size()); 3480} 3481 3482template <class _CharT, class _Traits, class _Allocator> 3483inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3484basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { 3485 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_of(): received nullptr"); 3486 return std::__str_find_last_of<value_type, size_type, traits_type, npos>( 3487 data(), size(), __s, __pos, traits_type::length(__s)); 3488} 3489 3490template <class _CharT, class _Traits, class _Allocator> 3491inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3492basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c, size_type __pos) const _NOEXCEPT { 3493 return rfind(__c, __pos); 3494} 3495 3496// find_first_not_of 3497 3498template <class _CharT, class _Traits, class _Allocator> 3499_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3500basic_string<_CharT, _Traits, _Allocator>::find_first_not_of( 3501 const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3502 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); 3503 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3504} 3505 3506template <class _CharT, class _Traits, class _Allocator> 3507inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3508basic_string<_CharT, _Traits, _Allocator>::find_first_not_of( 3509 const basic_string& __str, size_type __pos) const _NOEXCEPT { 3510 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( 3511 data(), size(), __str.data(), __pos, __str.size()); 3512} 3513 3514template <class _CharT, class _Traits, class _Allocator> 3515template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3516_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3517basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3518 __self_view __sv = __t; 3519 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( 3520 data(), size(), __sv.data(), __pos, __sv.size()); 3521} 3522 3523template <class _CharT, class _Traits, class _Allocator> 3524inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3525basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { 3526 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_not_of(): received nullptr"); 3527 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( 3528 data(), size(), __s, __pos, traits_type::length(__s)); 3529} 3530 3531template <class _CharT, class _Traits, class _Allocator> 3532inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3533basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT { 3534 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); 3535} 3536 3537// find_last_not_of 3538 3539template <class _CharT, class _Traits, class _Allocator> 3540_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3541basic_string<_CharT, _Traits, _Allocator>::find_last_not_of( 3542 const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { 3543 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); 3544 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); 3545} 3546 3547template <class _CharT, class _Traits, class _Allocator> 3548inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3549basic_string<_CharT, _Traits, _Allocator>::find_last_not_of( 3550 const basic_string& __str, size_type __pos) const _NOEXCEPT { 3551 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( 3552 data(), size(), __str.data(), __pos, __str.size()); 3553} 3554 3555template <class _CharT, class _Traits, class _Allocator> 3556template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3557_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3558basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { 3559 __self_view __sv = __t; 3560 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( 3561 data(), size(), __sv.data(), __pos, __sv.size()); 3562} 3563 3564template <class _CharT, class _Traits, class _Allocator> 3565inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3566basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { 3567 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_not_of(): received nullptr"); 3568 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( 3569 data(), size(), __s, __pos, traits_type::length(__s)); 3570} 3571 3572template <class _CharT, class _Traits, class _Allocator> 3573inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type 3574basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT { 3575 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); 3576} 3577 3578// compare 3579 3580template <class _CharT, class _Traits, class _Allocator> 3581template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3582_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { 3583 __self_view __sv = __t; 3584 size_t __lhs_sz = size(); 3585 size_t __rhs_sz = __sv.size(); 3586 int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz)); 3587 if (__result != 0) 3588 return __result; 3589 if (__lhs_sz < __rhs_sz) 3590 return -1; 3591 if (__lhs_sz > __rhs_sz) 3592 return 1; 3593 return 0; 3594} 3595 3596template <class _CharT, class _Traits, class _Allocator> 3597inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int 3598basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT { 3599 return compare(__self_view(__str)); 3600} 3601 3602template <class _CharT, class _Traits, class _Allocator> 3603inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( 3604 size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const { 3605 _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); 3606 size_type __sz = size(); 3607 if (__pos1 > __sz || __n2 == npos) 3608 __throw_out_of_range(); 3609 size_type __rlen = std::min(__n1, __sz - __pos1); 3610 int __r = traits_type::compare(data() + __pos1, __s, std::min(__rlen, __n2)); 3611 if (__r == 0) { 3612 if (__rlen < __n2) 3613 __r = -1; 3614 else if (__rlen > __n2) 3615 __r = 1; 3616 } 3617 return __r; 3618} 3619 3620template <class _CharT, class _Traits, class _Allocator> 3621template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > 3622_LIBCPP_CONSTEXPR_SINCE_CXX20 int 3623basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const _Tp& __t) const { 3624 __self_view __sv = __t; 3625 return compare(__pos1, __n1, __sv.data(), __sv.size()); 3626} 3627 3628template <class _CharT, class _Traits, class _Allocator> 3629inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int 3630basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str) const { 3631 return compare(__pos1, __n1, __str.data(), __str.size()); 3632} 3633 3634template <class _CharT, class _Traits, class _Allocator> 3635template <class _Tp, 3636 __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && 3637 !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, 3638 int> > 3639_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( 3640 size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const { 3641 __self_view __sv = __t; 3642 return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); 3643} 3644 3645template <class _CharT, class _Traits, class _Allocator> 3646_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( 3647 size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) const { 3648 return compare(__pos1, __n1, __self_view(__str), __pos2, __n2); 3649} 3650 3651template <class _CharT, class _Traits, class _Allocator> 3652_LIBCPP_CONSTEXPR_SINCE_CXX20 int 3653basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { 3654 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); 3655 return compare(0, npos, __s, traits_type::length(__s)); 3656} 3657 3658template <class _CharT, class _Traits, class _Allocator> 3659_LIBCPP_CONSTEXPR_SINCE_CXX20 int 3660basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { 3661 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); 3662 return compare(__pos1, __n1, __s, traits_type::length(__s)); 3663} 3664 3665// __invariants 3666 3667template <class _CharT, class _Traits, class _Allocator> 3668inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const { 3669 if (size() > capacity()) 3670 return false; 3671 if (capacity() < __min_cap - 1) 3672 return false; 3673 if (data() == nullptr) 3674 return false; 3675 if (!_Traits::eq(data()[size()], value_type())) 3676 return false; 3677 return true; 3678} 3679 3680// __clear_and_shrink 3681 3682template <class _CharT, class _Traits, class _Allocator> 3683inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { 3684 clear(); 3685 if (__is_long()) { 3686 __annotate_delete(); 3687 __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); 3688 __r_.first() = __rep(); 3689 } 3690} 3691 3692// operator== 3693 3694template <class _CharT, class _Traits, class _Allocator> 3695inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool 3696operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3697 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3698#if _LIBCPP_STD_VER >= 20 3699 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); 3700#else 3701 size_t __lhs_sz = __lhs.size(); 3702 return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(), __rhs.data(), __lhs_sz) == 0; 3703#endif 3704} 3705 3706template <class _Allocator> 3707inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool 3708operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs, 3709 const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT { 3710 size_t __lhs_sz = __lhs.size(); 3711 if (__lhs_sz != __rhs.size()) 3712 return false; 3713 const char* __lp = __lhs.data(); 3714 const char* __rp = __rhs.data(); 3715 if (__lhs.__is_long()) 3716 return char_traits<char>::compare(__lp, __rp, __lhs_sz) == 0; 3717 for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp) 3718 if (*__lp != *__rp) 3719 return false; 3720 return true; 3721} 3722 3723#if _LIBCPP_STD_VER <= 17 3724template <class _CharT, class _Traits, class _Allocator> 3725inline _LIBCPP_HIDE_FROM_ABI bool 3726operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3727 typedef basic_string<_CharT, _Traits, _Allocator> _String; 3728 _LIBCPP_ASSERT_NON_NULL(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); 3729 size_t __lhs_len = _Traits::length(__lhs); 3730 if (__lhs_len != __rhs.size()) 3731 return false; 3732 return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0; 3733} 3734#endif // _LIBCPP_STD_VER <= 17 3735 3736template <class _CharT, class _Traits, class _Allocator> 3737inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool 3738operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3739#if _LIBCPP_STD_VER >= 20 3740 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); 3741#else 3742 typedef basic_string<_CharT, _Traits, _Allocator> _String; 3743 _LIBCPP_ASSERT_NON_NULL(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); 3744 size_t __rhs_len = _Traits::length(__rhs); 3745 if (__rhs_len != __lhs.size()) 3746 return false; 3747 return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0; 3748#endif 3749} 3750 3751#if _LIBCPP_STD_VER >= 20 3752 3753template <class _CharT, class _Traits, class _Allocator> 3754_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3755 const basic_string<_CharT, _Traits, _Allocator>& __rhs) noexcept { 3756 return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); 3757} 3758 3759template <class _CharT, class _Traits, class _Allocator> 3760_LIBCPP_HIDE_FROM_ABI constexpr auto 3761operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { 3762 return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); 3763} 3764 3765#else // _LIBCPP_STD_VER >= 20 3766 3767template <class _CharT, class _Traits, class _Allocator> 3768inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3769 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3770 return !(__lhs == __rhs); 3771} 3772 3773template <class _CharT, class _Traits, class _Allocator> 3774inline _LIBCPP_HIDE_FROM_ABI bool 3775operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3776 return !(__lhs == __rhs); 3777} 3778 3779template <class _CharT, class _Traits, class _Allocator> 3780inline _LIBCPP_HIDE_FROM_ABI bool 3781operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3782 return !(__lhs == __rhs); 3783} 3784 3785// operator< 3786 3787template <class _CharT, class _Traits, class _Allocator> 3788inline _LIBCPP_HIDE_FROM_ABI bool operator<(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3789 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3790 return __lhs.compare(__rhs) < 0; 3791} 3792 3793template <class _CharT, class _Traits, class _Allocator> 3794inline _LIBCPP_HIDE_FROM_ABI bool 3795operator<(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3796 return __lhs.compare(__rhs) < 0; 3797} 3798 3799template <class _CharT, class _Traits, class _Allocator> 3800inline _LIBCPP_HIDE_FROM_ABI bool 3801operator<(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3802 return __rhs.compare(__lhs) > 0; 3803} 3804 3805// operator> 3806 3807template <class _CharT, class _Traits, class _Allocator> 3808inline _LIBCPP_HIDE_FROM_ABI bool operator>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3809 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3810 return __rhs < __lhs; 3811} 3812 3813template <class _CharT, class _Traits, class _Allocator> 3814inline _LIBCPP_HIDE_FROM_ABI bool 3815operator>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3816 return __rhs < __lhs; 3817} 3818 3819template <class _CharT, class _Traits, class _Allocator> 3820inline _LIBCPP_HIDE_FROM_ABI bool 3821operator>(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3822 return __rhs < __lhs; 3823} 3824 3825// operator<= 3826 3827template <class _CharT, class _Traits, class _Allocator> 3828inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3829 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3830 return !(__rhs < __lhs); 3831} 3832 3833template <class _CharT, class _Traits, class _Allocator> 3834inline _LIBCPP_HIDE_FROM_ABI bool 3835operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3836 return !(__rhs < __lhs); 3837} 3838 3839template <class _CharT, class _Traits, class _Allocator> 3840inline _LIBCPP_HIDE_FROM_ABI bool 3841operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3842 return !(__rhs < __lhs); 3843} 3844 3845// operator>= 3846 3847template <class _CharT, class _Traits, class _Allocator> 3848inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3849 const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3850 return !(__lhs < __rhs); 3851} 3852 3853template <class _CharT, class _Traits, class _Allocator> 3854inline _LIBCPP_HIDE_FROM_ABI bool 3855operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { 3856 return !(__lhs < __rhs); 3857} 3858 3859template <class _CharT, class _Traits, class _Allocator> 3860inline _LIBCPP_HIDE_FROM_ABI bool 3861operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { 3862 return !(__lhs < __rhs); 3863} 3864#endif // _LIBCPP_STD_VER >= 20 3865 3866// operator + 3867 3868template <class _CharT, class _Traits, class _Allocator> 3869_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3870operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, 3871 const basic_string<_CharT, _Traits, _Allocator>& __rhs) { 3872 using _String = basic_string<_CharT, _Traits, _Allocator>; 3873 auto __lhs_sz = __lhs.size(); 3874 auto __rhs_sz = __rhs.size(); 3875 _String __r(__uninitialized_size_tag(), 3876 __lhs_sz + __rhs_sz, 3877 _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); 3878 auto __ptr = std::__to_address(__r.__get_pointer()); 3879 _Traits::copy(__ptr, __lhs.data(), __lhs_sz); 3880 _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); 3881 _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); 3882 return __r; 3883} 3884 3885template <class _CharT, class _Traits, class _Allocator> 3886_LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3887operator+(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { 3888 using _String = basic_string<_CharT, _Traits, _Allocator>; 3889 auto __lhs_sz = _Traits::length(__lhs); 3890 auto __rhs_sz = __rhs.size(); 3891 _String __r(__uninitialized_size_tag(), 3892 __lhs_sz + __rhs_sz, 3893 _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); 3894 auto __ptr = std::__to_address(__r.__get_pointer()); 3895 _Traits::copy(__ptr, __lhs, __lhs_sz); 3896 _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); 3897 _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); 3898 return __r; 3899} 3900 3901template <class _CharT, class _Traits, class _Allocator> 3902_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3903operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { 3904 using _String = basic_string<_CharT, _Traits, _Allocator>; 3905 typename _String::size_type __rhs_sz = __rhs.size(); 3906 _String __r(__uninitialized_size_tag(), 3907 __rhs_sz + 1, 3908 _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); 3909 auto __ptr = std::__to_address(__r.__get_pointer()); 3910 _Traits::assign(__ptr, 1, __lhs); 3911 _Traits::copy(__ptr + 1, __rhs.data(), __rhs_sz); 3912 _Traits::assign(__ptr + 1 + __rhs_sz, 1, _CharT()); 3913 return __r; 3914} 3915 3916template <class _CharT, class _Traits, class _Allocator> 3917inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3918operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { 3919 using _String = basic_string<_CharT, _Traits, _Allocator>; 3920 typename _String::size_type __lhs_sz = __lhs.size(); 3921 typename _String::size_type __rhs_sz = _Traits::length(__rhs); 3922 _String __r(__uninitialized_size_tag(), 3923 __lhs_sz + __rhs_sz, 3924 _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); 3925 auto __ptr = std::__to_address(__r.__get_pointer()); 3926 _Traits::copy(__ptr, __lhs.data(), __lhs_sz); 3927 _Traits::copy(__ptr + __lhs_sz, __rhs, __rhs_sz); 3928 _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); 3929 return __r; 3930} 3931 3932template <class _CharT, class _Traits, class _Allocator> 3933_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3934operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs) { 3935 using _String = basic_string<_CharT, _Traits, _Allocator>; 3936 typename _String::size_type __lhs_sz = __lhs.size(); 3937 _String __r(__uninitialized_size_tag(), 3938 __lhs_sz + 1, 3939 _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); 3940 auto __ptr = std::__to_address(__r.__get_pointer()); 3941 _Traits::copy(__ptr, __lhs.data(), __lhs_sz); 3942 _Traits::assign(__ptr + __lhs_sz, 1, __rhs); 3943 _Traits::assign(__ptr + 1 + __lhs_sz, 1, _CharT()); 3944 return __r; 3945} 3946 3947#ifndef _LIBCPP_CXX03_LANG 3948 3949template <class _CharT, class _Traits, class _Allocator> 3950inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3951operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { 3952 return std::move(__lhs.append(__rhs)); 3953} 3954 3955template <class _CharT, class _Traits, class _Allocator> 3956inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3957operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { 3958 return std::move(__rhs.insert(0, __lhs)); 3959} 3960 3961template <class _CharT, class _Traits, class _Allocator> 3962inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3963operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { 3964 return std::move(__lhs.append(__rhs)); 3965} 3966 3967template <class _CharT, class _Traits, class _Allocator> 3968inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3969operator+(const _CharT* __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { 3970 return std::move(__rhs.insert(0, __lhs)); 3971} 3972 3973template <class _CharT, class _Traits, class _Allocator> 3974inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3975operator+(_CharT __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { 3976 __rhs.insert(__rhs.begin(), __lhs); 3977 return std::move(__rhs); 3978} 3979 3980template <class _CharT, class _Traits, class _Allocator> 3981inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3982operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs) { 3983 return std::move(__lhs.append(__rhs)); 3984} 3985 3986template <class _CharT, class _Traits, class _Allocator> 3987inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> 3988operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) { 3989 __lhs.push_back(__rhs); 3990 return std::move(__lhs); 3991} 3992 3993#endif // _LIBCPP_CXX03_LANG 3994 3995// swap 3996 3997template <class _CharT, class _Traits, class _Allocator> 3998inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 3999swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>& __rhs) 4000 _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs))) { 4001 __lhs.swap(__rhs); 4002} 4003 4004_LIBCPP_EXPORTED_FROM_ABI int stoi(const string& __str, size_t* __idx = nullptr, int __base = 10); 4005_LIBCPP_EXPORTED_FROM_ABI long stol(const string& __str, size_t* __idx = nullptr, int __base = 10); 4006_LIBCPP_EXPORTED_FROM_ABI unsigned long stoul(const string& __str, size_t* __idx = nullptr, int __base = 10); 4007_LIBCPP_EXPORTED_FROM_ABI long long stoll(const string& __str, size_t* __idx = nullptr, int __base = 10); 4008_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10); 4009 4010_LIBCPP_EXPORTED_FROM_ABI float stof(const string& __str, size_t* __idx = nullptr); 4011_LIBCPP_EXPORTED_FROM_ABI double stod(const string& __str, size_t* __idx = nullptr); 4012_LIBCPP_EXPORTED_FROM_ABI long double stold(const string& __str, size_t* __idx = nullptr); 4013 4014_LIBCPP_EXPORTED_FROM_ABI string to_string(int __val); 4015_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned __val); 4016_LIBCPP_EXPORTED_FROM_ABI string to_string(long __val); 4017_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long __val); 4018_LIBCPP_EXPORTED_FROM_ABI string to_string(long long __val); 4019_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long long __val); 4020_LIBCPP_EXPORTED_FROM_ABI string to_string(float __val); 4021_LIBCPP_EXPORTED_FROM_ABI string to_string(double __val); 4022_LIBCPP_EXPORTED_FROM_ABI string to_string(long double __val); 4023 4024#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4025_LIBCPP_EXPORTED_FROM_ABI int stoi(const wstring& __str, size_t* __idx = nullptr, int __base = 10); 4026_LIBCPP_EXPORTED_FROM_ABI long stol(const wstring& __str, size_t* __idx = nullptr, int __base = 10); 4027_LIBCPP_EXPORTED_FROM_ABI unsigned long stoul(const wstring& __str, size_t* __idx = nullptr, int __base = 10); 4028_LIBCPP_EXPORTED_FROM_ABI long long stoll(const wstring& __str, size_t* __idx = nullptr, int __base = 10); 4029_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10); 4030 4031_LIBCPP_EXPORTED_FROM_ABI float stof(const wstring& __str, size_t* __idx = nullptr); 4032_LIBCPP_EXPORTED_FROM_ABI double stod(const wstring& __str, size_t* __idx = nullptr); 4033_LIBCPP_EXPORTED_FROM_ABI long double stold(const wstring& __str, size_t* __idx = nullptr); 4034 4035_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(int __val); 4036_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned __val); 4037_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long __val); 4038_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long __val); 4039_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long long __val); 4040_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long long __val); 4041_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(float __val); 4042_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(double __val); 4043_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long double __val); 4044#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 4045 4046template <class _CharT, class _Traits, class _Allocator> 4047_LIBCPP_TEMPLATE_DATA_VIS const typename basic_string<_CharT, _Traits, _Allocator>::size_type 4048 basic_string<_CharT, _Traits, _Allocator>::npos; 4049 4050template <class _CharT, class _Allocator> 4051struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> { 4052 _LIBCPP_HIDE_FROM_ABI size_t 4053 operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT { 4054 return std::__do_string_hash(__val.data(), __val.data() + __val.size()); 4055 } 4056}; 4057 4058template <class _Allocator> 4059struct hash<basic_string<char, char_traits<char>, _Allocator> > : __string_hash<char, _Allocator> {}; 4060 4061#ifndef _LIBCPP_HAS_NO_CHAR8_T 4062template <class _Allocator> 4063struct hash<basic_string<char8_t, char_traits<char8_t>, _Allocator> > : __string_hash<char8_t, _Allocator> {}; 4064#endif 4065 4066template <class _Allocator> 4067struct hash<basic_string<char16_t, char_traits<char16_t>, _Allocator> > : __string_hash<char16_t, _Allocator> {}; 4068 4069template <class _Allocator> 4070struct hash<basic_string<char32_t, char_traits<char32_t>, _Allocator> > : __string_hash<char32_t, _Allocator> {}; 4071 4072#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4073template <class _Allocator> 4074struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Allocator> > : __string_hash<wchar_t, _Allocator> {}; 4075#endif 4076 4077template <class _CharT, class _Traits, class _Allocator> 4078_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 4079operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str); 4080 4081template <class _CharT, class _Traits, class _Allocator> 4082_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 4083operator>>(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); 4084 4085template <class _CharT, class _Traits, class _Allocator> 4086_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 4087getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); 4088 4089template <class _CharT, class _Traits, class _Allocator> 4090inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 4091getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); 4092 4093template <class _CharT, class _Traits, class _Allocator> 4094inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 4095getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); 4096 4097template <class _CharT, class _Traits, class _Allocator> 4098inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 4099getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str); 4100 4101#if _LIBCPP_STD_VER >= 20 4102template <class _CharT, class _Traits, class _Allocator, class _Up> 4103inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type 4104erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) { 4105 auto __old_size = __str.size(); 4106 __str.erase(std::remove(__str.begin(), __str.end(), __v), __str.end()); 4107 return __old_size - __str.size(); 4108} 4109 4110template <class _CharT, class _Traits, class _Allocator, class _Predicate> 4111inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type 4112erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) { 4113 auto __old_size = __str.size(); 4114 __str.erase(std::remove_if(__str.begin(), __str.end(), __pred), __str.end()); 4115 return __old_size - __str.size(); 4116} 4117#endif 4118 4119#if _LIBCPP_STD_VER >= 14 4120// Literal suffixes for basic_string [basic.string.literals] 4121inline namespace literals { 4122inline namespace string_literals { 4123inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char> 4124operator""s(const char* __str, size_t __len) { 4125 return basic_string<char>(__str, __len); 4126} 4127 4128# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4129inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t> 4130operator""s(const wchar_t* __str, size_t __len) { 4131 return basic_string<wchar_t>(__str, __len); 4132} 4133# endif 4134 4135# ifndef _LIBCPP_HAS_NO_CHAR8_T 4136inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string<char8_t> operator""s(const char8_t* __str, size_t __len) { 4137 return basic_string<char8_t>(__str, __len); 4138} 4139# endif 4140 4141inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t> 4142operator""s(const char16_t* __str, size_t __len) { 4143 return basic_string<char16_t>(__str, __len); 4144} 4145 4146inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char32_t> 4147operator""s(const char32_t* __str, size_t __len) { 4148 return basic_string<char32_t>(__str, __len); 4149} 4150} // namespace string_literals 4151} // namespace literals 4152 4153# if _LIBCPP_STD_VER >= 20 4154template <> 4155inline constexpr bool __format::__enable_insertable<std::basic_string<char>> = true; 4156# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4157template <> 4158inline constexpr bool __format::__enable_insertable<std::basic_string<wchar_t>> = true; 4159# endif 4160# endif 4161 4162#endif 4163 4164_LIBCPP_END_NAMESPACE_STD 4165 4166_LIBCPP_POP_MACROS 4167 4168#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 4169# include <algorithm> 4170# include <concepts> 4171# include <cstdlib> 4172# include <iterator> 4173# include <new> 4174# include <type_traits> 4175# include <typeinfo> 4176# include <utility> 4177#endif 4178 4179#endif // _LIBCPP_STRING 4180