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