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