basic_string.tcc

00001 // Components for manipulating sequences of characters -*- C++ -*- 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 // 00032 // ISO C++ 14882: 21 Strings library 00033 // 00034 00035 // This file is included by <string>. It is not meant to be included 00036 // separately. 00037 00038 // Written by Jason Merrill based upon the specification by Takanori Adachi 00039 // in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882. 00040 00041 #ifndef _BASIC_STRING_TCC 00042 #define _BASIC_STRING_TCC 1 00043 00044 #pragma GCC system_header 00045 00046 namespace std 00047 { 00048 template<typename _Type> 00049 inline bool 00050 __is_null_pointer(_Type* __ptr) 00051 { return __ptr == 0; } 00052 00053 template<typename _Type> 00054 inline bool 00055 __is_null_pointer(_Type) 00056 { return false; } 00057 00058 template<typename _CharT, typename _Traits, typename _Alloc> 00059 const typename basic_string<_CharT, _Traits, _Alloc>::size_type 00060 basic_string<_CharT, _Traits, _Alloc>:: 00061 _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4; 00062 00063 template<typename _CharT, typename _Traits, typename _Alloc> 00064 const _CharT 00065 basic_string<_CharT, _Traits, _Alloc>:: 00066 _Rep::_S_terminal = _CharT(); 00067 00068 template<typename _CharT, typename _Traits, typename _Alloc> 00069 const typename basic_string<_CharT, _Traits, _Alloc>::size_type 00070 basic_string<_CharT, _Traits, _Alloc>::npos; 00071 00072 // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string) 00073 // at static init time (before static ctors are run). 00074 template<typename _CharT, typename _Traits, typename _Alloc> 00075 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00076 basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[ 00077 (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) / 00078 sizeof(size_type)]; 00079 00080 // NB: This is the special case for Input Iterators, used in 00081 // istreambuf_iterators, etc. 00082 // Input Iterators have a cost structure very different from 00083 // pointers, calling for a different coding style. 00084 template<typename _CharT, typename _Traits, typename _Alloc> 00085 template<typename _InIterator> 00086 _CharT* 00087 basic_string<_CharT, _Traits, _Alloc>:: 00088 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 00089 input_iterator_tag) 00090 { 00091 if (__beg == __end && __a == _Alloc()) 00092 return _S_empty_rep()._M_refdata(); 00093 // Avoid reallocation for common case. 00094 _CharT __buf[128]; 00095 size_type __len = 0; 00096 while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT)) 00097 { 00098 __buf[__len++] = *__beg; 00099 ++__beg; 00100 } 00101 _Rep* __r = _Rep::_S_create(__len, size_type(0), __a); 00102 traits_type::copy(__r->_M_refdata(), __buf, __len); 00103 try 00104 { 00105 while (__beg != __end) 00106 { 00107 if (__len == __r->_M_capacity) 00108 { 00109 // Allocate more space. 00110 _Rep* __another = _Rep::_S_create(__len + 1, __len, __a); 00111 traits_type::copy(__another->_M_refdata(), 00112 __r->_M_refdata(), __len); 00113 __r->_M_destroy(__a); 00114 __r = __another; 00115 } 00116 __r->_M_refdata()[__len++] = *__beg; 00117 ++__beg; 00118 } 00119 } 00120 catch(...) 00121 { 00122 __r->_M_destroy(__a); 00123 __throw_exception_again; 00124 } 00125 __r->_M_length = __len; 00126 __r->_M_refdata()[__len] = _Rep::_S_terminal; // grrr. 00127 return __r->_M_refdata(); 00128 } 00129 00130 template<typename _CharT, typename _Traits, typename _Alloc> 00131 template <typename _InIterator> 00132 _CharT* 00133 basic_string<_CharT, _Traits, _Alloc>:: 00134 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 00135 forward_iterator_tag) 00136 { 00137 if (__beg == __end && __a == _Alloc()) 00138 return _S_empty_rep()._M_refdata(); 00139 00140 // NB: Not required, but considered best practice. 00141 if (__builtin_expect(__is_null_pointer(__beg), 0)) 00142 __throw_logic_error(__N("basic_string::_S_construct NULL not valid")); 00143 00144 const size_type __dnew = static_cast<size_type>(std::distance(__beg, 00145 __end)); 00146 // Check for out_of_range and length_error exceptions. 00147 _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a); 00148 try 00149 { _S_copy_chars(__r->_M_refdata(), __beg, __end); } 00150 catch(...) 00151 { 00152 __r->_M_destroy(__a); 00153 __throw_exception_again; 00154 } 00155 __r->_M_length = __dnew; 00156 __r->_M_refdata()[__dnew] = _Rep::_S_terminal; // grrr. 00157 return __r->_M_refdata(); 00158 } 00159 00160 template<typename _CharT, typename _Traits, typename _Alloc> 00161 _CharT* 00162 basic_string<_CharT, _Traits, _Alloc>:: 00163 _S_construct(size_type __n, _CharT __c, const _Alloc& __a) 00164 { 00165 if (__n == 0 && __a == _Alloc()) 00166 return _S_empty_rep()._M_refdata(); 00167 00168 // Check for out_of_range and length_error exceptions. 00169 _Rep* __r = _Rep::_S_create(__n, size_type(0), __a); 00170 if (__n) 00171 traits_type::assign(__r->_M_refdata(), __n, __c); 00172 00173 __r->_M_length = __n; 00174 __r->_M_refdata()[__n] = _Rep::_S_terminal; // grrr 00175 return __r->_M_refdata(); 00176 } 00177 00178 template<typename _CharT, typename _Traits, typename _Alloc> 00179 basic_string<_CharT, _Traits, _Alloc>:: 00180 basic_string(const basic_string& __str) 00181 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), 00182 __str.get_allocator()), 00183 __str.get_allocator()) 00184 { } 00185 00186 template<typename _CharT, typename _Traits, typename _Alloc> 00187 basic_string<_CharT, _Traits, _Alloc>:: 00188 basic_string(const _Alloc& __a) 00189 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) 00190 { } 00191 00192 template<typename _CharT, typename _Traits, typename _Alloc> 00193 basic_string<_CharT, _Traits, _Alloc>:: 00194 basic_string(const basic_string& __str, size_type __pos, size_type __n) 00195 : _M_dataplus(_S_construct(__str._M_data() 00196 + __str._M_check(__pos, 00197 "basic_string::basic_string"), 00198 __str._M_data() + __str._M_limit(__pos, __n) 00199 + __pos, _Alloc()), _Alloc()) 00200 { } 00201 00202 template<typename _CharT, typename _Traits, typename _Alloc> 00203 basic_string<_CharT, _Traits, _Alloc>:: 00204 basic_string(const basic_string& __str, size_type __pos, 00205 size_type __n, const _Alloc& __a) 00206 : _M_dataplus(_S_construct(__str._M_data() 00207 + __str._M_check(__pos, 00208 "basic_string::basic_string"), 00209 __str._M_data() + __str._M_limit(__pos, __n) 00210 + __pos, __a), __a) 00211 { } 00212 00213 // TBD: DPG annotate 00214 template<typename _CharT, typename _Traits, typename _Alloc> 00215 basic_string<_CharT, _Traits, _Alloc>:: 00216 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a) 00217 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a) 00218 { } 00219 00220 // TBD: DPG annotate 00221 template<typename _CharT, typename _Traits, typename _Alloc> 00222 basic_string<_CharT, _Traits, _Alloc>:: 00223 basic_string(const _CharT* __s, const _Alloc& __a) 00224 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : 00225 __s + npos, __a), __a) 00226 { } 00227 00228 template<typename _CharT, typename _Traits, typename _Alloc> 00229 basic_string<_CharT, _Traits, _Alloc>:: 00230 basic_string(size_type __n, _CharT __c, const _Alloc& __a) 00231 : _M_dataplus(_S_construct(__n, __c, __a), __a) 00232 { } 00233 00234 // TBD: DPG annotate 00235 template<typename _CharT, typename _Traits, typename _Alloc> 00236 template<typename _InputIterator> 00237 basic_string<_CharT, _Traits, _Alloc>:: 00238 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a) 00239 : _M_dataplus(_S_construct(__beg, __end, __a), __a) 00240 { } 00241 00242 template<typename _CharT, typename _Traits, typename _Alloc> 00243 basic_string<_CharT, _Traits, _Alloc>& 00244 basic_string<_CharT, _Traits, _Alloc>:: 00245 assign(const basic_string& __str) 00246 { 00247 if (_M_rep() != __str._M_rep()) 00248 { 00249 // XXX MT 00250 const allocator_type __a = this->get_allocator(); 00251 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator()); 00252 _M_rep()->_M_dispose(__a); 00253 _M_data(__tmp); 00254 } 00255 return *this; 00256 } 00257 00258 template<typename _CharT, typename _Traits, typename _Alloc> 00259 basic_string<_CharT, _Traits, _Alloc>& 00260 basic_string<_CharT, _Traits, _Alloc>:: 00261 assign(const _CharT* __s, size_type __n) 00262 { 00263 __glibcxx_requires_string_len(__s, __n); 00264 if (__n > this->max_size()) 00265 __throw_length_error(__N("basic_string::assign")); 00266 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) 00267 || less<const _CharT*>()(_M_data() + this->size(), __s)) 00268 return _M_replace_safe(size_type(0), this->size(), __s, __n); 00269 else 00270 { 00271 // Work in-place 00272 const size_type __pos = __s - _M_data(); 00273 if (__pos >= __n) 00274 traits_type::copy(_M_data(), __s, __n); 00275 else if (__pos) 00276 traits_type::move(_M_data(), __s, __n); 00277 _M_rep()->_M_set_sharable(); 00278 _M_rep()->_M_length = __n; 00279 _M_data()[__n] = _Rep::_S_terminal; // grr. 00280 return *this; 00281 } 00282 } 00283 00284 template<typename _CharT, typename _Traits, typename _Alloc> 00285 basic_string<_CharT, _Traits, _Alloc>& 00286 basic_string<_CharT, _Traits, _Alloc>:: 00287 insert(size_type __pos, const _CharT* __s, size_type __n) 00288 { 00289 __glibcxx_requires_string_len(__s, __n); 00290 _M_check(__pos, "basic_string::insert"); 00291 if (this->max_size() - this->size() < __n) 00292 __throw_length_error(__N("basic_string::insert")); 00293 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) 00294 || less<const _CharT*>()(_M_data() + this->size(), __s)) 00295 return _M_replace_safe(__pos, size_type(0), __s, __n); 00296 else 00297 { 00298 // Work in-place. If _M_mutate reallocates the string, __s 00299 // does not point anymore to valid data, therefore we save its 00300 // offset, then we restore it. 00301 const size_type __off = __s - _M_data(); 00302 _M_mutate(__pos, 0, __n); 00303 __s = _M_data() + __off; 00304 _CharT* __p = _M_data() + __pos; 00305 if (__s + __n <= __p) 00306 traits_type::copy(__p, __s, __n); 00307 else if (__s >= __p) 00308 traits_type::copy(__p, __s + __n, __n); 00309 else 00310 { 00311 const size_type __nleft = __p - __s; 00312 traits_type::copy(__p, __s, __nleft); 00313 traits_type::copy(__p + __nleft, __p + __n, __n - __nleft); 00314 } 00315 return *this; 00316 } 00317 } 00318 00319 template<typename _CharT, typename _Traits, typename _Alloc> 00320 basic_string<_CharT, _Traits, _Alloc>& 00321 basic_string<_CharT, _Traits, _Alloc>:: 00322 replace(size_type __pos, size_type __n1, const _CharT* __s, 00323 size_type __n2) 00324 { 00325 __glibcxx_requires_string_len(__s, __n2); 00326 _M_check(__pos, "basic_string::replace"); 00327 __n1 = _M_limit(__pos, __n1); 00328 if (this->max_size() - (this->size() - __n1) < __n2) 00329 __throw_length_error(__N("basic_string::replace")); 00330 bool __left; 00331 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) 00332 || less<const _CharT*>()(_M_data() + this->size(), __s)) 00333 return _M_replace_safe(__pos, __n1, __s, __n2); 00334 else if ((__left = __s + __n2 <= _M_data() + __pos) 00335 || _M_data() + __pos + __n1 <= __s) 00336 { 00337 // Work in-place: non-overlapping case. 00338 const size_type __off = __s - _M_data(); 00339 _M_mutate(__pos, __n1, __n2); 00340 if (__left) 00341 traits_type::copy(_M_data() + __pos, 00342 _M_data() + __off, __n2); 00343 else 00344 traits_type::copy(_M_data() + __pos, 00345 _M_data() + __off + __n2 - __n1, __n2); 00346 return *this; 00347 } 00348 else 00349 { 00350 // Todo: overlapping case. 00351 const basic_string __tmp(__s, __n2); 00352 return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2); 00353 } 00354 } 00355 00356 template<typename _CharT, typename _Traits, typename _Alloc> 00357 void 00358 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 00359 _M_destroy(const _Alloc& __a) throw () 00360 { 00361 if (this == &_S_empty_rep()) 00362 return; 00363 const size_type __size = sizeof(_Rep_base) + 00364 (this->_M_capacity + 1) * sizeof(_CharT); 00365 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size); 00366 } 00367 00368 template<typename _CharT, typename _Traits, typename _Alloc> 00369 void 00370 basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard() 00371 { 00372 if (_M_rep() == &_S_empty_rep()) 00373 return; 00374 if (_M_rep()->_M_is_shared()) 00375 _M_mutate(0, 0, 0); 00376 _M_rep()->_M_set_leaked(); 00377 } 00378 00379 template<typename _CharT, typename _Traits, typename _Alloc> 00380 void 00381 basic_string<_CharT, _Traits, _Alloc>:: 00382 _M_mutate(size_type __pos, size_type __len1, size_type __len2) 00383 { 00384 const size_type __old_size = this->size(); 00385 const size_type __new_size = __old_size + __len2 - __len1; 00386 const size_type __how_much = __old_size - __pos - __len1; 00387 00388 if (_M_rep() == &_S_empty_rep() 00389 || _M_rep()->_M_is_shared() || __new_size > capacity()) 00390 { 00391 // Must reallocate. 00392 const allocator_type __a = get_allocator(); 00393 _Rep* __r = _Rep::_S_create(__new_size, capacity(), __a); 00394 00395 if (__pos) 00396 traits_type::copy(__r->_M_refdata(), _M_data(), __pos); 00397 if (__how_much) 00398 traits_type::copy(__r->_M_refdata() + __pos + __len2, 00399 _M_data() + __pos + __len1, __how_much); 00400 00401 _M_rep()->_M_dispose(__a); 00402 _M_data(__r->_M_refdata()); 00403 } 00404 else if (__how_much && __len1 != __len2) 00405 { 00406 // Work in-place 00407 traits_type::move(_M_data() + __pos + __len2, 00408 _M_data() + __pos + __len1, __how_much); 00409 } 00410 _M_rep()->_M_set_sharable(); 00411 _M_rep()->_M_length = __new_size; 00412 _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4) 00413 // You cannot leave those LWG people alone for a second. 00414 } 00415 00416 template<typename _CharT, typename _Traits, typename _Alloc> 00417 void 00418 basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res) 00419 { 00420 if (__res != this->capacity() || _M_rep()->_M_is_shared()) 00421 { 00422 if (__res > this->max_size()) 00423 __throw_length_error(__N("basic_string::reserve")); 00424 // Make sure we don't shrink below the current size 00425 if (__res < this->size()) 00426 __res = this->size(); 00427 const allocator_type __a = get_allocator(); 00428 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); 00429 _M_rep()->_M_dispose(__a); 00430 _M_data(__tmp); 00431 } 00432 } 00433 00434 template<typename _CharT, typename _Traits, typename _Alloc> 00435 void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s) 00436 { 00437 if (_M_rep()->_M_is_leaked()) 00438 _M_rep()->_M_set_sharable(); 00439 if (__s._M_rep()->_M_is_leaked()) 00440 __s._M_rep()->_M_set_sharable(); 00441 if (this->get_allocator() == __s.get_allocator()) 00442 { 00443 _CharT* __tmp = _M_data(); 00444 _M_data(__s._M_data()); 00445 __s._M_data(__tmp); 00446 } 00447 // The code below can usually be optimized away. 00448 else 00449 { 00450 const basic_string __tmp1(_M_ibegin(), _M_iend(), 00451 __s.get_allocator()); 00452 const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 00453 this->get_allocator()); 00454 *this = __tmp2; 00455 __s = __tmp1; 00456 } 00457 } 00458 00459 template<typename _CharT, typename _Traits, typename _Alloc> 00460 typename basic_string<_CharT, _Traits, _Alloc>::_Rep* 00461 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 00462 _S_create(size_type __capacity, size_type __old_capacity, 00463 const _Alloc& __alloc) 00464 { 00465 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00466 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00467 // 83. String::npos vs. string::max_size() 00468 if (__capacity > _S_max_size) 00469 __throw_length_error(__N("basic_string::_S_create")); 00470 00471 // The standard places no restriction on allocating more memory 00472 // than is strictly needed within this layer at the moment or as 00473 // requested by an explicit application call to reserve(). 00474 00475 // Many malloc implementations perform quite poorly when an 00476 // application attempts to allocate memory in a stepwise fashion 00477 // growing each allocation size by only 1 char. Additionally, 00478 // it makes little sense to allocate less linear memory than the 00479 // natural blocking size of the malloc implementation. 00480 // Unfortunately, we would need a somewhat low-level calculation 00481 // with tuned parameters to get this perfect for any particular 00482 // malloc implementation. Fortunately, generalizations about 00483 // common features seen among implementations seems to suffice. 00484 00485 // __pagesize need not match the actual VM page size for good 00486 // results in practice, thus we pick a common value on the low 00487 // side. __malloc_header_size is an estimate of the amount of 00488 // overhead per memory allocation (in practice seen N * sizeof 00489 // (void*) where N is 0, 2 or 4). According to folklore, 00490 // picking this value on the high side is better than 00491 // low-balling it (especially when this algorithm is used with 00492 // malloc implementations that allocate memory blocks rounded up 00493 // to a size which is a power of 2). 00494 const size_type __pagesize = 4096; // must be 2^i * __subpagesize 00495 const size_type __subpagesize = 128; // should be >> __malloc_header_size 00496 const size_type __malloc_header_size = 4 * sizeof (void*); 00497 00498 // The below implements an exponential growth policy, necessary to 00499 // meet amortized linear time requirements of the library: see 00500 // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. 00501 // It's active for allocations requiring an amount of memory above 00502 // system pagesize. This is consistent with the requirements of the 00503 // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html 00504 00505 // The biggest string which fits in a memory page 00506 const size_type __page_capacity = ((__pagesize - __malloc_header_size 00507 - sizeof(_Rep) - sizeof(_CharT)) 00508 / sizeof(_CharT)); 00509 00510 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity 00511 && __capacity > __page_capacity) 00512 __capacity = 2 * __old_capacity; 00513 00514 // NB: Need an array of char_type[__capacity], plus a terminating 00515 // null char_type() element, plus enough for the _Rep data structure. 00516 // Whew. Seemingly so needy, yet so elemental. 00517 size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 00518 00519 const size_type __adj_size = __size + __malloc_header_size; 00520 if (__adj_size > __pagesize) 00521 { 00522 const size_type __extra = __pagesize - __adj_size % __pagesize; 00523 __capacity += __extra / sizeof(_CharT); 00524 // Never allocate a string bigger than _S_max_size. 00525 if (__capacity > _S_max_size) 00526 __capacity = _S_max_size; 00527 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 00528 } 00529 else if (__size > __subpagesize) 00530 { 00531 const size_type __extra = __subpagesize - __adj_size % __subpagesize; 00532 __capacity += __extra / sizeof(_CharT); 00533 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 00534 } 00535 00536 // NB: Might throw, but no worries about a leak, mate: _Rep() 00537 // does not throw. 00538 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); 00539 _Rep *__p = new (__place) _Rep; 00540 __p->_M_capacity = __capacity; 00541 __p->_M_set_sharable(); // One reference. 00542 __p->_M_length = 0; 00543 return __p; 00544 } 00545 00546 template<typename _CharT, typename _Traits, typename _Alloc> 00547 _CharT* 00548 basic_string<_CharT, _Traits, _Alloc>::_Rep:: 00549 _M_clone(const _Alloc& __alloc, size_type __res) 00550 { 00551 // Requested capacity of the clone. 00552 const size_type __requested_cap = this->_M_length + __res; 00553 _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity, 00554 __alloc); 00555 if (this->_M_length) 00556 traits_type::copy(__r->_M_refdata(), _M_refdata(), 00557 this->_M_length); 00558 00559 __r->_M_length = this->_M_length; 00560 __r->_M_refdata()[this->_M_length] = _Rep::_S_terminal; 00561 return __r->_M_refdata(); 00562 } 00563 00564 template<typename _CharT, typename _Traits, typename _Alloc> 00565 void 00566 basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c) 00567 { 00568 if (__n > max_size()) 00569 __throw_length_error(__N("basic_string::resize")); 00570 const size_type __size = this->size(); 00571 if (__size < __n) 00572 this->append(__n - __size, __c); 00573 else if (__n < __size) 00574 this->erase(__n); 00575 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.) 00576 } 00577 00578 template<typename _CharT, typename _Traits, typename _Alloc> 00579 template<typename _InputIterator> 00580 basic_string<_CharT, _Traits, _Alloc>& 00581 basic_string<_CharT, _Traits, _Alloc>:: 00582 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1, 00583 _InputIterator __k2, __false_type) 00584 { 00585 const basic_string __s(__k1, __k2); 00586 const size_type __n1 = __i2 - __i1; 00587 if (this->max_size() - (this->size() - __n1) < __s.size()) 00588 __throw_length_error(__N("basic_string::_M_replace_dispatch")); 00589 return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(), 00590 __s.size()); 00591 } 00592 00593 template<typename _CharT, typename _Traits, typename _Alloc> 00594 basic_string<_CharT, _Traits, _Alloc>& 00595 basic_string<_CharT, _Traits, _Alloc>:: 00596 append(const basic_string& __str) 00597 { 00598 // Iff appending itself, string needs to pre-reserve the 00599 // correct size so that _M_mutate does not clobber the 00600 // pointer __str._M_data() formed here. 00601 const size_type __size = __str.size(); 00602 const size_type __len = __size + this->size(); 00603 if (__len > this->capacity()) 00604 this->reserve(__len); 00605 return _M_replace_safe(this->size(), size_type(0), __str._M_data(), 00606 __str.size()); 00607 } 00608 00609 template<typename _CharT, typename _Traits, typename _Alloc> 00610 basic_string<_CharT, _Traits, _Alloc>& 00611 basic_string<_CharT, _Traits, _Alloc>:: 00612 append(const basic_string& __str, size_type __pos, size_type __n) 00613 { 00614 // Iff appending itself, string needs to pre-reserve the 00615 // correct size so that _M_mutate does not clobber the 00616 // pointer __str._M_data() formed here. 00617 __str._M_check(__pos, "basic_string::append"); 00618 __n = __str._M_limit(__pos, __n); 00619 const size_type __len = __n + this->size(); 00620 if (__len > this->capacity()) 00621 this->reserve(__len); 00622 return _M_replace_safe(this->size(), size_type(0), __str._M_data() 00623 + __pos, __n); 00624 } 00625 00626 template<typename _CharT, typename _Traits, typename _Alloc> 00627 basic_string<_CharT, _Traits, _Alloc>& 00628 basic_string<_CharT, _Traits, _Alloc>:: 00629 append(const _CharT* __s, size_type __n) 00630 { 00631 __glibcxx_requires_string_len(__s, __n); 00632 const size_type __len = __n + this->size(); 00633 if (__len > this->capacity()) 00634 this->reserve(__len); 00635 return _M_replace_safe(this->size(), size_type(0), __s, __n); 00636 } 00637 00638 template<typename _CharT, typename _Traits, typename _Alloc> 00639 basic_string<_CharT, _Traits, _Alloc> 00640 operator+(const _CharT* __lhs, 00641 const basic_string<_CharT, _Traits, _Alloc>& __rhs) 00642 { 00643 __glibcxx_requires_string(__lhs); 00644 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00645 typedef typename __string_type::size_type __size_type; 00646 const __size_type __len = _Traits::length(__lhs); 00647 __string_type __str; 00648 __str.reserve(__len + __rhs.size()); 00649 __str.append(__lhs, __len); 00650 __str.append(__rhs); 00651 return __str; 00652 } 00653 00654 template<typename _CharT, typename _Traits, typename _Alloc> 00655 basic_string<_CharT, _Traits, _Alloc> 00656 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) 00657 { 00658 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00659 typedef typename __string_type::size_type __size_type; 00660 __string_type __str; 00661 const __size_type __len = __rhs.size(); 00662 __str.reserve(__len + 1); 00663 __str.append(__size_type(1), __lhs); 00664 __str.append(__rhs); 00665 return __str; 00666 } 00667 00668 template<typename _CharT, typename _Traits, typename _Alloc> 00669 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00670 basic_string<_CharT, _Traits, _Alloc>:: 00671 copy(_CharT* __s, size_type __n, size_type __pos) const 00672 { 00673 _M_check(__pos, "basic_string::copy"); 00674 __n = _M_limit(__pos, __n); 00675 __glibcxx_requires_string_len(__s, __n); 00676 if (__n) 00677 traits_type::copy(__s, _M_data() + __pos, __n); 00678 // 21.3.5.7 par 3: do not append null. (good.) 00679 return __n; 00680 } 00681 00682 template<typename _CharT, typename _Traits, typename _Alloc> 00683 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00684 basic_string<_CharT, _Traits, _Alloc>:: 00685 find(const _CharT* __s, size_type __pos, size_type __n) const 00686 { 00687 __glibcxx_requires_string_len(__s, __n); 00688 const size_type __size = this->size(); 00689 const _CharT* __data = _M_data(); 00690 for (; __pos + __n <= __size; ++__pos) 00691 if (traits_type::compare(__data + __pos, __s, __n) == 0) 00692 return __pos; 00693 return npos; 00694 } 00695 00696 template<typename _CharT, typename _Traits, typename _Alloc> 00697 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00698 basic_string<_CharT, _Traits, _Alloc>:: 00699 find(_CharT __c, size_type __pos) const 00700 { 00701 const size_type __size = this->size(); 00702 size_type __ret = npos; 00703 if (__pos < __size) 00704 { 00705 const _CharT* __data = _M_data(); 00706 const size_type __n = __size - __pos; 00707 const _CharT* __p = traits_type::find(__data + __pos, __n, __c); 00708 if (__p) 00709 __ret = __p - __data; 00710 } 00711 return __ret; 00712 } 00713 00714 template<typename _CharT, typename _Traits, typename _Alloc> 00715 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00716 basic_string<_CharT, _Traits, _Alloc>:: 00717 rfind(const _CharT* __s, size_type __pos, size_type __n) const 00718 { 00719 __glibcxx_requires_string_len(__s, __n); 00720 const size_type __size = this->size(); 00721 if (__n <= __size) 00722 { 00723 __pos = std::min(size_type(__size - __n), __pos); 00724 const _CharT* __data = _M_data(); 00725 do 00726 { 00727 if (traits_type::compare(__data + __pos, __s, __n) == 0) 00728 return __pos; 00729 } 00730 while (__pos-- > 0); 00731 } 00732 return npos; 00733 } 00734 00735 template<typename _CharT, typename _Traits, typename _Alloc> 00736 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00737 basic_string<_CharT, _Traits, _Alloc>:: 00738 rfind(_CharT __c, size_type __pos) const 00739 { 00740 size_type __size = this->size(); 00741 if (__size) 00742 { 00743 if (--__size > __pos) 00744 __size = __pos; 00745 for (++__size; __size-- > 0; ) 00746 if (traits_type::eq(_M_data()[__size], __c)) 00747 return __size; 00748 } 00749 return npos; 00750 } 00751 00752 template<typename _CharT, typename _Traits, typename _Alloc> 00753 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00754 basic_string<_CharT, _Traits, _Alloc>:: 00755 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const 00756 { 00757 __glibcxx_requires_string_len(__s, __n); 00758 for (; __n && __pos < this->size(); ++__pos) 00759 { 00760 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]); 00761 if (__p) 00762 return __pos; 00763 } 00764 return npos; 00765 } 00766 00767 template<typename _CharT, typename _Traits, typename _Alloc> 00768 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00769 basic_string<_CharT, _Traits, _Alloc>:: 00770 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const 00771 { 00772 __glibcxx_requires_string_len(__s, __n); 00773 size_type __size = this->size(); 00774 if (__size && __n) 00775 { 00776 if (--__size > __pos) 00777 __size = __pos; 00778 do 00779 { 00780 if (traits_type::find(__s, __n, _M_data()[__size])) 00781 return __size; 00782 } 00783 while (__size-- != 0); 00784 } 00785 return npos; 00786 } 00787 00788 template<typename _CharT, typename _Traits, typename _Alloc> 00789 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00790 basic_string<_CharT, _Traits, _Alloc>:: 00791 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const 00792 { 00793 __glibcxx_requires_string_len(__s, __n); 00794 for (; __pos < this->size(); ++__pos) 00795 if (!traits_type::find(__s, __n, _M_data()[__pos])) 00796 return __pos; 00797 return npos; 00798 } 00799 00800 template<typename _CharT, typename _Traits, typename _Alloc> 00801 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00802 basic_string<_CharT, _Traits, _Alloc>:: 00803 find_first_not_of(_CharT __c, size_type __pos) const 00804 { 00805 for (; __pos < this->size(); ++__pos) 00806 if (!traits_type::eq(_M_data()[__pos], __c)) 00807 return __pos; 00808 return npos; 00809 } 00810 00811 template<typename _CharT, typename _Traits, typename _Alloc> 00812 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00813 basic_string<_CharT, _Traits, _Alloc>:: 00814 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const 00815 { 00816 __glibcxx_requires_string_len(__s, __n); 00817 size_type __size = this->size(); 00818 if (__size) 00819 { 00820 if (--__size > __pos) 00821 __size = __pos; 00822 do 00823 { 00824 if (!traits_type::find(__s, __n, _M_data()[__size])) 00825 return __size; 00826 } 00827 while (__size--); 00828 } 00829 return npos; 00830 } 00831 00832 template<typename _CharT, typename _Traits, typename _Alloc> 00833 typename basic_string<_CharT, _Traits, _Alloc>::size_type 00834 basic_string<_CharT, _Traits, _Alloc>:: 00835 find_last_not_of(_CharT __c, size_type __pos) const 00836 { 00837 size_type __size = this->size(); 00838 if (__size) 00839 { 00840 if (--__size > __pos) 00841 __size = __pos; 00842 do 00843 { 00844 if (!traits_type::eq(_M_data()[__size], __c)) 00845 return __size; 00846 } 00847 while (__size--); 00848 } 00849 return npos; 00850 } 00851 00852 template<typename _CharT, typename _Traits, typename _Alloc> 00853 int 00854 basic_string<_CharT, _Traits, _Alloc>:: 00855 compare(size_type __pos, size_type __n, const basic_string& __str) const 00856 { 00857 _M_check(__pos, "basic_string::compare"); 00858 __n = _M_limit(__pos, __n); 00859 const size_type __osize = __str.size(); 00860 const size_type __len = std::min(__n, __osize); 00861 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len); 00862 if (!__r) 00863 __r = __n - __osize; 00864 return __r; 00865 } 00866 00867 template<typename _CharT, typename _Traits, typename _Alloc> 00868 int 00869 basic_string<_CharT, _Traits, _Alloc>:: 00870 compare(size_type __pos1, size_type __n1, const basic_string& __str, 00871 size_type __pos2, size_type __n2) const 00872 { 00873 _M_check(__pos1, "basic_string::compare"); 00874 __str._M_check(__pos2, "basic_string::compare"); 00875 __n1 = _M_limit(__pos1, __n1); 00876 __n2 = __str._M_limit(__pos2, __n2); 00877 const size_type __len = std::min(__n1, __n2); 00878 int __r = traits_type::compare(_M_data() + __pos1, 00879 __str.data() + __pos2, __len); 00880 if (!__r) 00881 __r = __n1 - __n2; 00882 return __r; 00883 } 00884 00885 template<typename _CharT, typename _Traits, typename _Alloc> 00886 int 00887 basic_string<_CharT, _Traits, _Alloc>:: 00888 compare(const _CharT* __s) const 00889 { 00890 __glibcxx_requires_string(__s); 00891 const size_type __size = this->size(); 00892 const size_type __osize = traits_type::length(__s); 00893 const size_type __len = std::min(__size, __osize); 00894 int __r = traits_type::compare(_M_data(), __s, __len); 00895 if (!__r) 00896 __r = __size - __osize; 00897 return __r; 00898 } 00899 00900 template<typename _CharT, typename _Traits, typename _Alloc> 00901 int 00902 basic_string <_CharT, _Traits, _Alloc>:: 00903 compare(size_type __pos, size_type __n1, const _CharT* __s) const 00904 { 00905 __glibcxx_requires_string(__s); 00906 _M_check(__pos, "basic_string::compare"); 00907 __n1 = _M_limit(__pos, __n1); 00908 const size_type __osize = traits_type::length(__s); 00909 const size_type __len = std::min(__n1, __osize); 00910 int __r = traits_type::compare(_M_data() + __pos, __s, __len); 00911 if (!__r) 00912 __r = __n1 - __osize; 00913 return __r; 00914 } 00915 00916 template<typename _CharT, typename _Traits, typename _Alloc> 00917 int 00918 basic_string <_CharT, _Traits, _Alloc>:: 00919 compare(size_type __pos, size_type __n1, const _CharT* __s, 00920 size_type __n2) const 00921 { 00922 __glibcxx_requires_string_len(__s, __n2); 00923 _M_check(__pos, "basic_string::compare"); 00924 __n1 = _M_limit(__pos, __n1); 00925 const size_type __len = std::min(__n1, __n2); 00926 int __r = traits_type::compare(_M_data() + __pos, __s, __len); 00927 if (!__r) 00928 __r = __n1 - __n2; 00929 return __r; 00930 } 00931 00932 // Inhibit implicit instantiations for required instantiations, 00933 // which are defined via explicit instantiations elsewhere. 00934 // NB: This syntax is a GNU extension. 00935 #if _GLIBCXX_EXTERN_TEMPLATE 00936 extern template class basic_string<char>; 00937 extern template 00938 basic_istream<char>& 00939 operator>>(basic_istream<char>&, string&); 00940 extern template 00941 basic_ostream<char>& 00942 operator<<(basic_ostream<char>&, const string&); 00943 extern template 00944 basic_istream<char>& 00945 getline(basic_istream<char>&, string&, char); 00946 extern template 00947 basic_istream<char>& 00948 getline(basic_istream<char>&, string&); 00949 00950 #ifdef _GLIBCXX_USE_WCHAR_T 00951 extern template class basic_string<wchar_t>; 00952 extern template 00953 basic_istream<wchar_t>& 00954 operator>>(basic_istream<wchar_t>&, wstring&); 00955 extern template 00956 basic_ostream<wchar_t>& 00957 operator<<(basic_ostream<wchar_t>&, const wstring&); 00958 extern template 00959 basic_istream<wchar_t>& 00960 getline(basic_istream<wchar_t>&, wstring&, wchar_t); 00961 extern template 00962 basic_istream<wchar_t>& 00963 getline(basic_istream<wchar_t>&, wstring&); 00964 #endif 00965 #endif 00966 } // namespace std 00967 00968 #endif

Generated on Wed Jun 9 11:18:15 2004 for libstdc++-v3 Source by doxygen 1.3.7