197403Sobrien// Components for manipulating sequences of characters -*- C++ -*- 297403Sobrien 3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 4169691Skan// 2006, 2007 597403Sobrien// Free Software Foundation, Inc. 697403Sobrien// 797403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 897403Sobrien// software; you can redistribute it and/or modify it under the 997403Sobrien// terms of the GNU General Public License as published by the 1097403Sobrien// Free Software Foundation; either version 2, or (at your option) 1197403Sobrien// any later version. 1297403Sobrien 1397403Sobrien// This library is distributed in the hope that it will be useful, 1497403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1597403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1697403Sobrien// GNU General Public License for more details. 1797403Sobrien 1897403Sobrien// You should have received a copy of the GNU General Public License along 1997403Sobrien// with this library; see the file COPYING. If not, write to the Free 20169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2197403Sobrien// USA. 2297403Sobrien 2397403Sobrien// As a special exception, you may use this file as part of a free software 2497403Sobrien// library without restriction. Specifically, if other files instantiate 2597403Sobrien// templates or use macros or inline functions from this file, or you compile 2697403Sobrien// this file and link it with other files to produce an executable, this 2797403Sobrien// file does not by itself cause the resulting executable to be covered by 2897403Sobrien// the GNU General Public License. This exception does not however 2997403Sobrien// invalidate any other reasons why the executable file might be covered by 3097403Sobrien// the GNU General Public License. 3197403Sobrien 32169691Skan/** @file basic_string.tcc 33169691Skan * This is an internal header file, included by other library headers. 34169691Skan * You should not attempt to use it directly. 35169691Skan */ 36169691Skan 3797403Sobrien// 3897403Sobrien// ISO C++ 14882: 21 Strings library 3997403Sobrien// 4097403Sobrien 4197403Sobrien// Written by Jason Merrill based upon the specification by Takanori Adachi 4297403Sobrien// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882. 4397403Sobrien 44132720Skan#ifndef _BASIC_STRING_TCC 45132720Skan#define _BASIC_STRING_TCC 1 4697403Sobrien 4797403Sobrien#pragma GCC system_header 4897403Sobrien 49169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 50169691Skan 51132720Skan template<typename _Type> 52132720Skan inline bool 53132720Skan __is_null_pointer(_Type* __ptr) 54132720Skan { return __ptr == 0; } 55132720Skan 56132720Skan template<typename _Type> 57132720Skan inline bool 58132720Skan __is_null_pointer(_Type) 59132720Skan { return false; } 60132720Skan 6197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 62132720Skan const typename basic_string<_CharT, _Traits, _Alloc>::size_type 6397403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 64132720Skan _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4; 6597403Sobrien 6697403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 67132720Skan const _CharT 6897403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 6997403Sobrien _Rep::_S_terminal = _CharT(); 7097403Sobrien 7197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 7297403Sobrien const typename basic_string<_CharT, _Traits, _Alloc>::size_type 7397403Sobrien basic_string<_CharT, _Traits, _Alloc>::npos; 7497403Sobrien 7597403Sobrien // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string) 7697403Sobrien // at static init time (before static ctors are run). 7797403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 7897403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 79132720Skan basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[ 80132720Skan (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) / 81132720Skan sizeof(size_type)]; 8297403Sobrien 8397403Sobrien // NB: This is the special case for Input Iterators, used in 8497403Sobrien // istreambuf_iterators, etc. 8597403Sobrien // Input Iterators have a cost structure very different from 8697403Sobrien // pointers, calling for a different coding style. 8797403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 88132720Skan template<typename _InIterator> 8997403Sobrien _CharT* 9097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 91132720Skan _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 9297403Sobrien input_iterator_tag) 9397403Sobrien { 94146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 9597403Sobrien if (__beg == __end && __a == _Alloc()) 96132720Skan return _S_empty_rep()._M_refdata(); 97146897Skan#endif 9897403Sobrien // Avoid reallocation for common case. 99132720Skan _CharT __buf[128]; 100132720Skan size_type __len = 0; 101132720Skan while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT)) 102132720Skan { 103132720Skan __buf[__len++] = *__beg; 104132720Skan ++__beg; 10597403Sobrien } 106132720Skan _Rep* __r = _Rep::_S_create(__len, size_type(0), __a); 107169691Skan _M_copy(__r->_M_refdata(), __buf, __len); 108132720Skan try 10997403Sobrien { 110132720Skan while (__beg != __end) 11197403Sobrien { 112132720Skan if (__len == __r->_M_capacity) 11397403Sobrien { 114132720Skan // Allocate more space. 115132720Skan _Rep* __another = _Rep::_S_create(__len + 1, __len, __a); 116169691Skan _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len); 117132720Skan __r->_M_destroy(__a); 118132720Skan __r = __another; 11997403Sobrien } 120132720Skan __r->_M_refdata()[__len++] = *__beg; 121132720Skan ++__beg; 12297403Sobrien } 12397403Sobrien } 124132720Skan catch(...) 12597403Sobrien { 126132720Skan __r->_M_destroy(__a); 12797403Sobrien __throw_exception_again; 12897403Sobrien } 129169691Skan __r->_M_set_length_and_sharable(__len); 130132720Skan return __r->_M_refdata(); 13197403Sobrien } 132132720Skan 13397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 134132720Skan template <typename _InIterator> 13597403Sobrien _CharT* 13697403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 137132720Skan _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, 13897403Sobrien forward_iterator_tag) 13997403Sobrien { 140146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 141107606Sobrien if (__beg == __end && __a == _Alloc()) 142132720Skan return _S_empty_rep()._M_refdata(); 143146897Skan#endif 14497403Sobrien // NB: Not required, but considered best practice. 145146897Skan if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0)) 146132720Skan __throw_logic_error(__N("basic_string::_S_construct NULL not valid")); 147117397Skan 148132720Skan const size_type __dnew = static_cast<size_type>(std::distance(__beg, 149132720Skan __end)); 15097403Sobrien // Check for out_of_range and length_error exceptions. 151132720Skan _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a); 152132720Skan try 15397403Sobrien { _S_copy_chars(__r->_M_refdata(), __beg, __end); } 154132720Skan catch(...) 155132720Skan { 156132720Skan __r->_M_destroy(__a); 15797403Sobrien __throw_exception_again; 15897403Sobrien } 159169691Skan __r->_M_set_length_and_sharable(__dnew); 16097403Sobrien return __r->_M_refdata(); 16197403Sobrien } 16297403Sobrien 16397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 16497403Sobrien _CharT* 16597403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 16697403Sobrien _S_construct(size_type __n, _CharT __c, const _Alloc& __a) 16797403Sobrien { 168146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 16997403Sobrien if (__n == 0 && __a == _Alloc()) 170132720Skan return _S_empty_rep()._M_refdata(); 171146897Skan#endif 17297403Sobrien // Check for out_of_range and length_error exceptions. 173132720Skan _Rep* __r = _Rep::_S_create(__n, size_type(0), __a); 174132720Skan if (__n) 175169691Skan _M_assign(__r->_M_refdata(), __n, __c); 176132720Skan 177169691Skan __r->_M_set_length_and_sharable(__n); 17897403Sobrien return __r->_M_refdata(); 17997403Sobrien } 18097403Sobrien 18197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 18297403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 18397403Sobrien basic_string(const basic_string& __str) 184132720Skan : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), 185132720Skan __str.get_allocator()), 186132720Skan __str.get_allocator()) 18797403Sobrien { } 18897403Sobrien 18997403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 19097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 19197403Sobrien basic_string(const _Alloc& __a) 19297403Sobrien : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) 19397403Sobrien { } 194132720Skan 19597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 19697403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 19797403Sobrien basic_string(const basic_string& __str, size_type __pos, size_type __n) 198132720Skan : _M_dataplus(_S_construct(__str._M_data() 199132720Skan + __str._M_check(__pos, 200132720Skan "basic_string::basic_string"), 201132720Skan __str._M_data() + __str._M_limit(__pos, __n) 202132720Skan + __pos, _Alloc()), _Alloc()) 20397403Sobrien { } 20497403Sobrien 20597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 20697403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 20797403Sobrien basic_string(const basic_string& __str, size_type __pos, 20897403Sobrien size_type __n, const _Alloc& __a) 209132720Skan : _M_dataplus(_S_construct(__str._M_data() 210132720Skan + __str._M_check(__pos, 211132720Skan "basic_string::basic_string"), 212132720Skan __str._M_data() + __str._M_limit(__pos, __n) 213132720Skan + __pos, __a), __a) 21497403Sobrien { } 21597403Sobrien 216132720Skan // TBD: DPG annotate 21797403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 21897403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 21997403Sobrien basic_string(const _CharT* __s, size_type __n, const _Alloc& __a) 22097403Sobrien : _M_dataplus(_S_construct(__s, __s + __n, __a), __a) 22197403Sobrien { } 22297403Sobrien 223132720Skan // TBD: DPG annotate 22497403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 22597403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 22697403Sobrien basic_string(const _CharT* __s, const _Alloc& __a) 227107606Sobrien : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : 228107606Sobrien __s + npos, __a), __a) 22997403Sobrien { } 23097403Sobrien 23197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 23297403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 23397403Sobrien basic_string(size_type __n, _CharT __c, const _Alloc& __a) 23497403Sobrien : _M_dataplus(_S_construct(__n, __c, __a), __a) 23597403Sobrien { } 236132720Skan 237132720Skan // TBD: DPG annotate 23897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 239132720Skan template<typename _InputIterator> 24097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 241132720Skan basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a) 24297403Sobrien : _M_dataplus(_S_construct(__beg, __end, __a), __a) 24397403Sobrien { } 24497403Sobrien 24597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 24697403Sobrien basic_string<_CharT, _Traits, _Alloc>& 247132720Skan basic_string<_CharT, _Traits, _Alloc>:: 248132720Skan assign(const basic_string& __str) 24997403Sobrien { 25097403Sobrien if (_M_rep() != __str._M_rep()) 25197403Sobrien { 25297403Sobrien // XXX MT 253132720Skan const allocator_type __a = this->get_allocator(); 25497403Sobrien _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator()); 25597403Sobrien _M_rep()->_M_dispose(__a); 25697403Sobrien _M_data(__tmp); 25797403Sobrien } 25897403Sobrien return *this; 25997403Sobrien } 260117397Skan 261169691Skan template<typename _CharT, typename _Traits, typename _Alloc> 262169691Skan basic_string<_CharT, _Traits, _Alloc>& 263169691Skan basic_string<_CharT, _Traits, _Alloc>:: 264169691Skan assign(const _CharT* __s, size_type __n) 265169691Skan { 266169691Skan __glibcxx_requires_string_len(__s, __n); 267169691Skan _M_check_length(this->size(), __n, "basic_string::assign"); 268169691Skan if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 269169691Skan return _M_replace_safe(size_type(0), this->size(), __s, __n); 270169691Skan else 271169691Skan { 272169691Skan // Work in-place. 273169691Skan const size_type __pos = __s - _M_data(); 274169691Skan if (__pos >= __n) 275169691Skan _M_copy(_M_data(), __s, __n); 276169691Skan else if (__pos) 277169691Skan _M_move(_M_data(), __s, __n); 278169691Skan _M_rep()->_M_set_length_and_sharable(__n); 279169691Skan return *this; 280169691Skan } 281117397Skan } 282117397Skan 283169691Skan template<typename _CharT, typename _Traits, typename _Alloc> 284169691Skan basic_string<_CharT, _Traits, _Alloc>& 285169691Skan basic_string<_CharT, _Traits, _Alloc>:: 286169691Skan append(size_type __n, _CharT __c) 287169691Skan { 288169691Skan if (__n) 289169691Skan { 290169691Skan _M_check_length(size_type(0), __n, "basic_string::append"); 291169691Skan const size_type __len = __n + this->size(); 292169691Skan if (__len > this->capacity() || _M_rep()->_M_is_shared()) 293169691Skan this->reserve(__len); 294169691Skan _M_assign(_M_data() + this->size(), __n, __c); 295169691Skan _M_rep()->_M_set_length_and_sharable(__len); 296169691Skan } 297169691Skan return *this; 298169691Skan } 299169691Skan 300169691Skan template<typename _CharT, typename _Traits, typename _Alloc> 301169691Skan basic_string<_CharT, _Traits, _Alloc>& 302169691Skan basic_string<_CharT, _Traits, _Alloc>:: 303169691Skan append(const _CharT* __s, size_type __n) 304169691Skan { 305169691Skan __glibcxx_requires_string_len(__s, __n); 306169691Skan if (__n) 307169691Skan { 308169691Skan _M_check_length(size_type(0), __n, "basic_string::append"); 309169691Skan const size_type __len = __n + this->size(); 310169691Skan if (__len > this->capacity() || _M_rep()->_M_is_shared()) 311169691Skan { 312169691Skan if (_M_disjunct(__s)) 313169691Skan this->reserve(__len); 314169691Skan else 315169691Skan { 316169691Skan const size_type __off = __s - _M_data(); 317169691Skan this->reserve(__len); 318169691Skan __s = _M_data() + __off; 319169691Skan } 320169691Skan } 321169691Skan _M_copy(_M_data() + this->size(), __s, __n); 322169691Skan _M_rep()->_M_set_length_and_sharable(__len); 323169691Skan } 324169691Skan return *this; 325169691Skan } 326169691Skan 327169691Skan template<typename _CharT, typename _Traits, typename _Alloc> 328169691Skan basic_string<_CharT, _Traits, _Alloc>& 329169691Skan basic_string<_CharT, _Traits, _Alloc>:: 330169691Skan append(const basic_string& __str) 331169691Skan { 332169691Skan const size_type __size = __str.size(); 333169691Skan if (__size) 334169691Skan { 335169691Skan const size_type __len = __size + this->size(); 336169691Skan if (__len > this->capacity() || _M_rep()->_M_is_shared()) 337169691Skan this->reserve(__len); 338169691Skan _M_copy(_M_data() + this->size(), __str._M_data(), __size); 339169691Skan _M_rep()->_M_set_length_and_sharable(__len); 340169691Skan } 341169691Skan return *this; 342169691Skan } 343169691Skan 344169691Skan template<typename _CharT, typename _Traits, typename _Alloc> 345169691Skan basic_string<_CharT, _Traits, _Alloc>& 346169691Skan basic_string<_CharT, _Traits, _Alloc>:: 347169691Skan append(const basic_string& __str, size_type __pos, size_type __n) 348169691Skan { 349169691Skan __str._M_check(__pos, "basic_string::append"); 350169691Skan __n = __str._M_limit(__pos, __n); 351169691Skan if (__n) 352169691Skan { 353169691Skan const size_type __len = __n + this->size(); 354169691Skan if (__len > this->capacity() || _M_rep()->_M_is_shared()) 355169691Skan this->reserve(__len); 356169691Skan _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n); 357169691Skan _M_rep()->_M_set_length_and_sharable(__len); 358169691Skan } 359169691Skan return *this; 360169691Skan } 361169691Skan 362117397Skan template<typename _CharT, typename _Traits, typename _Alloc> 363117397Skan basic_string<_CharT, _Traits, _Alloc>& 364117397Skan basic_string<_CharT, _Traits, _Alloc>:: 365117397Skan insert(size_type __pos, const _CharT* __s, size_type __n) 366117397Skan { 367132720Skan __glibcxx_requires_string_len(__s, __n); 368132720Skan _M_check(__pos, "basic_string::insert"); 369169691Skan _M_check_length(size_type(0), __n, "basic_string::insert"); 370169691Skan if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 371132720Skan return _M_replace_safe(__pos, size_type(0), __s, __n); 372117397Skan else 373117397Skan { 374169691Skan // Work in-place. 375117397Skan const size_type __off = __s - _M_data(); 376117397Skan _M_mutate(__pos, 0, __n); 377117397Skan __s = _M_data() + __off; 378117397Skan _CharT* __p = _M_data() + __pos; 379117397Skan if (__s + __n <= __p) 380169691Skan _M_copy(__p, __s, __n); 381117397Skan else if (__s >= __p) 382169691Skan _M_copy(__p, __s + __n, __n); 383117397Skan else 384117397Skan { 385132720Skan const size_type __nleft = __p - __s; 386169691Skan _M_copy(__p, __s, __nleft); 387169691Skan _M_copy(__p + __nleft, __p + __n, __n - __nleft); 388117397Skan } 389117397Skan return *this; 390117397Skan } 391117397Skan } 392132720Skan 393117397Skan template<typename _CharT, typename _Traits, typename _Alloc> 394117397Skan basic_string<_CharT, _Traits, _Alloc>& 395117397Skan basic_string<_CharT, _Traits, _Alloc>:: 396117397Skan replace(size_type __pos, size_type __n1, const _CharT* __s, 397117397Skan size_type __n2) 398117397Skan { 399132720Skan __glibcxx_requires_string_len(__s, __n2); 400132720Skan _M_check(__pos, "basic_string::replace"); 401132720Skan __n1 = _M_limit(__pos, __n1); 402169691Skan _M_check_length(__n1, __n2, "basic_string::replace"); 403132720Skan bool __left; 404169691Skan if (_M_disjunct(__s) || _M_rep()->_M_is_shared()) 405132720Skan return _M_replace_safe(__pos, __n1, __s, __n2); 406132720Skan else if ((__left = __s + __n2 <= _M_data() + __pos) 407132720Skan || _M_data() + __pos + __n1 <= __s) 408132720Skan { 409132720Skan // Work in-place: non-overlapping case. 410169691Skan size_type __off = __s - _M_data(); 411169691Skan __left ? __off : (__off += __n2 - __n1); 412132720Skan _M_mutate(__pos, __n1, __n2); 413169691Skan _M_copy(_M_data() + __pos, _M_data() + __off, __n2); 414132720Skan return *this; 415132720Skan } 416117397Skan else 417132720Skan { 418132720Skan // Todo: overlapping case. 419132720Skan const basic_string __tmp(__s, __n2); 420132720Skan return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2); 421132720Skan } 422117397Skan } 423132720Skan 42497403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 42597403Sobrien void 42697403Sobrien basic_string<_CharT, _Traits, _Alloc>::_Rep:: 42797403Sobrien _M_destroy(const _Alloc& __a) throw () 42897403Sobrien { 429132720Skan const size_type __size = sizeof(_Rep_base) + 430132720Skan (this->_M_capacity + 1) * sizeof(_CharT); 43197403Sobrien _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size); 43297403Sobrien } 43397403Sobrien 43497403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 43597403Sobrien void 436169691Skan basic_string<_CharT, _Traits, _Alloc>:: 437169691Skan _M_leak_hard() 43897403Sobrien { 439146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING 440132720Skan if (_M_rep() == &_S_empty_rep()) 441146897Skan return; 442146897Skan#endif 443132720Skan if (_M_rep()->_M_is_shared()) 44497403Sobrien _M_mutate(0, 0, 0); 44597403Sobrien _M_rep()->_M_set_leaked(); 44697403Sobrien } 44797403Sobrien 44897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 44997403Sobrien void 45097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 45197403Sobrien _M_mutate(size_type __pos, size_type __len1, size_type __len2) 45297403Sobrien { 453132720Skan const size_type __old_size = this->size(); 45497403Sobrien const size_type __new_size = __old_size + __len2 - __len1; 45597403Sobrien const size_type __how_much = __old_size - __pos - __len1; 456132720Skan 457169691Skan if (__new_size > this->capacity() || _M_rep()->_M_is_shared()) 45897403Sobrien { 45997403Sobrien // Must reallocate. 460132720Skan const allocator_type __a = get_allocator(); 461169691Skan _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a); 462132720Skan 463132720Skan if (__pos) 464169691Skan _M_copy(__r->_M_refdata(), _M_data(), __pos); 465132720Skan if (__how_much) 466169691Skan _M_copy(__r->_M_refdata() + __pos + __len2, 467169691Skan _M_data() + __pos + __len1, __how_much); 468132720Skan 46997403Sobrien _M_rep()->_M_dispose(__a); 47097403Sobrien _M_data(__r->_M_refdata()); 471132720Skan } 47297403Sobrien else if (__how_much && __len1 != __len2) 47397403Sobrien { 474169691Skan // Work in-place. 475169691Skan _M_move(_M_data() + __pos + __len2, 476169691Skan _M_data() + __pos + __len1, __how_much); 47797403Sobrien } 478169691Skan _M_rep()->_M_set_length_and_sharable(__new_size); 47997403Sobrien } 480132720Skan 48197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 48297403Sobrien void 483169691Skan basic_string<_CharT, _Traits, _Alloc>:: 484169691Skan reserve(size_type __res) 48597403Sobrien { 486132720Skan if (__res != this->capacity() || _M_rep()->_M_is_shared()) 48797403Sobrien { 48897403Sobrien // Make sure we don't shrink below the current size 48997403Sobrien if (__res < this->size()) 49097403Sobrien __res = this->size(); 491132720Skan const allocator_type __a = get_allocator(); 49297403Sobrien _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); 49397403Sobrien _M_rep()->_M_dispose(__a); 49497403Sobrien _M_data(__tmp); 49597403Sobrien } 49697403Sobrien } 497132720Skan 49897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 499169691Skan void 500169691Skan basic_string<_CharT, _Traits, _Alloc>:: 501169691Skan swap(basic_string& __s) 50297403Sobrien { 503132720Skan if (_M_rep()->_M_is_leaked()) 50497403Sobrien _M_rep()->_M_set_sharable(); 505132720Skan if (__s._M_rep()->_M_is_leaked()) 50697403Sobrien __s._M_rep()->_M_set_sharable(); 50797403Sobrien if (this->get_allocator() == __s.get_allocator()) 50897403Sobrien { 50997403Sobrien _CharT* __tmp = _M_data(); 51097403Sobrien _M_data(__s._M_data()); 51197403Sobrien __s._M_data(__tmp); 51297403Sobrien } 51397403Sobrien // The code below can usually be optimized away. 514132720Skan else 51597403Sobrien { 516132720Skan const basic_string __tmp1(_M_ibegin(), _M_iend(), 517132720Skan __s.get_allocator()); 518132720Skan const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 519132720Skan this->get_allocator()); 52097403Sobrien *this = __tmp2; 52197403Sobrien __s = __tmp1; 52297403Sobrien } 52397403Sobrien } 52497403Sobrien 52597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 52697403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::_Rep* 52797403Sobrien basic_string<_CharT, _Traits, _Alloc>::_Rep:: 528132720Skan _S_create(size_type __capacity, size_type __old_capacity, 529132720Skan const _Alloc& __alloc) 53097403Sobrien { 531132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 53297403Sobrien // 83. String::npos vs. string::max_size() 53397403Sobrien if (__capacity > _S_max_size) 534132720Skan __throw_length_error(__N("basic_string::_S_create")); 53597403Sobrien 53697403Sobrien // The standard places no restriction on allocating more memory 53797403Sobrien // than is strictly needed within this layer at the moment or as 538132720Skan // requested by an explicit application call to reserve(). 539132720Skan 540132720Skan // Many malloc implementations perform quite poorly when an 54197403Sobrien // application attempts to allocate memory in a stepwise fashion 54297403Sobrien // growing each allocation size by only 1 char. Additionally, 54397403Sobrien // it makes little sense to allocate less linear memory than the 54497403Sobrien // natural blocking size of the malloc implementation. 54597403Sobrien // Unfortunately, we would need a somewhat low-level calculation 54697403Sobrien // with tuned parameters to get this perfect for any particular 54797403Sobrien // malloc implementation. Fortunately, generalizations about 54897403Sobrien // common features seen among implementations seems to suffice. 54997403Sobrien 55097403Sobrien // __pagesize need not match the actual VM page size for good 55197403Sobrien // results in practice, thus we pick a common value on the low 55297403Sobrien // side. __malloc_header_size is an estimate of the amount of 55397403Sobrien // overhead per memory allocation (in practice seen N * sizeof 55497403Sobrien // (void*) where N is 0, 2 or 4). According to folklore, 55597403Sobrien // picking this value on the high side is better than 55697403Sobrien // low-balling it (especially when this algorithm is used with 55797403Sobrien // malloc implementations that allocate memory blocks rounded up 55897403Sobrien // to a size which is a power of 2). 559169691Skan const size_type __pagesize = 4096; 560169691Skan const size_type __malloc_header_size = 4 * sizeof(void*); 561132720Skan 562132720Skan // The below implements an exponential growth policy, necessary to 563132720Skan // meet amortized linear time requirements of the library: see 564132720Skan // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. 565132720Skan // It's active for allocations requiring an amount of memory above 566132720Skan // system pagesize. This is consistent with the requirements of the 567132720Skan // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html 568169691Skan if (__capacity > __old_capacity && __capacity < 2 * __old_capacity) 569132720Skan __capacity = 2 * __old_capacity; 570132720Skan 571132720Skan // NB: Need an array of char_type[__capacity], plus a terminating 572132720Skan // null char_type() element, plus enough for the _Rep data structure. 573132720Skan // Whew. Seemingly so needy, yet so elemental. 574132720Skan size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 575132720Skan 576132720Skan const size_type __adj_size = __size + __malloc_header_size; 577169691Skan if (__adj_size > __pagesize && __capacity > __old_capacity) 57897403Sobrien { 579132720Skan const size_type __extra = __pagesize - __adj_size % __pagesize; 58097403Sobrien __capacity += __extra / sizeof(_CharT); 581132720Skan // Never allocate a string bigger than _S_max_size. 582132720Skan if (__capacity > _S_max_size) 583132720Skan __capacity = _S_max_size; 58497403Sobrien __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 58597403Sobrien } 58697403Sobrien 58797403Sobrien // NB: Might throw, but no worries about a leak, mate: _Rep() 58897403Sobrien // does not throw. 58997403Sobrien void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); 59097403Sobrien _Rep *__p = new (__place) _Rep; 59197403Sobrien __p->_M_capacity = __capacity; 592169691Skan // ABI compatibility - 3.4.x set in _S_create both 593169691Skan // _M_refcount and _M_length. All callers of _S_create 594169691Skan // in basic_string.tcc then set just _M_length. 595169691Skan // In 4.0.x and later both _M_refcount and _M_length 596169691Skan // are initialized in the callers, unfortunately we can 597169691Skan // have 3.4.x compiled code with _S_create callers inlined 598169691Skan // calling 4.0.x+ _S_create. 599169691Skan __p->_M_set_sharable(); 60097403Sobrien return __p; 60197403Sobrien } 60297403Sobrien 60397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 60497403Sobrien _CharT* 60597403Sobrien basic_string<_CharT, _Traits, _Alloc>::_Rep:: 60697403Sobrien _M_clone(const _Alloc& __alloc, size_type __res) 60797403Sobrien { 60897403Sobrien // Requested capacity of the clone. 609132720Skan const size_type __requested_cap = this->_M_length + __res; 610132720Skan _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity, 611132720Skan __alloc); 612132720Skan if (this->_M_length) 613169691Skan _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length); 614132720Skan 615169691Skan __r->_M_set_length_and_sharable(this->_M_length); 61697403Sobrien return __r->_M_refdata(); 61797403Sobrien } 618132720Skan 61997403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 62097403Sobrien void 621169691Skan basic_string<_CharT, _Traits, _Alloc>:: 622169691Skan resize(size_type __n, _CharT __c) 62397403Sobrien { 624132720Skan const size_type __size = this->size(); 625169691Skan _M_check_length(__size, __n, "basic_string::resize"); 62697403Sobrien if (__size < __n) 62797403Sobrien this->append(__n - __size, __c); 62897403Sobrien else if (__n < __size) 62997403Sobrien this->erase(__n); 63097403Sobrien // else nothing (in particular, avoid calling _M_mutate() unnecessarily.) 63197403Sobrien } 632102782Skan 63397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 634132720Skan template<typename _InputIterator> 63597403Sobrien basic_string<_CharT, _Traits, _Alloc>& 63697403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 637132720Skan _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1, 638132720Skan _InputIterator __k2, __false_type) 63997403Sobrien { 640132720Skan const basic_string __s(__k1, __k2); 641132720Skan const size_type __n1 = __i2 - __i1; 642169691Skan _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch"); 643132720Skan return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(), 644132720Skan __s.size()); 64597403Sobrien } 64697403Sobrien 64797403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 64897403Sobrien basic_string<_CharT, _Traits, _Alloc>& 64997403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 650169691Skan _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2, 651169691Skan _CharT __c) 65297403Sobrien { 653169691Skan _M_check_length(__n1, __n2, "basic_string::_M_replace_aux"); 654169691Skan _M_mutate(__pos1, __n1, __n2); 655169691Skan if (__n2) 656169691Skan _M_assign(_M_data() + __pos1, __n2, __c); 657169691Skan return *this; 65897403Sobrien } 65997403Sobrien 66097403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 66197403Sobrien basic_string<_CharT, _Traits, _Alloc>& 66297403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 663169691Skan _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s, 664169691Skan size_type __n2) 66597403Sobrien { 666169691Skan _M_mutate(__pos1, __n1, __n2); 667169691Skan if (__n2) 668169691Skan _M_copy(_M_data() + __pos1, __s, __n2); 669169691Skan return *this; 67097403Sobrien } 671169691Skan 67297403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 67397403Sobrien basic_string<_CharT, _Traits, _Alloc> 67497403Sobrien operator+(const _CharT* __lhs, 67597403Sobrien const basic_string<_CharT, _Traits, _Alloc>& __rhs) 67697403Sobrien { 677132720Skan __glibcxx_requires_string(__lhs); 67897403Sobrien typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 67997403Sobrien typedef typename __string_type::size_type __size_type; 680132720Skan const __size_type __len = _Traits::length(__lhs); 68197403Sobrien __string_type __str; 68297403Sobrien __str.reserve(__len + __rhs.size()); 683132720Skan __str.append(__lhs, __len); 68497403Sobrien __str.append(__rhs); 68597403Sobrien return __str; 68697403Sobrien } 68797403Sobrien 68897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 68997403Sobrien basic_string<_CharT, _Traits, _Alloc> 69097403Sobrien operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) 69197403Sobrien { 69297403Sobrien typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 69397403Sobrien typedef typename __string_type::size_type __size_type; 69497403Sobrien __string_type __str; 695132720Skan const __size_type __len = __rhs.size(); 69697403Sobrien __str.reserve(__len + 1); 69797403Sobrien __str.append(__size_type(1), __lhs); 69897403Sobrien __str.append(__rhs); 69997403Sobrien return __str; 70097403Sobrien } 70197403Sobrien 70297403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 70397403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 70497403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 70597403Sobrien copy(_CharT* __s, size_type __n, size_type __pos) const 70697403Sobrien { 707132720Skan _M_check(__pos, "basic_string::copy"); 708132720Skan __n = _M_limit(__pos, __n); 709132720Skan __glibcxx_requires_string_len(__s, __n); 710132720Skan if (__n) 711169691Skan _M_copy(__s, _M_data() + __pos, __n); 71297403Sobrien // 21.3.5.7 par 3: do not append null. (good.) 71397403Sobrien return __n; 71497403Sobrien } 71597403Sobrien 71697403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 71797403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 71897403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 71997403Sobrien find(const _CharT* __s, size_type __pos, size_type __n) const 72097403Sobrien { 721132720Skan __glibcxx_requires_string_len(__s, __n); 722132720Skan const size_type __size = this->size(); 72397403Sobrien const _CharT* __data = _M_data(); 724169691Skan 725169691Skan if (__n == 0) 726169691Skan return __pos <= __size ? __pos : npos; 727169691Skan 728169691Skan if (__n <= __size) 729169691Skan { 730169691Skan for (; __pos <= __size - __n; ++__pos) 731169691Skan if (traits_type::eq(__data[__pos], __s[0]) 732169691Skan && traits_type::compare(__data + __pos + 1, 733169691Skan __s + 1, __n - 1) == 0) 734169691Skan return __pos; 735169691Skan } 73697403Sobrien return npos; 73797403Sobrien } 73897403Sobrien 73997403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 74097403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 74197403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 74297403Sobrien find(_CharT __c, size_type __pos) const 74397403Sobrien { 744169691Skan size_type __ret = npos; 745132720Skan const size_type __size = this->size(); 74697403Sobrien if (__pos < __size) 74797403Sobrien { 74897403Sobrien const _CharT* __data = _M_data(); 749132720Skan const size_type __n = __size - __pos; 75097403Sobrien const _CharT* __p = traits_type::find(__data + __pos, __n, __c); 75197403Sobrien if (__p) 75297403Sobrien __ret = __p - __data; 75397403Sobrien } 75497403Sobrien return __ret; 75597403Sobrien } 75697403Sobrien 75797403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 75897403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 75997403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 76097403Sobrien rfind(const _CharT* __s, size_type __pos, size_type __n) const 76197403Sobrien { 762132720Skan __glibcxx_requires_string_len(__s, __n); 763132720Skan const size_type __size = this->size(); 76497403Sobrien if (__n <= __size) 76597403Sobrien { 766117397Skan __pos = std::min(size_type(__size - __n), __pos); 76797403Sobrien const _CharT* __data = _M_data(); 768132720Skan do 76997403Sobrien { 77097403Sobrien if (traits_type::compare(__data + __pos, __s, __n) == 0) 77197403Sobrien return __pos; 772132720Skan } 77397403Sobrien while (__pos-- > 0); 77497403Sobrien } 77597403Sobrien return npos; 77697403Sobrien } 777132720Skan 77897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 77997403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 78097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 78197403Sobrien rfind(_CharT __c, size_type __pos) const 78297403Sobrien { 78397403Sobrien size_type __size = this->size(); 78497403Sobrien if (__size) 78597403Sobrien { 786132720Skan if (--__size > __pos) 787132720Skan __size = __pos; 788132720Skan for (++__size; __size-- > 0; ) 789132720Skan if (traits_type::eq(_M_data()[__size], __c)) 790132720Skan return __size; 79197403Sobrien } 79297403Sobrien return npos; 79397403Sobrien } 794132720Skan 79597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 79697403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 79797403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 79897403Sobrien find_first_of(const _CharT* __s, size_type __pos, size_type __n) const 79997403Sobrien { 800132720Skan __glibcxx_requires_string_len(__s, __n); 80197403Sobrien for (; __n && __pos < this->size(); ++__pos) 80297403Sobrien { 80397403Sobrien const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]); 80497403Sobrien if (__p) 80597403Sobrien return __pos; 80697403Sobrien } 80797403Sobrien return npos; 80897403Sobrien } 809132720Skan 81097403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 81197403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 81297403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 81397403Sobrien find_last_of(const _CharT* __s, size_type __pos, size_type __n) const 81497403Sobrien { 815132720Skan __glibcxx_requires_string_len(__s, __n); 81697403Sobrien size_type __size = this->size(); 81797403Sobrien if (__size && __n) 818132720Skan { 819132720Skan if (--__size > __pos) 82097403Sobrien __size = __pos; 82197403Sobrien do 82297403Sobrien { 82397403Sobrien if (traits_type::find(__s, __n, _M_data()[__size])) 82497403Sobrien return __size; 825132720Skan } 82697403Sobrien while (__size-- != 0); 82797403Sobrien } 82897403Sobrien return npos; 82997403Sobrien } 830132720Skan 83197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 83297403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 83397403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 83497403Sobrien find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const 83597403Sobrien { 836132720Skan __glibcxx_requires_string_len(__s, __n); 837132720Skan for (; __pos < this->size(); ++__pos) 838132720Skan if (!traits_type::find(__s, __n, _M_data()[__pos])) 839132720Skan return __pos; 84097403Sobrien return npos; 84197403Sobrien } 84297403Sobrien 84397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 84497403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 84597403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 84697403Sobrien find_first_not_of(_CharT __c, size_type __pos) const 84797403Sobrien { 848132720Skan for (; __pos < this->size(); ++__pos) 849132720Skan if (!traits_type::eq(_M_data()[__pos], __c)) 850132720Skan return __pos; 85197403Sobrien return npos; 85297403Sobrien } 85397403Sobrien 85497403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 85597403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 85697403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 85797403Sobrien find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const 85897403Sobrien { 859132720Skan __glibcxx_requires_string_len(__s, __n); 86097403Sobrien size_type __size = this->size(); 86197403Sobrien if (__size) 862132720Skan { 863132720Skan if (--__size > __pos) 86497403Sobrien __size = __pos; 86597403Sobrien do 86697403Sobrien { 86797403Sobrien if (!traits_type::find(__s, __n, _M_data()[__size])) 86897403Sobrien return __size; 869132720Skan } 87097403Sobrien while (__size--); 87197403Sobrien } 87297403Sobrien return npos; 87397403Sobrien } 87497403Sobrien 87597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 87697403Sobrien typename basic_string<_CharT, _Traits, _Alloc>::size_type 87797403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 87897403Sobrien find_last_not_of(_CharT __c, size_type __pos) const 87997403Sobrien { 88097403Sobrien size_type __size = this->size(); 88197403Sobrien if (__size) 882132720Skan { 883132720Skan if (--__size > __pos) 88497403Sobrien __size = __pos; 88597403Sobrien do 88697403Sobrien { 88797403Sobrien if (!traits_type::eq(_M_data()[__size], __c)) 88897403Sobrien return __size; 889132720Skan } 89097403Sobrien while (__size--); 89197403Sobrien } 89297403Sobrien return npos; 89397403Sobrien } 894132720Skan 89597403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 89697403Sobrien int 89797403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 89897403Sobrien compare(size_type __pos, size_type __n, const basic_string& __str) const 89997403Sobrien { 900132720Skan _M_check(__pos, "basic_string::compare"); 901132720Skan __n = _M_limit(__pos, __n); 902132720Skan const size_type __osize = __str.size(); 903132720Skan const size_type __len = std::min(__n, __osize); 90497403Sobrien int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len); 90597403Sobrien if (!__r) 906259694Spfg __r = _S_compare(__n, __osize); 90797403Sobrien return __r; 90897403Sobrien } 90997403Sobrien 91097403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 91197403Sobrien int 91297403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 91397403Sobrien compare(size_type __pos1, size_type __n1, const basic_string& __str, 91497403Sobrien size_type __pos2, size_type __n2) const 91597403Sobrien { 916132720Skan _M_check(__pos1, "basic_string::compare"); 917132720Skan __str._M_check(__pos2, "basic_string::compare"); 918132720Skan __n1 = _M_limit(__pos1, __n1); 919132720Skan __n2 = __str._M_limit(__pos2, __n2); 920132720Skan const size_type __len = std::min(__n1, __n2); 921132720Skan int __r = traits_type::compare(_M_data() + __pos1, 92297403Sobrien __str.data() + __pos2, __len); 92397403Sobrien if (!__r) 924259694Spfg __r = _S_compare(__n1, __n2); 92597403Sobrien return __r; 92697403Sobrien } 92797403Sobrien 92897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 92997403Sobrien int 93097403Sobrien basic_string<_CharT, _Traits, _Alloc>:: 93197403Sobrien compare(const _CharT* __s) const 93297403Sobrien { 933132720Skan __glibcxx_requires_string(__s); 934132720Skan const size_type __size = this->size(); 935132720Skan const size_type __osize = traits_type::length(__s); 936132720Skan const size_type __len = std::min(__size, __osize); 937107606Sobrien int __r = traits_type::compare(_M_data(), __s, __len); 93897403Sobrien if (!__r) 939259694Spfg __r = _S_compare(__size, __osize); 94097403Sobrien return __r; 94197403Sobrien } 94297403Sobrien 94397403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 94497403Sobrien int 94597403Sobrien basic_string <_CharT, _Traits, _Alloc>:: 94697403Sobrien compare(size_type __pos, size_type __n1, const _CharT* __s) const 94797403Sobrien { 948132720Skan __glibcxx_requires_string(__s); 949132720Skan _M_check(__pos, "basic_string::compare"); 950132720Skan __n1 = _M_limit(__pos, __n1); 951132720Skan const size_type __osize = traits_type::length(__s); 952132720Skan const size_type __len = std::min(__n1, __osize); 95397403Sobrien int __r = traits_type::compare(_M_data() + __pos, __s, __len); 95497403Sobrien if (!__r) 955259694Spfg __r = _S_compare(__n1, __osize); 95697403Sobrien return __r; 95797403Sobrien } 95897403Sobrien 95997403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 96097403Sobrien int 96197403Sobrien basic_string <_CharT, _Traits, _Alloc>:: 962132720Skan compare(size_type __pos, size_type __n1, const _CharT* __s, 96397403Sobrien size_type __n2) const 96497403Sobrien { 965132720Skan __glibcxx_requires_string_len(__s, __n2); 966132720Skan _M_check(__pos, "basic_string::compare"); 967132720Skan __n1 = _M_limit(__pos, __n1); 968132720Skan const size_type __len = std::min(__n1, __n2); 96997403Sobrien int __r = traits_type::compare(_M_data() + __pos, __s, __len); 97097403Sobrien if (!__r) 971259694Spfg __r = _S_compare(__n1, __n2); 97297403Sobrien return __r; 97397403Sobrien } 97497403Sobrien 97597403Sobrien // Inhibit implicit instantiations for required instantiations, 976132720Skan // which are defined via explicit instantiations elsewhere. 97797403Sobrien // NB: This syntax is a GNU extension. 978132720Skan#if _GLIBCXX_EXTERN_TEMPLATE 97997403Sobrien extern template class basic_string<char>; 980132720Skan extern template 981132720Skan basic_istream<char>& 98297403Sobrien operator>>(basic_istream<char>&, string&); 983132720Skan extern template 984132720Skan basic_ostream<char>& 98597403Sobrien operator<<(basic_ostream<char>&, const string&); 986132720Skan extern template 987132720Skan basic_istream<char>& 98897403Sobrien getline(basic_istream<char>&, string&, char); 989132720Skan extern template 990132720Skan basic_istream<char>& 99197403Sobrien getline(basic_istream<char>&, string&); 99297403Sobrien 993132720Skan#ifdef _GLIBCXX_USE_WCHAR_T 99497403Sobrien extern template class basic_string<wchar_t>; 995132720Skan extern template 996132720Skan basic_istream<wchar_t>& 99797403Sobrien operator>>(basic_istream<wchar_t>&, wstring&); 998132720Skan extern template 999132720Skan basic_ostream<wchar_t>& 100097403Sobrien operator<<(basic_ostream<wchar_t>&, const wstring&); 1001132720Skan extern template 1002132720Skan basic_istream<wchar_t>& 100397403Sobrien getline(basic_istream<wchar_t>&, wstring&, wchar_t); 1004132720Skan extern template 1005132720Skan basic_istream<wchar_t>& 100697403Sobrien getline(basic_istream<wchar_t>&, wstring&); 1007107606Sobrien#endif 1008117397Skan#endif 100997403Sobrien 1010169691Skan_GLIBCXX_END_NAMESPACE 1011169691Skan 101297403Sobrien#endif 1013