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