# basic_string.h

Go to the documentation of this file.

    00001 // Components for manipulating sequences of characters -*- C++ -*-
    00002
    00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
    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
    00040 #ifndef _CPP_BITS_STRING_H
    00041 #define _CPP_BITS_STRING_H        1
    00042
    00043 #pragma GCC system_header
    00044
    00045 #include <bits/atomicity.h>
    00046
    00047 namespace std
    00048 {
    00107   // 21.3  Template class basic_string
    00108   template<typename _CharT, typename _Traits, typename _Alloc>
    00109     class basic_string
    00110     {
    00111       // Types:
    00112     public:
    00113       typedef _Traits                       traits_type;
    00114       typedef typename _Traits::char_type           value_type;
    00115       typedef _Alloc                        allocator_type;
    00116       typedef typename _Alloc::size_type            size_type;
    00117       typedef typename _Alloc::difference_type          difference_type;
    00118       typedef typename _Alloc::reference            reference;
    00119       typedef typename _Alloc::const_reference          const_reference;
    00120       typedef typename _Alloc::pointer              pointer;
    00121       typedef typename _Alloc::const_pointer            const_pointer;
    00122       typedef __gnu_cxx::__normal_iterator<pointer, basic_string>  iterator;
    00123       typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
    00124                                                             const_iterator;
    00125       typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
    00126       typedef std::reverse_iterator<iterator>           reverse_iterator;
    00127
    00128     private:
    00129       // _Rep: string representation
    00130       //   Invariants:
    00131       //   1. String really contains _M_length + 1 characters; last is set
    00132       //      to 0 only on call to c_str().  We avoid instantiating
    00133       //      _CharT() where the interface does not require it.
    00134       //   2. _M_capacity >= _M_length
    00135       //      Allocated memory is always _M_capacity + (1 * sizeof(_CharT)).
    00136       //   3. _M_references has three states:
    00137       //      -1: leaked, one reference, no ref-copies allowed, non-const.
    00138       //       0: one reference, non-const.
    00139       //     n>0: n + 1 references, operations require a lock, const.
    00140       //   4. All fields==0 is an empty string, given the extra storage
    00141       //      beyond-the-end for a null terminator; thus, the shared
    00142       //      empty string representation needs no constructor.
    00143       struct _Rep
    00144       {
    00145     // Types:
    00146     typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc;
    00147
    00148     // (Public) Data members:
    00149
    00150     // The maximum number of individual char_type elements of an
    00151     // individual string is determined by _S_max_size. This is the
    00152     // value that will be returned by max_size().  (Whereas npos
    00153     // is the maximum number of bytes the allocator can allocate.)
    00154     // If one was to divvy up the theoretical largest size string,
    00155     // with a terminating character and m _CharT elements, it'd
    00156     // look like this:
    00157     // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
    00158     // Solving for m:
    00159     // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
    00160     // In addition, this implementation quarters this ammount.
    00161     static const size_type  _S_max_size;
    00162     static const _CharT     _S_terminal;
    00163
    00164     size_type       _M_length;
    00165     size_type       _M_capacity;
    00166     _Atomic_word        _M_references;
    00167
    00168         bool
    00169     _M_is_leaked() const
    00170         { return _M_references < 0; }
    00171
    00172         bool
    00173     _M_is_shared() const
    00174         { return _M_references > 0; }
    00175
    00176         void
    00177     _M_set_leaked()
    00178         { _M_references = -1; }
    00179
    00180         void
    00181     _M_set_sharable()
    00182         { _M_references = 0; }
    00183
    00184     _CharT*
    00185     _M_refdata() throw()
    00186     { return reinterpret_cast<_CharT*>(this + 1); }
    00187
    00188     _CharT&
    00189     operator[](size_t __s) throw()
    00190     { return _M_refdata() [__s]; }
    00191
    00192     _CharT*
    00193     _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
    00194     {
    00195       return (!_M_is_leaked() && __alloc1 == __alloc2)
    00196               ? _M_refcopy() : _M_clone(__alloc1);
    00197     }
    00198
    00199     // Create & Destroy
    00200     static _Rep*
    00201     _S_create(size_t, const _Alloc&);
    00202
    00203     void
    00204     _M_dispose(const _Alloc& __a)
    00205     {
    00206       if (__exchange_and_add(&_M_references, -1) <= 0)
    00207         _M_destroy(__a);
    00208     }  // XXX MT
    00209
    00210     void
    00211     _M_destroy(const _Alloc&) throw();
    00212
    00213     _CharT*
    00214     _M_refcopy() throw()
    00215     {
    00216       __atomic_add(&_M_references, 1);
    00217       return _M_refdata();
    00218     }  // XXX MT
    00219
    00220     _CharT*
    00221     _M_clone(const _Alloc&, size_type __res = 0);
    00222       };
    00223
    00224       // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
    00225       struct _Alloc_hider : _Alloc
    00226       {
    00227     _Alloc_hider(_CharT* __dat, const _Alloc& __a)
    00228     : _Alloc(__a), _M_p(__dat) { }
    00229
    00230     _CharT* _M_p; // The actual data.
    00231       };
    00232
    00233     public:
    00234       // Data Members (public):
    00235       // NB: This is an unsigned type, and thus represents the maximum
    00236       // size that the allocator can hold.
    00237       static const size_type    npos = static_cast<size_type>(-1);
    00238
    00239     private:
    00240       // Data Members (private):
    00241       mutable _Alloc_hider  _M_dataplus;
    00242
    00243       // The following storage is init'd to 0 by the linker, resulting
    00244       // (carefully) in an empty string with one reference.
    00245       static size_type _S_empty_rep_storage[(sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
    00246
    00247       _CharT*
    00248       _M_data() const
    00249       { return  _M_dataplus._M_p; }
    00250
    00251       _CharT*
    00252       _M_data(_CharT* __p)
    00253       { return (_M_dataplus._M_p = __p); }
    00254
    00255       _Rep*
    00256       _M_rep() const
    00257       { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
    00258
    00259       // For the internal use we have functions similar to `begin'/`end'
    00260       // but they do not call _M_leak.
    00261       iterator
    00262       _M_ibegin() const { return iterator(_M_data()); }
    00263
    00264       iterator
    00265       _M_iend() const { return iterator(_M_data() + this->size()); }
    00266
    00267       void
    00268       _M_leak()    // for use in begin() & non-const op[]
    00269       {
    00270     if (!_M_rep()->_M_is_leaked())
    00271       _M_leak_hard();
    00272       }
    00273
    00274       iterator
    00275       _M_check(size_type __pos) const
    00276       {
    00277     if (__pos > this->size())
    00278       __throw_out_of_range("basic_string::_M_check");
    00279     return _M_ibegin() + __pos;
    00280       }
    00281
    00282       // NB: _M_fold doesn't check for a bad __pos1 value.
    00283       iterator
    00284       _M_fold(size_type __pos, size_type __off) const
    00285       {
    00286     bool __testoff =  __off < this->size() - __pos;
    00287     size_type __newoff = __testoff ? __off : this->size() - __pos;
    00288     return (_M_ibegin() + __pos + __newoff);
    00289       }
    00290
    00291       // _S_copy_chars is a separate template to permit specialization
    00292       // to optimize for the common case of pointers as iterators.
    00293       template<class _Iterator>
    00294         static void
    00295         _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
    00296         {
    00297       for (; __k1 != __k2; ++__k1, ++__p)
    00298         traits_type::assign(*__p, *__k1); // These types are off.
    00299     }
    00300
    00301       static void
    00302       _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
    00303       { _S_copy_chars(__p, __k1.base(), __k2.base()); }
    00304
    00305       static void
    00306       _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
    00307       { _S_copy_chars(__p, __k1.base(), __k2.base()); }
    00308
    00309       static void
    00310       _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
    00311       { traits_type::copy(__p, __k1, __k2 - __k1); }
    00312
    00313       static void
    00314       _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
    00315       { traits_type::copy(__p, __k1, __k2 - __k1); }
    00316
    00317       void
    00318       _M_mutate(size_type __pos, size_type __len1, size_type __len2);
    00319
    00320       void
    00321       _M_leak_hard();
    00322
    00323       static _Rep&
    00324       _S_empty_rep()
    00325       { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); }
    00326
    00327     public:
    00328       // Construct/copy/destroy:
    00329       // NB: We overload ctors in some cases instead of using default
    00330       // arguments, per 17.4.4.4 para. 2 item 2.
    00331
    00332       inline
    00333       basic_string();
    00334
    00335       explicit
    00336       basic_string(const _Alloc& __a);
    00337
    00338       // NB: per LWG issue 42, semantics different from IS:
    00339       basic_string(const basic_string& __str);
    00340       basic_string(const basic_string& __str, size_type __pos,
    00341            size_type __n = npos);
    00342       basic_string(const basic_string& __str, size_type __pos,
    00343            size_type __n, const _Alloc& __a);
    00344
    00345       basic_string(const _CharT* __s, size_type __n,
    00346            const _Alloc& __a = _Alloc());
    00347       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
    00348       basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
    00349
    00350       template<class _InputIterator>
    00351         basic_string(_InputIterator __beg, _InputIterator __end,
    00352              const _Alloc& __a = _Alloc());
    00353
    00354       ~basic_string()
    00355       { _M_rep()->_M_dispose(this->get_allocator()); }
    00356
    00357       basic_string&
    00358       operator=(const basic_string& __str) { return this->assign(__str); }
    00359
    00360       basic_string&
    00361       operator=(const _CharT* __s) { return this->assign(__s); }
    00362
    00363       basic_string&
    00364       operator=(_CharT __c) { return this->assign(1, __c); }
    00365
    00366       // Iterators:
    00367       iterator
    00368       begin()
    00369       {
    00370     _M_leak();
    00371     return iterator(_M_data());
    00372       }
    00373
    00374       const_iterator
    00375       begin() const
    00376       { return const_iterator(_M_data()); }
    00377
    00378       iterator
    00379       end()
    00380       {
    00381          _M_leak();
    00382      return iterator(_M_data() + this->size());
    00383       }
    00384
    00385       const_iterator
    00386       end() const
    00387       { return const_iterator(_M_data() + this->size()); }
    00388
    00389       reverse_iterator
    00390       rbegin()
    00391       { return reverse_iterator(this->end()); }
    00392
    00393       const_reverse_iterator
    00394       rbegin() const
    00395       { return const_reverse_iterator(this->end()); }
    00396
    00397       reverse_iterator
    00398       rend()
    00399       { return reverse_iterator(this->begin()); }
    00400
    00401       const_reverse_iterator
    00402       rend() const
    00403       { return const_reverse_iterator(this->begin()); }
    00404
    00405     public:
    00406       // Capacity:
    00407       size_type
    00408       size() const { return _M_rep()->_M_length; }
    00409
    00410       size_type
    00411       length() const { return _M_rep()->_M_length; }
    00412
    00413       size_type
    00414       max_size() const { return _Rep::_S_max_size; }
    00415
    00416       void
    00417       resize(size_type __n, _CharT __c);
    00418
    00419       void
    00420       resize(size_type __n) { this->resize(__n, _CharT()); }
    00421
    00422       size_type
    00423       capacity() const { return _M_rep()->_M_capacity; }
    00424
    00425       void
    00426       reserve(size_type __res_arg = 0);
    00427
    00428       void
    00429       clear() { _M_mutate(0, this->size(), 0); }
    00430
    00431       bool
    00432       empty() const { return this->size() == 0; }
    00433
    00434       // Element access:
    00435       const_reference
    00436       operator[] (size_type __pos) const
    00437       { return _M_data()[__pos]; }
    00438
    00439       reference
    00440       operator[](size_type __pos)
    00441       {
    00442     _M_leak();
    00443     return _M_data()[__pos];
    00444       }
    00445
    00446       const_reference
    00447       at(size_type __n) const
    00448       {
    00449     if (__n >= this->size())
    00450       __throw_out_of_range("basic_string::at");
    00451     return _M_data()[__n];
    00452       }
    00453
    00454       reference
    00455       at(size_type __n)
    00456       {
    00457     if (__n >= size())
    00458       __throw_out_of_range("basic_string::at");
    00459     _M_leak();
    00460     return _M_data()[__n];
    00461       }
    00462
    00463       // Modifiers:
    00464       basic_string&
    00465       operator+=(const basic_string& __str) { return this->append(__str); }
    00466
    00467       basic_string&
    00468       operator+=(const _CharT* __s) { return this->append(__s); }
    00469
    00470       basic_string&
    00471       operator+=(_CharT __c) { return this->append(size_type(1), __c); }
    00472
    00473       basic_string&
    00474       append(const basic_string& __str);
    00475
    00476       basic_string&
    00477       append(const basic_string& __str, size_type __pos, size_type __n);
    00478
    00479       basic_string&
    00480       append(const _CharT* __s, size_type __n);
    00481
    00482       basic_string&
    00483       append(const _CharT* __s)
    00484       { return this->append(__s, traits_type::length(__s)); }
    00485
    00486       basic_string&
    00487       append(size_type __n, _CharT __c);
    00488
    00489       template<class _InputIterator>
    00490         basic_string&
    00491         append(_InputIterator __first, _InputIterator __last)
    00492         { return this->replace(_M_iend(), _M_iend(), __first, __last); }
    00493
    00494       void
    00495       push_back(_CharT __c)
    00496       { this->replace(_M_iend(), _M_iend(), 1, __c); }
    00497
    00498       basic_string&
    00499       assign(const basic_string& __str);
    00500
    00501       basic_string&
    00502       assign(const basic_string& __str, size_type __pos, size_type __n)
    00503       {
    00504     const size_type __strsize = __str.size();
    00505     if (__pos > __strsize)
    00506       __throw_out_of_range("basic_string::assign");
    00507     const bool __testn = __n < __strsize - __pos;
    00508     const size_type __newsize = __testn ? __n : __strsize - __pos;
    00509     return this->assign(__str._M_data() + __pos, __newsize);
    00510       }
    00511
    00512       basic_string&
    00513       assign(const _CharT* __s, size_type __n)
    00514       {
    00515     if (__n > this->max_size())
    00516       __throw_length_error("basic_string::assign");
    00517     if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
    00518         || less<const _CharT*>()(_M_data() + this->size(), __s))
    00519       return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n);
    00520     else
    00521       {
    00522         // Work in-place
    00523         const size_type __pos = __s - _M_data();
    00524         if (__pos >= __n)
    00525           traits_type::copy(_M_data(), __s, __n);
    00526         else if (__pos)
    00527           traits_type::move(_M_data(), __s, __n);
    00528         _M_rep()->_M_length = __n;
    00529         _M_data()[__n] = _Rep::_S_terminal;
    00530         return *this;
    00531       }
    00532       }
    00533
    00534       basic_string&
    00535       assign(const _CharT* __s)
    00536       { return this->assign(__s, traits_type::length(__s)); }
    00537
    00538       basic_string&
    00539       assign(size_type __n, _CharT __c)
    00540       { return this->replace(_M_ibegin(), _M_iend(), __n, __c); }
    00541
    00542       template<class _InputIterator>
    00543         basic_string&
    00544         assign(_InputIterator __first, _InputIterator __last)
    00545         { return this->replace(_M_ibegin(), _M_iend(), __first, __last); }
    00546
    00547       void
    00548       insert(iterator __p, size_type __n, _CharT __c)
    00549       { this->replace(__p, __p, __n, __c);  }
    00550
    00551       template<class _InputIterator>
    00552         void insert(iterator __p, _InputIterator __beg, _InputIterator __end)
    00553         { this->replace(__p, __p, __beg, __end); }
    00554
    00555       basic_string&
    00556       insert(size_type __pos1, const basic_string& __str)
    00557       { return this->insert(__pos1, __str, 0, __str.size()); }
    00558
    00559       basic_string&
    00560       insert(size_type __pos1, const basic_string& __str,
    00561          size_type __pos2, size_type __n)
    00562       {
    00563     const size_type __strsize = __str.size();
    00564     if (__pos2 > __strsize)
    00565       __throw_out_of_range("basic_string::insert");
    00566     const bool __testn = __n < __strsize - __pos2;
    00567     const size_type __newsize = __testn ? __n : __strsize - __pos2;
    00568     return this->insert(__pos1, __str._M_data() + __pos2, __newsize);
    00569       }
    00570
    00571       basic_string&
    00572       insert(size_type __pos, const _CharT* __s, size_type __n)
    00573       {
    00574     const size_type __size = this->size();
    00575     if (__pos > __size)
    00576       __throw_out_of_range("basic_string::insert");
    00577     if (__size > this->max_size() - __n)
    00578       __throw_length_error("basic_string::insert");
    00579     if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
    00580         || less<const _CharT*>()(_M_data() + __size, __s))
    00581       return _M_replace_safe(_M_ibegin() + __pos, _M_ibegin() + __pos,
    00582                  __s, __s + __n);
    00583     else
    00584       {
    00585         // Work in-place. If _M_mutate reallocates the string, __s
    00586         // does not point anymore to valid data, therefore we save its
    00587         // offset, then we restore it.
    00588         const size_type __off = __s - _M_data();
    00589         _M_mutate(__pos, 0, __n);
    00590         __s = _M_data() + __off;
    00591         _CharT* __p = _M_data() + __pos;
    00592         if (__s  + __n <= __p)
    00593           traits_type::copy(__p, __s, __n);
    00594         else if (__s >= __p)
    00595           traits_type::copy(__p, __s + __n, __n);
    00596         else
    00597           {
    00598         traits_type::copy(__p, __s, __p - __s);
    00599         traits_type::copy(__p + (__p - __s), __p + __n, __n - (__p - __s));
    00600           }
    00601         return *this;
    00602       }
    00603        }
    00604
    00605       basic_string&
    00606       insert(size_type __pos, const _CharT* __s)
    00607       { return this->insert(__pos, __s, traits_type::length(__s)); }
    00608
    00609       basic_string&
    00610       insert(size_type __pos, size_type __n, _CharT __c)
    00611       {
    00612     this->insert(_M_check(__pos), __n, __c);
    00613     return *this;
    00614       }
    00615
    00616       iterator
    00617       insert(iterator __p, _CharT __c = _CharT())
    00618       {
    00619     size_type __pos = __p - _M_ibegin();
    00620     this->insert(_M_check(__pos), size_type(1), __c);
    00621     _M_rep()->_M_set_leaked();
    00622     return this->_M_ibegin() + __pos;
    00623       }
    00624
    00625       basic_string&
    00626       erase(size_type __pos = 0, size_type __n = npos)
    00627       {
    00628     return this->replace(_M_check(__pos), _M_fold(__pos, __n),
    00629                  _M_data(), _M_data());
    00630       }
    00631
    00632       iterator
    00633       erase(iterator __position)
    00634       {
    00635     size_type __i = __position - _M_ibegin();
    00636         this->replace(__position, __position + 1, _M_data(), _M_data());
    00637     _M_rep()->_M_set_leaked();
    00638     return _M_ibegin() + __i;
    00639       }
    00640
    00641       iterator
    00642       erase(iterator __first, iterator __last)
    00643       {
    00644         size_type __i = __first - _M_ibegin();
    00645     this->replace(__first, __last, _M_data(), _M_data());
    00646     _M_rep()->_M_set_leaked();
    00647        return _M_ibegin() + __i;
    00648       }
    00649
    00650       basic_string&
    00651       replace(size_type __pos, size_type __n, const basic_string& __str)
    00652       { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
    00653
    00654       basic_string&
    00655       replace(size_type __pos1, size_type __n1, const basic_string& __str,
    00656           size_type __pos2, size_type __n2);
    00657
    00658       basic_string&
    00659       replace(size_type __pos, size_type __n1, const _CharT* __s,
    00660           size_type __n2)
    00661       {
    00662     const size_type __size = this->size();
    00663     if (__pos > __size)
    00664       __throw_out_of_range("basic_string::replace");
    00665     const bool __testn1 = __n1 < __size - __pos;
    00666     const size_type __foldn1 = __testn1 ? __n1 : __size - __pos;
    00667     if (__size - __foldn1 > this->max_size() - __n2)
    00668       __throw_length_error("basic_string::replace");
    00669     if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
    00670         || less<const _CharT*>()(_M_data() + __size, __s))
    00671       return _M_replace_safe(_M_ibegin() + __pos,
    00672                  _M_ibegin() + __pos + __foldn1, __s, __s + __n2);
    00673     // Todo: optimized in-place replace.
    00674     else return
    00675            _M_replace(_M_ibegin() + __pos, _M_ibegin() + __pos + __foldn1,
    00676               __s, __s + __n2,
    00677               typename iterator_traits<const _CharT*>::iterator_category());
    00678       }
    00679
    00680       basic_string&
    00681       replace(size_type __pos, size_type __n1, const _CharT* __s)
    00682       { return this->replace(__pos, __n1, __s, traits_type::length(__s)); }
    00683
    00684       basic_string&
    00685       replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
    00686       { return this->replace(_M_check(__pos), _M_fold(__pos, __n1), __n2, __c); }
    00687
    00688       basic_string&
    00689       replace(iterator __i1, iterator __i2, const basic_string& __str)
    00690       { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
    00691
    00692       basic_string&
    00693       replace(iterator __i1, iterator __i2,
    00694                            const _CharT* __s, size_type __n)
    00695       { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n); }
    00696
    00697       basic_string&
    00698       replace(iterator __i1, iterator __i2, const _CharT* __s)
    00699       { return this->replace(__i1, __i2, __s, traits_type::length(__s)); }
    00700
    00701       basic_string&
    00702       replace(iterator __i1, iterator __i2, size_type __n, _CharT __c);
    00703
    00704       template<class _InputIterator>
    00705         basic_string&
    00706         replace(iterator __i1, iterator __i2,
    00707         _InputIterator __k1, _InputIterator __k2)
    00708         { return _M_replace(__i1, __i2, __k1, __k2,
    00709          typename iterator_traits<_InputIterator>::iterator_category()); }
    00710
    00711       // Specializations for the common case of pointer and iterator:
    00712       // useful to avoid the overhead of temporary buffering in _M_replace.
    00713       basic_string&
    00714       replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2)
    00715         { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
    00716                    __k1, __k2 - __k1); }
    00717
    00718       basic_string&
    00719       replace(iterator __i1, iterator __i2, const _CharT* __k1, const _CharT* __k2)
    00720         { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
    00721                    __k1, __k2 - __k1); }
    00722
    00723       basic_string&
    00724       replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2)
    00725         { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
    00726                    __k1.base(), __k2 - __k1);
    00727     }
    00728
    00729       basic_string&
    00730       replace(iterator __i1, iterator __i2, const_iterator __k1, const_iterator __k2)
    00731         { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
    00732                    __k1.base(), __k2 - __k1);
    00733     }
    00734
    00735     private:
    00736       template<class _InputIterator>
    00737         basic_string&
    00738         _M_replace(iterator __i1, iterator __i2, _InputIterator __k1,
    00739            _InputIterator __k2, input_iterator_tag);
    00740
    00741       template<class _ForwardIterator>
    00742         basic_string&
    00743         _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1,
    00744            _ForwardIterator __k2);
    00745
    00746       // _S_construct_aux is used to implement the 21.3.1 para 15 which
    00747       // requires special behaviour if _InIter is an integral type
    00748       template<class _InIter>
    00749         static _CharT*
    00750         _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a,
    00751              __false_type)
    00752     {
    00753           typedef typename iterator_traits<_InIter>::iterator_category _Tag;
    00754           return _S_construct(__beg, __end, __a, _Tag());
    00755     }
    00756
    00757       template<class _InIter>
    00758         static _CharT*
    00759         _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a,
    00760              __true_type)
    00761     {
    00762       return _S_construct(static_cast<size_type>(__beg),
    00763                   static_cast<value_type>(__end), __a);
    00764     }
    00765
    00766       template<class _InIter>
    00767         static _CharT*
    00768         _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a)
    00769     {
    00770       typedef typename _Is_integer<_InIter>::_Integral _Integral;
    00771       return _S_construct_aux(__beg, __end, __a, _Integral());
    00772         }
    00773
    00774       // For Input Iterators, used in istreambuf_iterators, etc.
    00775       template<class _InIter>
    00776         static _CharT*
    00777          _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
    00778               input_iterator_tag);
    00779
    00780       // For forward_iterators up to random_access_iterators, used for
    00781       // string::iterator, _CharT*, etc.
    00782       template<class _FwdIter>
    00783         static _CharT*
    00784         _S_construct(_FwdIter __beg, _FwdIter __end, const _Alloc& __a,
    00785              forward_iterator_tag);
    00786
    00787       static _CharT*
    00788       _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
    00789
    00790     public:
    00791
    00792       size_type
    00793       copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
    00794
    00795       void
    00796       swap(basic_string<_CharT, _Traits, _Alloc>& __s);
    00797
    00798       // String operations:
    00799       const _CharT*
    00800       c_str() const
    00801       {
    00802     // MT: This assumes concurrent writes are OK.
    00803     size_type __n = this->size();
    00804     traits_type::assign(_M_data()[__n], _Rep::_S_terminal);
    00805         return _M_data();
    00806       }
    00807
    00808       const _CharT*
    00809       data() const { return _M_data(); }
    00810
    00811       allocator_type
    00812       get_allocator() const { return _M_dataplus; }
    00813
    00814       size_type
    00815       find(const _CharT* __s, size_type __pos, size_type __n) const;
    00816
    00817       size_type
    00818       find(const basic_string& __str, size_type __pos = 0) const
    00819       { return this->find(__str.data(), __pos, __str.size()); }
    00820
    00821       size_type
    00822       find(const _CharT* __s, size_type __pos = 0) const
    00823       { return this->find(__s, __pos, traits_type::length(__s)); }
    00824
    00825       size_type
    00826       find(_CharT __c, size_type __pos = 0) const;
    00827
    00828       size_type
    00829       rfind(const basic_string& __str, size_type __pos = npos) const
    00830       { return this->rfind(__str.data(), __pos, __str.size()); }
    00831
    00832       size_type
    00833       rfind(const _CharT* __s, size_type __pos, size_type __n) const;
    00834
    00835       size_type
    00836       rfind(const _CharT* __s, size_type __pos = npos) const
    00837       { return this->rfind(__s, __pos, traits_type::length(__s)); }
    00838
    00839       size_type
    00840       rfind(_CharT __c, size_type __pos = npos) const;
    00841
    00842       size_type
    00843       find_first_of(const basic_string& __str, size_type __pos = 0) const
    00844       { return this->find_first_of(__str.data(), __pos, __str.size()); }
    00845
    00846       size_type
    00847       find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
    00848
    00849       size_type
    00850       find_first_of(const _CharT* __s, size_type __pos = 0) const
    00851       { return this->find_first_of(__s, __pos, traits_type::length(__s)); }
    00852
    00853       size_type
    00854       find_first_of(_CharT __c, size_type __pos = 0) const
    00855       { return this->find(__c, __pos); }
    00856
    00857       size_type
    00858       find_last_of(const basic_string& __str, size_type __pos = npos) const
    00859       { return this->find_last_of(__str.data(), __pos, __str.size()); }
    00860
    00861       size_type
    00862       find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
    00863
    00864       size_type
    00865       find_last_of(const _CharT* __s, size_type __pos = npos) const
    00866       { return this->find_last_of(__s, __pos, traits_type::length(__s)); }
    00867
    00868       size_type
    00869       find_last_of(_CharT __c, size_type __pos = npos) const
    00870       { return this->rfind(__c, __pos); }
    00871
    00872       size_type
    00873       find_first_not_of(const basic_string& __str, size_type __pos = 0) const
    00874       { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
    00875
    00876       size_type
    00877       find_first_not_of(const _CharT* __s, size_type __pos,
    00878             size_type __n) const;
    00879
    00880       size_type
    00881       find_first_not_of(const _CharT* __s, size_type __pos = 0) const
    00882       { return this->find_first_not_of(__s, __pos, traits_type::length(__s)); }
    00883
    00884       size_type
    00885       find_first_not_of(_CharT __c, size_type __pos = 0) const;
    00886
    00887       size_type
    00888       find_last_not_of(const basic_string& __str, size_type __pos = npos) const
    00889       { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
    00890
    00891       size_type
    00892       find_last_not_of(const _CharT* __s, size_type __pos,
    00893                size_type __n) const;
    00894       size_type
    00895       find_last_not_of(const _CharT* __s, size_type __pos = npos) const
    00896       { return this->find_last_not_of(__s, __pos, traits_type::length(__s)); }
    00897
    00898       size_type
    00899       find_last_not_of(_CharT __c, size_type __pos = npos) const;
    00900
    00901       basic_string
    00902       substr(size_type __pos = 0, size_type __n = npos) const
    00903       {
    00904     if (__pos > this->size())
    00905       __throw_out_of_range("basic_string::substr");
    00906     return basic_string(*this, __pos, __n);
    00907       }
    00908
    00909       int
    00910       compare(const basic_string& __str) const
    00911       {
    00912     size_type __size = this->size();
    00913     size_type __osize = __str.size();
    00914     size_type __len = min(__size, __osize);
    00915
    00916     int __r = traits_type::compare(_M_data(), __str.data(), __len);
    00917     if (!__r)
    00918       __r =  __size - __osize;
    00919     return __r;
    00920       }
    00921
    00922       int
    00923       compare(size_type __pos, size_type __n, const basic_string& __str) const;
    00924
    00925       int
    00926       compare(size_type __pos1, size_type __n1, const basic_string& __str,
    00927           size_type __pos2, size_type __n2) const;
    00928
    00929       int
    00930       compare(const _CharT* __s) const;
    00931
    00932       // _GLIBCPP_RESOLVE_LIB_DEFECTS
    00933       // 5. String::compare specification questionable
    00934       int
    00935       compare(size_type __pos, size_type __n1, const _CharT* __s) const;
    00936
    00937       int
    00938       compare(size_type __pos, size_type __n1, const _CharT* __s,
    00939           size_type __n2) const;
    00940   };
    00941
    00942
    00943   template<typename _CharT, typename _Traits, typename _Alloc>
    00944     inline basic_string<_CharT, _Traits, _Alloc>::
    00945     basic_string()
    00946     : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { }
    00947
    00948   // operator+
    00949   template<typename _CharT, typename _Traits, typename _Alloc>
    00950     basic_string<_CharT, _Traits, _Alloc>
    00951     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    00952           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    00953     {
    00954       basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
    00955       __str.append(__rhs);
    00956       return __str;
    00957     }
    00958
    00959   template<typename _CharT, typename _Traits, typename _Alloc>
    00960     basic_string<_CharT,_Traits,_Alloc>
    00961     operator+(const _CharT* __lhs,
    00962           const basic_string<_CharT,_Traits,_Alloc>& __rhs);
    00963
    00964   template<typename _CharT, typename _Traits, typename _Alloc>
    00965     basic_string<_CharT,_Traits,_Alloc>
    00966     operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
    00967
    00968   template<typename _CharT, typename _Traits, typename _Alloc>
    00969     inline basic_string<_CharT, _Traits, _Alloc>
    00970     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    00971          const _CharT* __rhs)
    00972     {
    00973       basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
    00974       __str.append(__rhs);
    00975       return __str;
    00976     }
    00977
    00978   template<typename _CharT, typename _Traits, typename _Alloc>
    00979     inline basic_string<_CharT, _Traits, _Alloc>
    00980     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
    00981     {
    00982       typedef basic_string<_CharT, _Traits, _Alloc>     __string_type;
    00983       typedef typename __string_type::size_type     __size_type;
    00984       __string_type __str(__lhs);
    00985       __str.append(__size_type(1), __rhs);
    00986       return __str;
    00987     }
    00988
    00989   // operator ==
    00990   template<typename _CharT, typename _Traits, typename _Alloc>
    00991     inline bool
    00992     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    00993            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    00994     { return __lhs.compare(__rhs) == 0; }
    00995
    00996   template<typename _CharT, typename _Traits, typename _Alloc>
    00997     inline bool
    00998     operator==(const _CharT* __lhs,
    00999            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01000     { return __rhs.compare(__lhs) == 0; }
    01001
    01002   template<typename _CharT, typename _Traits, typename _Alloc>
    01003     inline bool
    01004     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01005            const _CharT* __rhs)
    01006     { return __lhs.compare(__rhs) == 0; }
    01007
    01008   // operator !=
    01009   template<typename _CharT, typename _Traits, typename _Alloc>
    01010     inline bool
    01011     operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01012            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01013     { return __rhs.compare(__lhs) != 0; }
    01014
    01015   template<typename _CharT, typename _Traits, typename _Alloc>
    01016     inline bool
    01017     operator!=(const _CharT* __lhs,
    01018            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01019     { return __rhs.compare(__lhs) != 0; }
    01020
    01021   template<typename _CharT, typename _Traits, typename _Alloc>
    01022     inline bool
    01023     operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01024            const _CharT* __rhs)
    01025     { return __lhs.compare(__rhs) != 0; }
    01026
    01027   // operator <
    01028   template<typename _CharT, typename _Traits, typename _Alloc>
    01029     inline bool
    01030     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01031           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01032     { return __lhs.compare(__rhs) < 0; }
    01033
    01034   template<typename _CharT, typename _Traits, typename _Alloc>
    01035     inline bool
    01036     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01037           const _CharT* __rhs)
    01038     { return __lhs.compare(__rhs) < 0; }
    01039
    01040   template<typename _CharT, typename _Traits, typename _Alloc>
    01041     inline bool
    01042     operator<(const _CharT* __lhs,
    01043           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01044     { return __rhs.compare(__lhs) > 0; }
    01045
    01046   // operator >
    01047   template<typename _CharT, typename _Traits, typename _Alloc>
    01048     inline bool
    01049     operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01050           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01051     { return __lhs.compare(__rhs) > 0; }
    01052
    01053   template<typename _CharT, typename _Traits, typename _Alloc>
    01054     inline bool
    01055     operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01056           const _CharT* __rhs)
    01057     { return __lhs.compare(__rhs) > 0; }
    01058
    01059   template<typename _CharT, typename _Traits, typename _Alloc>
    01060     inline bool
    01061     operator>(const _CharT* __lhs,
    01062           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01063     { return __rhs.compare(__lhs) < 0; }
    01064
    01065   // operator <=
    01066   template<typename _CharT, typename _Traits, typename _Alloc>
    01067     inline bool
    01068     operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01069            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01070     { return __lhs.compare(__rhs) <= 0; }
    01071
    01072   template<typename _CharT, typename _Traits, typename _Alloc>
    01073     inline bool
    01074     operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01075            const _CharT* __rhs)
    01076     { return __lhs.compare(__rhs) <= 0; }
    01077
    01078   template<typename _CharT, typename _Traits, typename _Alloc>
    01079     inline bool
    01080     operator<=(const _CharT* __lhs,
    01081            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01082   { return __rhs.compare(__lhs) >= 0; }
    01083
    01084   // operator >=
    01085   template<typename _CharT, typename _Traits, typename _Alloc>
    01086     inline bool
    01087     operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01088            const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01089     { return __lhs.compare(__rhs) >= 0; }
    01090
    01091   template<typename _CharT, typename _Traits, typename _Alloc>
    01092     inline bool
    01093     operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01094            const _CharT* __rhs)
    01095     { return __lhs.compare(__rhs) >= 0; }
    01096
    01097   template<typename _CharT, typename _Traits, typename _Alloc>
    01098     inline bool
    01099     operator>=(const _CharT* __lhs,
    01100          const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01101     { return __rhs.compare(__lhs) <= 0; }
    01102
    01103
    01104   template<typename _CharT, typename _Traits, typename _Alloc>
    01105     inline void
    01106     swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
    01107      basic_string<_CharT, _Traits, _Alloc>& __rhs)
    01108     { __lhs.swap(__rhs); }
    01109
    01110   template<typename _CharT, typename _Traits, typename _Alloc>
    01111     basic_istream<_CharT, _Traits>&
    01112     operator>>(basic_istream<_CharT, _Traits>& __is,
    01113            basic_string<_CharT, _Traits, _Alloc>& __str);
    01114
    01115   template<typename _CharT, typename _Traits, typename _Alloc>
    01116     basic_ostream<_CharT, _Traits>&
    01117     operator<<(basic_ostream<_CharT, _Traits>& __os,
    01118            const basic_string<_CharT, _Traits, _Alloc>& __str);
    01119
    01120   template<typename _CharT, typename _Traits, typename _Alloc>
    01121     basic_istream<_CharT,_Traits>&
    01122     getline(basic_istream<_CharT, _Traits>& __is,
    01123         basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
    01124
    01125   template<typename _CharT, typename _Traits, typename _Alloc>
    01126     inline basic_istream<_CharT,_Traits>&
    01127     getline(basic_istream<_CharT, _Traits>& __is,
    01128         basic_string<_CharT, _Traits, _Alloc>& __str);
    01129 } // namespace std
    01130
    01131 #endif /* _CPP_BITS_STRING_H */