1// Components for manipulating sequences of characters -*- C++ -*- 2 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 4// 2006, 2007, 2008, 2009 5// Free Software Foundation, Inc. 6// 7// This file is part of the GNU ISO C++ Library. This library is free 8// software; you can redistribute it and/or modify it under the 9// terms of the GNU General Public License as published by the 10// Free Software Foundation; either version 3, or (at your option) 11// any later version. 12 13// This library is distributed in the hope that it will be useful, 14// but WITHOUT ANY WARRANTY; without even the implied warranty of 15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16// GNU General Public License for more details. 17 18// Under Section 7 of GPL version 3, you are granted additional 19// permissions described in the GCC Runtime Library Exception, version 20// 3.1, as published by the Free Software Foundation. 21 22// You should have received a copy of the GNU General Public License and 23// a copy of the GCC Runtime Library Exception along with this program; 24// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25// <http://www.gnu.org/licenses/>. 26 27/** @file basic_string.tcc 28 * This is an internal header file, included by other library headers. 29 * You should not attempt to use it directly. 30 */ 31 32// 33// ISO C++ 14882: 21 Strings library 34// 35 36// Written by Jason Merrill based upon the specification by Takanori Adachi 37// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882. 38 39#ifndef _BASIC_STRING_TCC 40#define _BASIC_STRING_TCC 1 41 42#pragma GCC system_header 43 44#include <cxxabi-forced.h> 45 46_GLIBCXX_BEGIN_NAMESPACE(std) 47 48 template<typename _CharT, typename _Traits, typename _Alloc> 49 const typename basic_string<_CharT, _Traits, _Alloc>::size_type 50 basic_string<_CharT, _Traits, _Alloc>:: 51 _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4; 52 53 template<typename _CharT, typename _Traits, typename _Alloc> 54 const _CharT 55 basic_string<_CharT, _Traits, _Alloc>:: 56 _Rep::_S_terminal = _CharT(); 57 58 template<typename _CharT, typename _Traits, typename _Alloc> 59 const typename basic_string<_CharT, _Traits, _Alloc>::size_type 60 basic_string<_CharT, _Traits, _Alloc>::npos; 61 62 // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string) 63 // at static init time (before static ctors are run). 64 template<typename _CharT, typename _Traits, typename _Alloc> 65 typename basic_string<_CharT, _Traits, _Alloc>::size_type 66 basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[ 67 (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) / 68 sizeof(size_type)]; 69 70 // NB: This is the special case for Input Iterators, used in 71 // istreambuf_iterators, etc. 72 // Input Iterators have a cost structure very different from 73 // pointers, calling for a different coding style. 74 template<typename _CharT, typename _Traits, typename _Alloc> 75 template<typename _InIterator> 76 _CharT* 77 basic_string<_CharT, _Traits, _Alloc>:: 78 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 79 input_iterator_tag) 80 { 81#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 82 if (__beg == __end && __a == _Alloc()) 83 return _S_empty_rep()._M_refdata(); 84#endif 85 // Avoid reallocation for common case. 86 _CharT __buf[128]; 87 size_type __len = 0; 88 while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT)) 89 { 90 __buf[__len++] = *__beg; 91 ++__beg; 92 } 93 _Rep* __r = _Rep::_S_create(__len, size_type(0), __a); 94 _M_copy(__r->_M_refdata(), __buf, __len); 95 __try 96 { 97 while (__beg != __end) 98 { 99 if (__len == __r->_M_capacity) 100 { 101 // Allocate more space. 102 _Rep* __another = _Rep::_S_create(__len + 1, __len, __a); 103 _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len); 104 __r->_M_destroy(__a); 105 __r = __another; 106 } 107 __r->_M_refdata()[__len++] = *__beg; 108 ++__beg; 109 } 110 } 111 __catch(...) 112 { 113 __r->_M_destroy(__a); 114 __throw_exception_again; 115 } 116 __r->_M_set_length_and_sharable(__len); 117 return __r->_M_refdata(); 118 } 119 120 template<typename _CharT, typename _Traits, typename _Alloc> 121 template <typename _InIterator> 122 _CharT* 123 basic_string<_CharT, _Traits, _Alloc>:: 124 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 125 forward_iterator_tag) 126 { 127#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 128 if (__beg == __end && __a == _Alloc()) 129 return _S_empty_rep()._M_refdata(); 130#endif 131 // NB: Not required, but considered best practice. 132 if (__builtin_expect(__gnu_cxx::__is_null_pointer(__beg) 133 && __beg != __end, 0)) 134 __throw_logic_error(__N("basic_string::_S_construct NULL not valid")); 135 136 const size_type __dnew = static_cast<size_type>(std::distance(__beg, 137 __end)); 138 // Check for out_of_range and length_error exceptions. 139 _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a); 140 __try 141 { _S_copy_chars(__r->_M_refdata(), __beg, __end); } 142 __catch(...) 143 { 144 __r->_M_destroy(__a); 145 __throw_exception_again; 146 } 147 __r->_M_set_length_and_sharable(__dnew); 148 return __r->_M_refdata(); 149 } 150 151 template<typename _CharT, typename _Traits, typename _Alloc> 152 _CharT* 153 basic_string<_CharT, _Traits, _Alloc>:: 154 _S_construct(size_type __n, _CharT __c, const _Alloc& __a) 155 { 156#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 157 if (__n == 0 && __a == _Alloc()) 158 return _S_empty_rep()._M_refdata(); 159#endif 160 // Check for out_of_range and length_error exceptions. 161 _Rep* __r = _Rep::_S_create(__n, size_type(0), __a); 162 if (__n) 163 _M_assign(__r->_M_refdata(), __n, __c); 164 165 __r->_M_set_length_and_sharable(__n); 166 return __r->_M_refdata(); 167 } 168 169 template<typename _CharT, typename _Traits, typename _Alloc> 170 basic_string<_CharT, _Traits, _Alloc>:: 171 basic_string(const basic_string& __str) 172 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), 173 __str.get_allocator()), 174 __str.get_allocator()) 175 { } 176 177 template<typename _CharT, typename _Traits, typename _Alloc> 178 basic_string<_CharT, _Traits, _Alloc>:: 179 basic_string(const _Alloc& __a) 180 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) 181 { } 182 183 template<typename _CharT, typename _Traits, typename _Alloc> 184 basic_string<_CharT, _Traits, _Alloc>:: 185 basic_string(const basic_string& __str, size_type __pos, size_type __n) 186 : _M_dataplus(_S_construct(__str._M_data() 187 + __str._M_check(__pos, 188 "basic_string::basic_string"), 189 __str._M_data() + __str._M_limit(__pos, __n) 190 + __pos, _Alloc()), _Alloc()) 191 { } 192 193 template<typename _CharT, typename _Traits, typename _Alloc> 194 basic_string<_CharT, _Traits, _Alloc>:: 195 basic_string(const basic_string& __str, size_type __pos, 196 size_type __n, const _Alloc& __a) 197 : _M_dataplus(_S_construct(__str._M_data() 198 + __str._M_check(__pos, 199 "basic_string::basic_string"), 200 __str._M_data() + __str._M_limit(__pos, __n) 201 + __pos, __a), __a) 202 { } 203 204 // TBD: DPG annotate 205 template<typename _CharT, typename _Traits, typename _Alloc> 206 basic_string<_CharT, _Traits, _Alloc>:: 207 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a) 208 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a) 209 { } 210 211 // TBD: DPG annotate 212 template<typename _CharT, typename _Traits, typename _Alloc> 213 basic_string<_CharT, _Traits, _Alloc>:: 214 basic_string(const _CharT* __s, const _Alloc& __a) 215 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : 216 __s + npos, __a), __a) 217 { } 218 219 template<typename _CharT, typename _Traits, typename _Alloc> 220 basic_string<_CharT, _Traits, _Alloc>:: 221 basic_string(size_type __n, _CharT __c, const _Alloc& __a) 222 : _M_dataplus(_S_construct(__n, __c, __a), __a) 223 { } 224 225 // TBD: DPG annotate 226 template<typename _CharT, typename _Traits, typename _Alloc> 227 template<typename _InputIterator> 228 basic_string<_CharT, _Traits, _Alloc>:: 229 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a) 230 : _M_dataplus(_S_construct(__beg, __end, __a), __a) 231 { } 232 233#ifdef __GXX_EXPERIMENTAL_CXX0X__ 234 template<typename _CharT, typename _Traits, typename _Alloc> 235 basic_string<_CharT, _Traits, _Alloc>:: 236 basic_string(initializer_list<_CharT> __l, const _Alloc& __a) 237 : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a) 238 { } 239#endif 240 241 template<typename _CharT, typename _Traits, typename _Alloc> 242 basic_string<_CharT, _Traits, _Alloc>& 243 basic_string<_CharT, _Traits, _Alloc>:: 244 assign(const basic_string& __str) 245 { 246 if (_M_rep() != __str._M_rep()) 247 { 248 // XXX MT 249 const allocator_type __a = this->get_allocator(); 250 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator()); 251 _M_rep()->_M_dispose(__a); 252 _M_data(__tmp); 253 } 254 return *this; 255 } 256 257 template<typename _CharT, typename _Traits, typename _Alloc> 258 basic_string<_CharT, _Traits, _Alloc>& 259 basic_string<_CharT, _Traits, _Alloc>:: 260 assign(const _CharT* __s, size_type __n) 261 { 262 __glibcxx_requires_string_len(__s, __n); 263 _M_check_length(this->size(), __n, "basic_string::assign"); 264 if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 265 return _M_replace_safe(size_type(0), this->size(), __s, __n); 266 else 267 { 268 // Work in-place. 269 const size_type __pos = __s - _M_data(); 270 if (__pos >= __n) 271 _M_copy(_M_data(), __s, __n); 272 else if (__pos) 273 _M_move(_M_data(), __s, __n); 274 _M_rep()->_M_set_length_and_sharable(__n); 275 return *this; 276 } 277 } 278 279 template<typename _CharT, typename _Traits, typename _Alloc> 280 basic_string<_CharT, _Traits, _Alloc>& 281 basic_string<_CharT, _Traits, _Alloc>:: 282 append(size_type __n, _CharT __c) 283 { 284 if (__n) 285 { 286 _M_check_length(size_type(0), __n, "basic_string::append"); 287 const size_type __len = __n + this->size(); 288 if (__len > this->capacity() || _M_rep()->_M_is_shared()) 289 this->reserve(__len); 290 _M_assign(_M_data() + this->size(), __n, __c); 291 _M_rep()->_M_set_length_and_sharable(__len); 292 } 293 return *this; 294 } 295 296 template<typename _CharT, typename _Traits, typename _Alloc> 297 basic_string<_CharT, _Traits, _Alloc>& 298 basic_string<_CharT, _Traits, _Alloc>:: 299 append(const _CharT* __s, size_type __n) 300 { 301 __glibcxx_requires_string_len(__s, __n); 302 if (__n) 303 { 304 _M_check_length(size_type(0), __n, "basic_string::append"); 305 const size_type __len = __n + this->size(); 306 if (__len > this->capacity() || _M_rep()->_M_is_shared()) 307 { 308 if (_M_disjunct(__s)) 309 this->reserve(__len); 310 else 311 { 312 const size_type __off = __s - _M_data(); 313 this->reserve(__len); 314 __s = _M_data() + __off; 315 } 316 } 317 _M_copy(_M_data() + this->size(), __s, __n); 318 _M_rep()->_M_set_length_and_sharable(__len); 319 } 320 return *this; 321 } 322 323 template<typename _CharT, typename _Traits, typename _Alloc> 324 basic_string<_CharT, _Traits, _Alloc>& 325 basic_string<_CharT, _Traits, _Alloc>:: 326 append(const basic_string& __str) 327 { 328 const size_type __size = __str.size(); 329 if (__size) 330 { 331 const size_type __len = __size + this->size(); 332 if (__len > this->capacity() || _M_rep()->_M_is_shared()) 333 this->reserve(__len); 334 _M_copy(_M_data() + this->size(), __str._M_data(), __size); 335 _M_rep()->_M_set_length_and_sharable(__len); 336 } 337 return *this; 338 } 339 340 template<typename _CharT, typename _Traits, typename _Alloc> 341 basic_string<_CharT, _Traits, _Alloc>& 342 basic_string<_CharT, _Traits, _Alloc>:: 343 append(const basic_string& __str, size_type __pos, size_type __n) 344 { 345 __str._M_check(__pos, "basic_string::append"); 346 __n = __str._M_limit(__pos, __n); 347 if (__n) 348 { 349 const size_type __len = __n + this->size(); 350 if (__len > this->capacity() || _M_rep()->_M_is_shared()) 351 this->reserve(__len); 352 _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n); 353 _M_rep()->_M_set_length_and_sharable(__len); 354 } 355 return *this; 356 } 357 358 template<typename _CharT, typename _Traits, typename _Alloc> 359 basic_string<_CharT, _Traits, _Alloc>& 360 basic_string<_CharT, _Traits, _Alloc>:: 361 insert(size_type __pos, const _CharT* __s, size_type __n) 362 { 363 __glibcxx_requires_string_len(__s, __n); 364 _M_check(__pos, "basic_string::insert"); 365 _M_check_length(size_type(0), __n, "basic_string::insert"); 366 if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 367 return _M_replace_safe(__pos, size_type(0), __s, __n); 368 else 369 { 370 // Work in-place. 371 const size_type __off = __s - _M_data(); 372 _M_mutate(__pos, 0, __n); 373 __s = _M_data() + __off; 374 _CharT* __p = _M_data() + __pos; 375 if (__s + __n <= __p) 376 _M_copy(__p, __s, __n); 377 else if (__s >= __p) 378 _M_copy(__p, __s + __n, __n); 379 else 380 { 381 const size_type __nleft = __p - __s; 382 _M_copy(__p, __s, __nleft); 383 _M_copy(__p + __nleft, __p + __n, __n - __nleft); 384 } 385 return *this; 386 } 387 } 388 389 template<typename _CharT, typename _Traits, typename _Alloc> 390 basic_string<_CharT, _Traits, _Alloc>& 391 basic_string<_CharT, _Traits, _Alloc>:: 392 replace(size_type __pos, size_type __n1, const _CharT* __s, 393 size_type __n2) 394 { 395 __glibcxx_requires_string_len(__s, __n2); 396 _M_check(__pos, "basic_string::replace"); 397 __n1 = _M_limit(__pos, __n1); 398 _M_check_length(__n1, __n2, "basic_string::replace"); 399 bool __left; 400 if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 401 return _M_replace_safe(__pos, __n1, __s, __n2); 402 else if ((__left = __s + __n2 <= _M_data() + __pos) 403 || _M_data() + __pos + __n1 <= __s) 404 { 405 // Work in-place: non-overlapping case. 406 size_type __off = __s - _M_data(); 407 __left ? __off : (__off += __n2 - __n1); 408 _M_mutate(__pos, __n1, __n2); 409 _M_copy(_M_data() + __pos, _M_data() + __off, __n2); 410 return *this; 411 } 412 else 413 { 414 // Todo: overlapping case. 415 const basic_string __tmp(__s, __n2); 416 return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2); 417 } 418 } 419 420 template<typename _CharT, typename _Traits, typename _Alloc> 421 void 422 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 423 _M_destroy(const _Alloc& __a) throw () 424 { 425 const size_type __size = sizeof(_Rep_base) + 426 (this->_M_capacity + 1) * sizeof(_CharT); 427 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size); 428 } 429 430 template<typename _CharT, typename _Traits, typename _Alloc> 431 void 432 basic_string<_CharT, _Traits, _Alloc>:: 433 _M_leak_hard() 434 { 435#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 436 if (_M_rep() == &_S_empty_rep()) 437 return; 438#endif 439 if (_M_rep()->_M_is_shared()) 440 _M_mutate(0, 0, 0); 441 _M_rep()->_M_set_leaked(); 442 } 443 444 template<typename _CharT, typename _Traits, typename _Alloc> 445 void 446 basic_string<_CharT, _Traits, _Alloc>:: 447 _M_mutate(size_type __pos, size_type __len1, size_type __len2) 448 { 449 const size_type __old_size = this->size(); 450 const size_type __new_size = __old_size + __len2 - __len1; 451 const size_type __how_much = __old_size - __pos - __len1; 452 453 if (__new_size > this->capacity() || _M_rep()->_M_is_shared()) 454 { 455 // Must reallocate. 456 const allocator_type __a = get_allocator(); 457 _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a); 458 459 if (__pos) 460 _M_copy(__r->_M_refdata(), _M_data(), __pos); 461 if (__how_much) 462 _M_copy(__r->_M_refdata() + __pos + __len2, 463 _M_data() + __pos + __len1, __how_much); 464 465 _M_rep()->_M_dispose(__a); 466 _M_data(__r->_M_refdata()); 467 } 468 else if (__how_much && __len1 != __len2) 469 { 470 // Work in-place. 471 _M_move(_M_data() + __pos + __len2, 472 _M_data() + __pos + __len1, __how_much); 473 } 474 _M_rep()->_M_set_length_and_sharable(__new_size); 475 } 476 477 template<typename _CharT, typename _Traits, typename _Alloc> 478 void 479 basic_string<_CharT, _Traits, _Alloc>:: 480 reserve(size_type __res) 481 { 482 if (__res != this->capacity() || _M_rep()->_M_is_shared()) 483 { 484 // Make sure we don't shrink below the current size 485 if (__res < this->size()) 486 __res = this->size(); 487 const allocator_type __a = get_allocator(); 488 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); 489 _M_rep()->_M_dispose(__a); 490 _M_data(__tmp); 491 } 492 } 493 494 template<typename _CharT, typename _Traits, typename _Alloc> 495 void 496 basic_string<_CharT, _Traits, _Alloc>:: 497 swap(basic_string& __s) 498 { 499 if (_M_rep()->_M_is_leaked()) 500 _M_rep()->_M_set_sharable(); 501 if (__s._M_rep()->_M_is_leaked()) 502 __s._M_rep()->_M_set_sharable(); 503 if (this->get_allocator() == __s.get_allocator()) 504 { 505 _CharT* __tmp = _M_data(); 506 _M_data(__s._M_data()); 507 __s._M_data(__tmp); 508 } 509 // The code below can usually be optimized away. 510 else 511 { 512 const basic_string __tmp1(_M_ibegin(), _M_iend(), 513 __s.get_allocator()); 514 const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 515 this->get_allocator()); 516 *this = __tmp2; 517 __s = __tmp1; 518 } 519 } 520 521 template<typename _CharT, typename _Traits, typename _Alloc> 522 typename basic_string<_CharT, _Traits, _Alloc>::_Rep* 523 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 524 _S_create(size_type __capacity, size_type __old_capacity, 525 const _Alloc& __alloc) 526 { 527 // _GLIBCXX_RESOLVE_LIB_DEFECTS 528 // 83. String::npos vs. string::max_size() 529 if (__capacity > _S_max_size) 530 __throw_length_error(__N("basic_string::_S_create")); 531 532 // The standard places no restriction on allocating more memory 533 // than is strictly needed within this layer at the moment or as 534 // requested by an explicit application call to reserve(). 535 536 // Many malloc implementations perform quite poorly when an 537 // application attempts to allocate memory in a stepwise fashion 538 // growing each allocation size by only 1 char. Additionally, 539 // it makes little sense to allocate less linear memory than the 540 // natural blocking size of the malloc implementation. 541 // Unfortunately, we would need a somewhat low-level calculation 542 // with tuned parameters to get this perfect for any particular 543 // malloc implementation. Fortunately, generalizations about 544 // common features seen among implementations seems to suffice. 545 546 // __pagesize need not match the actual VM page size for good 547 // results in practice, thus we pick a common value on the low 548 // side. __malloc_header_size is an estimate of the amount of 549 // overhead per memory allocation (in practice seen N * sizeof 550 // (void*) where N is 0, 2 or 4). According to folklore, 551 // picking this value on the high side is better than 552 // low-balling it (especially when this algorithm is used with 553 // malloc implementations that allocate memory blocks rounded up 554 // to a size which is a power of 2). 555 const size_type __pagesize = 4096; 556 const size_type __malloc_header_size = 4 * sizeof(void*); 557 558 // The below implements an exponential growth policy, necessary to 559 // meet amortized linear time requirements of the library: see 560 // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. 561 // It's active for allocations requiring an amount of memory above 562 // system pagesize. This is consistent with the requirements of the 563 // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html 564 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity) 565 __capacity = 2 * __old_capacity; 566 567 // NB: Need an array of char_type[__capacity], plus a terminating 568 // null char_type() element, plus enough for the _Rep data structure. 569 // Whew. Seemingly so needy, yet so elemental. 570 size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 571 572 const size_type __adj_size = __size + __malloc_header_size; 573 if (__adj_size > __pagesize && __capacity > __old_capacity) 574 { 575 const size_type __extra = __pagesize - __adj_size % __pagesize; 576 __capacity += __extra / sizeof(_CharT); 577 // Never allocate a string bigger than _S_max_size. 578 if (__capacity > _S_max_size) 579 __capacity = _S_max_size; 580 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 581 } 582 583 // NB: Might throw, but no worries about a leak, mate: _Rep() 584 // does not throw. 585 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); 586 _Rep *__p = new (__place) _Rep; 587 __p->_M_capacity = __capacity; 588 // ABI compatibility - 3.4.x set in _S_create both 589 // _M_refcount and _M_length. All callers of _S_create 590 // in basic_string.tcc then set just _M_length. 591 // In 4.0.x and later both _M_refcount and _M_length 592 // are initialized in the callers, unfortunately we can 593 // have 3.4.x compiled code with _S_create callers inlined 594 // calling 4.0.x+ _S_create. 595 __p->_M_set_sharable(); 596 return __p; 597 } 598 599 template<typename _CharT, typename _Traits, typename _Alloc> 600 _CharT* 601 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 602 _M_clone(const _Alloc& __alloc, size_type __res) 603 { 604 // Requested capacity of the clone. 605 const size_type __requested_cap = this->_M_length + __res; 606 _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity, 607 __alloc); 608 if (this->_M_length) 609 _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length); 610 611 __r->_M_set_length_and_sharable(this->_M_length); 612 return __r->_M_refdata(); 613 } 614 615 template<typename _CharT, typename _Traits, typename _Alloc> 616 void 617 basic_string<_CharT, _Traits, _Alloc>:: 618 resize(size_type __n, _CharT __c) 619 { 620 const size_type __size = this->size(); 621 _M_check_length(__size, __n, "basic_string::resize"); 622 if (__size < __n) 623 this->append(__n - __size, __c); 624 else if (__n < __size) 625 this->erase(__n); 626 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.) 627 } 628 629 template<typename _CharT, typename _Traits, typename _Alloc> 630 template<typename _InputIterator> 631 basic_string<_CharT, _Traits, _Alloc>& 632 basic_string<_CharT, _Traits, _Alloc>:: 633 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1, 634 _InputIterator __k2, __false_type) 635 { 636 const basic_string __s(__k1, __k2); 637 const size_type __n1 = __i2 - __i1; 638 _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch"); 639 return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(), 640 __s.size()); 641 } 642 643 template<typename _CharT, typename _Traits, typename _Alloc> 644 basic_string<_CharT, _Traits, _Alloc>& 645 basic_string<_CharT, _Traits, _Alloc>:: 646 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2, 647 _CharT __c) 648 { 649 _M_check_length(__n1, __n2, "basic_string::_M_replace_aux"); 650 _M_mutate(__pos1, __n1, __n2); 651 if (__n2) 652 _M_assign(_M_data() + __pos1, __n2, __c); 653 return *this; 654 } 655 656 template<typename _CharT, typename _Traits, typename _Alloc> 657 basic_string<_CharT, _Traits, _Alloc>& 658 basic_string<_CharT, _Traits, _Alloc>:: 659 _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s, 660 size_type __n2) 661 { 662 _M_mutate(__pos1, __n1, __n2); 663 if (__n2) 664 _M_copy(_M_data() + __pos1, __s, __n2); 665 return *this; 666 } 667 668 template<typename _CharT, typename _Traits, typename _Alloc> 669 basic_string<_CharT, _Traits, _Alloc> 670 operator+(const _CharT* __lhs, 671 const basic_string<_CharT, _Traits, _Alloc>& __rhs) 672 { 673 __glibcxx_requires_string(__lhs); 674 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 675 typedef typename __string_type::size_type __size_type; 676 const __size_type __len = _Traits::length(__lhs); 677 __string_type __str; 678 __str.reserve(__len + __rhs.size()); 679 __str.append(__lhs, __len); 680 __str.append(__rhs); 681 return __str; 682 } 683 684 template<typename _CharT, typename _Traits, typename _Alloc> 685 basic_string<_CharT, _Traits, _Alloc> 686 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) 687 { 688 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 689 typedef typename __string_type::size_type __size_type; 690 __string_type __str; 691 const __size_type __len = __rhs.size(); 692 __str.reserve(__len + 1); 693 __str.append(__size_type(1), __lhs); 694 __str.append(__rhs); 695 return __str; 696 } 697 698 template<typename _CharT, typename _Traits, typename _Alloc> 699 typename basic_string<_CharT, _Traits, _Alloc>::size_type 700 basic_string<_CharT, _Traits, _Alloc>:: 701 copy(_CharT* __s, size_type __n, size_type __pos) const 702 { 703 _M_check(__pos, "basic_string::copy"); 704 __n = _M_limit(__pos, __n); 705 __glibcxx_requires_string_len(__s, __n); 706 if (__n) 707 _M_copy(__s, _M_data() + __pos, __n); 708 // 21.3.5.7 par 3: do not append null. (good.) 709 return __n; 710 } 711 712 template<typename _CharT, typename _Traits, typename _Alloc> 713 typename basic_string<_CharT, _Traits, _Alloc>::size_type 714 basic_string<_CharT, _Traits, _Alloc>:: 715 find(const _CharT* __s, size_type __pos, size_type __n) const 716 { 717 __glibcxx_requires_string_len(__s, __n); 718 const size_type __size = this->size(); 719 const _CharT* __data = _M_data(); 720 721 if (__n == 0) 722 return __pos <= __size ? __pos : npos; 723 724 if (__n <= __size) 725 { 726 for (; __pos <= __size - __n; ++__pos) 727 if (traits_type::eq(__data[__pos], __s[0]) 728 && traits_type::compare(__data + __pos + 1, 729 __s + 1, __n - 1) == 0) 730 return __pos; 731 } 732 return npos; 733 } 734 735 template<typename _CharT, typename _Traits, typename _Alloc> 736 typename basic_string<_CharT, _Traits, _Alloc>::size_type 737 basic_string<_CharT, _Traits, _Alloc>:: 738 find(_CharT __c, size_type __pos) const 739 { 740 size_type __ret = npos; 741 const size_type __size = this->size(); 742 if (__pos < __size) 743 { 744 const _CharT* __data = _M_data(); 745 const size_type __n = __size - __pos; 746 const _CharT* __p = traits_type::find(__data + __pos, __n, __c); 747 if (__p) 748 __ret = __p - __data; 749 } 750 return __ret; 751 } 752 753 template<typename _CharT, typename _Traits, typename _Alloc> 754 typename basic_string<_CharT, _Traits, _Alloc>::size_type 755 basic_string<_CharT, _Traits, _Alloc>:: 756 rfind(const _CharT* __s, size_type __pos, size_type __n) const 757 { 758 __glibcxx_requires_string_len(__s, __n); 759 const size_type __size = this->size(); 760 if (__n <= __size) 761 { 762 __pos = std::min(size_type(__size - __n), __pos); 763 const _CharT* __data = _M_data(); 764 do 765 { 766 if (traits_type::compare(__data + __pos, __s, __n) == 0) 767 return __pos; 768 } 769 while (__pos-- > 0); 770 } 771 return npos; 772 } 773 774 template<typename _CharT, typename _Traits, typename _Alloc> 775 typename basic_string<_CharT, _Traits, _Alloc>::size_type 776 basic_string<_CharT, _Traits, _Alloc>:: 777 rfind(_CharT __c, size_type __pos) const 778 { 779 size_type __size = this->size(); 780 if (__size) 781 { 782 if (--__size > __pos) 783 __size = __pos; 784 for (++__size; __size-- > 0; ) 785 if (traits_type::eq(_M_data()[__size], __c)) 786 return __size; 787 } 788 return npos; 789 } 790 791 template<typename _CharT, typename _Traits, typename _Alloc> 792 typename basic_string<_CharT, _Traits, _Alloc>::size_type 793 basic_string<_CharT, _Traits, _Alloc>:: 794 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const 795 { 796 __glibcxx_requires_string_len(__s, __n); 797 for (; __n && __pos < this->size(); ++__pos) 798 { 799 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]); 800 if (__p) 801 return __pos; 802 } 803 return npos; 804 } 805 806 template<typename _CharT, typename _Traits, typename _Alloc> 807 typename basic_string<_CharT, _Traits, _Alloc>::size_type 808 basic_string<_CharT, _Traits, _Alloc>:: 809 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const 810 { 811 __glibcxx_requires_string_len(__s, __n); 812 size_type __size = this->size(); 813 if (__size && __n) 814 { 815 if (--__size > __pos) 816 __size = __pos; 817 do 818 { 819 if (traits_type::find(__s, __n, _M_data()[__size])) 820 return __size; 821 } 822 while (__size-- != 0); 823 } 824 return npos; 825 } 826 827 template<typename _CharT, typename _Traits, typename _Alloc> 828 typename basic_string<_CharT, _Traits, _Alloc>::size_type 829 basic_string<_CharT, _Traits, _Alloc>:: 830 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const 831 { 832 __glibcxx_requires_string_len(__s, __n); 833 for (; __pos < this->size(); ++__pos) 834 if (!traits_type::find(__s, __n, _M_data()[__pos])) 835 return __pos; 836 return npos; 837 } 838 839 template<typename _CharT, typename _Traits, typename _Alloc> 840 typename basic_string<_CharT, _Traits, _Alloc>::size_type 841 basic_string<_CharT, _Traits, _Alloc>:: 842 find_first_not_of(_CharT __c, size_type __pos) const 843 { 844 for (; __pos < this->size(); ++__pos) 845 if (!traits_type::eq(_M_data()[__pos], __c)) 846 return __pos; 847 return npos; 848 } 849 850 template<typename _CharT, typename _Traits, typename _Alloc> 851 typename basic_string<_CharT, _Traits, _Alloc>::size_type 852 basic_string<_CharT, _Traits, _Alloc>:: 853 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const 854 { 855 __glibcxx_requires_string_len(__s, __n); 856 size_type __size = this->size(); 857 if (__size) 858 { 859 if (--__size > __pos) 860 __size = __pos; 861 do 862 { 863 if (!traits_type::find(__s, __n, _M_data()[__size])) 864 return __size; 865 } 866 while (__size--); 867 } 868 return npos; 869 } 870 871 template<typename _CharT, typename _Traits, typename _Alloc> 872 typename basic_string<_CharT, _Traits, _Alloc>::size_type 873 basic_string<_CharT, _Traits, _Alloc>:: 874 find_last_not_of(_CharT __c, size_type __pos) const 875 { 876 size_type __size = this->size(); 877 if (__size) 878 { 879 if (--__size > __pos) 880 __size = __pos; 881 do 882 { 883 if (!traits_type::eq(_M_data()[__size], __c)) 884 return __size; 885 } 886 while (__size--); 887 } 888 return npos; 889 } 890 891 template<typename _CharT, typename _Traits, typename _Alloc> 892 int 893 basic_string<_CharT, _Traits, _Alloc>:: 894 compare(size_type __pos, size_type __n, const basic_string& __str) const 895 { 896 _M_check(__pos, "basic_string::compare"); 897 __n = _M_limit(__pos, __n); 898 const size_type __osize = __str.size(); 899 const size_type __len = std::min(__n, __osize); 900 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len); 901 if (!__r) 902 __r = _S_compare(__n, __osize); 903 return __r; 904 } 905 906 template<typename _CharT, typename _Traits, typename _Alloc> 907 int 908 basic_string<_CharT, _Traits, _Alloc>:: 909 compare(size_type __pos1, size_type __n1, const basic_string& __str, 910 size_type __pos2, size_type __n2) const 911 { 912 _M_check(__pos1, "basic_string::compare"); 913 __str._M_check(__pos2, "basic_string::compare"); 914 __n1 = _M_limit(__pos1, __n1); 915 __n2 = __str._M_limit(__pos2, __n2); 916 const size_type __len = std::min(__n1, __n2); 917 int __r = traits_type::compare(_M_data() + __pos1, 918 __str.data() + __pos2, __len); 919 if (!__r) 920 __r = _S_compare(__n1, __n2); 921 return __r; 922 } 923 924 template<typename _CharT, typename _Traits, typename _Alloc> 925 int 926 basic_string<_CharT, _Traits, _Alloc>:: 927 compare(const _CharT* __s) const 928 { 929 __glibcxx_requires_string(__s); 930 const size_type __size = this->size(); 931 const size_type __osize = traits_type::length(__s); 932 const size_type __len = std::min(__size, __osize); 933 int __r = traits_type::compare(_M_data(), __s, __len); 934 if (!__r) 935 __r = _S_compare(__size, __osize); 936 return __r; 937 } 938 939 template<typename _CharT, typename _Traits, typename _Alloc> 940 int 941 basic_string <_CharT, _Traits, _Alloc>:: 942 compare(size_type __pos, size_type __n1, const _CharT* __s) const 943 { 944 __glibcxx_requires_string(__s); 945 _M_check(__pos, "basic_string::compare"); 946 __n1 = _M_limit(__pos, __n1); 947 const size_type __osize = traits_type::length(__s); 948 const size_type __len = std::min(__n1, __osize); 949 int __r = traits_type::compare(_M_data() + __pos, __s, __len); 950 if (!__r) 951 __r = _S_compare(__n1, __osize); 952 return __r; 953 } 954 955 template<typename _CharT, typename _Traits, typename _Alloc> 956 int 957 basic_string <_CharT, _Traits, _Alloc>:: 958 compare(size_type __pos, size_type __n1, const _CharT* __s, 959 size_type __n2) const 960 { 961 __glibcxx_requires_string_len(__s, __n2); 962 _M_check(__pos, "basic_string::compare"); 963 __n1 = _M_limit(__pos, __n1); 964 const size_type __len = std::min(__n1, __n2); 965 int __r = traits_type::compare(_M_data() + __pos, __s, __len); 966 if (!__r) 967 __r = _S_compare(__n1, __n2); 968 return __r; 969 } 970 971 // 21.3.7.9 basic_string::getline and operators 972 template<typename _CharT, typename _Traits, typename _Alloc> 973 basic_istream<_CharT, _Traits>& 974 operator>>(basic_istream<_CharT, _Traits>& __in, 975 basic_string<_CharT, _Traits, _Alloc>& __str) 976 { 977 typedef basic_istream<_CharT, _Traits> __istream_type; 978 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 979 typedef typename __istream_type::ios_base __ios_base; 980 typedef typename __istream_type::int_type __int_type; 981 typedef typename __string_type::size_type __size_type; 982 typedef ctype<_CharT> __ctype_type; 983 typedef typename __ctype_type::ctype_base __ctype_base; 984 985 __size_type __extracted = 0; 986 typename __ios_base::iostate __err = __ios_base::goodbit; 987 typename __istream_type::sentry __cerb(__in, false); 988 if (__cerb) 989 { 990 __try 991 { 992 // Avoid reallocation for common case. 993 __str.erase(); 994 _CharT __buf[128]; 995 __size_type __len = 0; 996 const streamsize __w = __in.width(); 997 const __size_type __n = __w > 0 ? static_cast<__size_type>(__w) 998 : __str.max_size(); 999 const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc()); 1000 const __int_type __eof = _Traits::eof(); 1001 __int_type __c = __in.rdbuf()->sgetc(); 1002 1003 while (__extracted < __n 1004 && !_Traits::eq_int_type(__c, __eof) 1005 && !__ct.is(__ctype_base::space, 1006 _Traits::to_char_type(__c))) 1007 { 1008 if (__len == sizeof(__buf) / sizeof(_CharT)) 1009 { 1010 __str.append(__buf, sizeof(__buf) / sizeof(_CharT)); 1011 __len = 0; 1012 } 1013 __buf[__len++] = _Traits::to_char_type(__c); 1014 ++__extracted; 1015 __c = __in.rdbuf()->snextc(); 1016 } 1017 __str.append(__buf, __len); 1018 1019 if (_Traits::eq_int_type(__c, __eof)) 1020 __err |= __ios_base::eofbit; 1021 __in.width(0); 1022 } 1023 __catch(__cxxabiv1::__forced_unwind&) 1024 { 1025 __in._M_setstate(__ios_base::badbit); 1026 __throw_exception_again; 1027 } 1028 __catch(...) 1029 { 1030 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1031 // 91. Description of operator>> and getline() for string<> 1032 // might cause endless loop 1033 __in._M_setstate(__ios_base::badbit); 1034 } 1035 } 1036 // 211. operator>>(istream&, string&) doesn't set failbit 1037 if (!__extracted) 1038 __err |= __ios_base::failbit; 1039 if (__err) 1040 __in.setstate(__err); 1041 return __in; 1042 } 1043 1044 template<typename _CharT, typename _Traits, typename _Alloc> 1045 basic_istream<_CharT, _Traits>& 1046 getline(basic_istream<_CharT, _Traits>& __in, 1047 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim) 1048 { 1049 typedef basic_istream<_CharT, _Traits> __istream_type; 1050 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 1051 typedef typename __istream_type::ios_base __ios_base; 1052 typedef typename __istream_type::int_type __int_type; 1053 typedef typename __string_type::size_type __size_type; 1054 1055 __size_type __extracted = 0; 1056 const __size_type __n = __str.max_size(); 1057 typename __ios_base::iostate __err = __ios_base::goodbit; 1058 typename __istream_type::sentry __cerb(__in, true); 1059 if (__cerb) 1060 { 1061 __try 1062 { 1063 __str.erase(); 1064 const __int_type __idelim = _Traits::to_int_type(__delim); 1065 const __int_type __eof = _Traits::eof(); 1066 __int_type __c = __in.rdbuf()->sgetc(); 1067 1068 while (__extracted < __n 1069 && !_Traits::eq_int_type(__c, __eof) 1070 && !_Traits::eq_int_type(__c, __idelim)) 1071 { 1072 __str += _Traits::to_char_type(__c); 1073 ++__extracted; 1074 __c = __in.rdbuf()->snextc(); 1075 } 1076 1077 if (_Traits::eq_int_type(__c, __eof)) 1078 __err |= __ios_base::eofbit; 1079 else if (_Traits::eq_int_type(__c, __idelim)) 1080 { 1081 ++__extracted; 1082 __in.rdbuf()->sbumpc(); 1083 } 1084 else 1085 __err |= __ios_base::failbit; 1086 } 1087 __catch(__cxxabiv1::__forced_unwind&) 1088 { 1089 __in._M_setstate(__ios_base::badbit); 1090 __throw_exception_again; 1091 } 1092 __catch(...) 1093 { 1094 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1095 // 91. Description of operator>> and getline() for string<> 1096 // might cause endless loop 1097 __in._M_setstate(__ios_base::badbit); 1098 } 1099 } 1100 if (!__extracted) 1101 __err |= __ios_base::failbit; 1102 if (__err) 1103 __in.setstate(__err); 1104 return __in; 1105 } 1106 1107 // Inhibit implicit instantiations for required instantiations, 1108 // which are defined via explicit instantiations elsewhere. 1109 // NB: This syntax is a GNU extension. 1110#if _GLIBCXX_EXTERN_TEMPLATE > 0 1111 extern template class basic_string<char>; 1112 extern template 1113 basic_istream<char>& 1114 operator>>(basic_istream<char>&, string&); 1115 extern template 1116 basic_ostream<char>& 1117 operator<<(basic_ostream<char>&, const string&); 1118 extern template 1119 basic_istream<char>& 1120 getline(basic_istream<char>&, string&, char); 1121 extern template 1122 basic_istream<char>& 1123 getline(basic_istream<char>&, string&); 1124 1125#ifdef _GLIBCXX_USE_WCHAR_T 1126 extern template class basic_string<wchar_t>; 1127 extern template 1128 basic_istream<wchar_t>& 1129 operator>>(basic_istream<wchar_t>&, wstring&); 1130 extern template 1131 basic_ostream<wchar_t>& 1132 operator<<(basic_ostream<wchar_t>&, const wstring&); 1133 extern template 1134 basic_istream<wchar_t>& 1135 getline(basic_istream<wchar_t>&, wstring&, wchar_t); 1136 extern template 1137 basic_istream<wchar_t>& 1138 getline(basic_istream<wchar_t>&, wstring&); 1139#endif 1140#endif 1141 1142_GLIBCXX_END_NAMESPACE 1143 1144#endif 1145