Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Reference-counted versatile string base -*- C++ -*-
  2.  
  3. // Copyright (C) 2005-2013 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. /** @file ext/rc_string_base.h
  26.  *  This is an internal header file, included by other library headers.
  27.  *  Do not attempt to use it directly. @headername{ext/vstring.h}
  28.  */
  29.  
  30. #ifndef _RC_STRING_BASE_H
  31. #define _RC_STRING_BASE_H 1
  32.  
  33. #include <ext/atomicity.h>
  34. #include <bits/stl_iterator_base_funcs.h>
  35.  
  36. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39.  
  40.   /**
  41.    *  Documentation?  What's that?
  42.    *  Nathan Myers <ncm@cantrip.org>.
  43.    *
  44.    *  A string looks like this:
  45.    *
  46.    *  @code
  47.    *                                        [_Rep]
  48.    *                                        _M_length
  49.    *   [__rc_string_base<char_type>]        _M_capacity
  50.    *   _M_dataplus                          _M_refcount
  51.    *   _M_p ---------------->               unnamed array of char_type
  52.    *  @endcode
  53.    *
  54.    *  Where the _M_p points to the first character in the string, and
  55.    *  you cast it to a pointer-to-_Rep and subtract 1 to get a
  56.    *  pointer to the header.
  57.    *
  58.    *  This approach has the enormous advantage that a string object
  59.    *  requires only one allocation.  All the ugliness is confined
  60.    *  within a single pair of inline functions, which each compile to
  61.    *  a single @a add instruction: _Rep::_M_refdata(), and
  62.    *  __rc_string_base::_M_rep(); and the allocation function which gets a
  63.    *  block of raw bytes and with room enough and constructs a _Rep
  64.    *  object at the front.
  65.    *
  66.    *  The reason you want _M_data pointing to the character array and
  67.    *  not the _Rep is so that the debugger can see the string
  68.    *  contents. (Probably we should add a non-inline member to get
  69.    *  the _Rep for the debugger to use, so users can check the actual
  70.    *  string length.)
  71.    *
  72.    *  Note that the _Rep object is a POD so that you can have a
  73.    *  static <em>empty string</em> _Rep object already @a constructed before
  74.    *  static constructors have run.  The reference-count encoding is
  75.    *  chosen so that a 0 indicates one reference, so you never try to
  76.    *  destroy the empty-string _Rep object.
  77.    *
  78.    *  All but the last paragraph is considered pretty conventional
  79.    *  for a C++ string implementation.
  80.   */
  81.  template<typename _CharT, typename _Traits, typename _Alloc>
  82.     class __rc_string_base
  83.     : protected __vstring_utility<_CharT, _Traits, _Alloc>
  84.     {
  85.     public:
  86.       typedef _Traits                                       traits_type;
  87.       typedef typename _Traits::char_type                   value_type;
  88.       typedef _Alloc                                        allocator_type;
  89.  
  90.       typedef __vstring_utility<_CharT, _Traits, _Alloc>    _Util_Base;
  91.       typedef typename _Util_Base::_CharT_alloc_type        _CharT_alloc_type;
  92.       typedef typename _CharT_alloc_type::size_type         size_type;
  93.  
  94.     private:
  95.       // _Rep: string representation
  96.       //   Invariants:
  97.       //   1. String really contains _M_length + 1 characters: due to 21.3.4
  98.       //      must be kept null-terminated.
  99.       //   2. _M_capacity >= _M_length
  100.       //      Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
  101.       //   3. _M_refcount has three states:
  102.       //      -1: leaked, one reference, no ref-copies allowed, non-const.
  103.       //       0: one reference, non-const.
  104.       //     n>0: n + 1 references, operations require a lock, const.
  105.       //   4. All fields == 0 is an empty string, given the extra storage
  106.       //      beyond-the-end for a null terminator; thus, the shared
  107.       //      empty string representation needs no constructor.
  108.       struct _Rep
  109.       {
  110.         union
  111.         {
  112.           struct
  113.           {
  114.             size_type       _M_length;
  115.             size_type       _M_capacity;
  116.             _Atomic_word    _M_refcount;
  117.           }                 _M_info;
  118.  
  119.           // Only for alignment purposes.
  120.           _CharT            _M_align;
  121.         };
  122.  
  123.         typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
  124.  
  125.         _CharT*
  126.         _M_refdata() throw()
  127.         { return reinterpret_cast<_CharT*>(this + 1); }
  128.  
  129.         _CharT*
  130.         _M_refcopy() throw()
  131.         {
  132.           __atomic_add_dispatch(&_M_info._M_refcount, 1);
  133.           return _M_refdata();
  134.         }  // XXX MT
  135.  
  136.         void
  137.         _M_set_length(size_type __n)
  138.         {
  139.           _M_info._M_refcount = 0;  // One reference.
  140.           _M_info._M_length = __n;
  141.           // grrr. (per 21.3.4)
  142.           // You cannot leave those LWG people alone for a second.
  143.           traits_type::assign(_M_refdata()[__n], _CharT());
  144.         }
  145.  
  146.         // Create & Destroy
  147.         static _Rep*
  148.         _S_create(size_type, size_type, const _Alloc&);
  149.  
  150.         void
  151.         _M_destroy(const _Alloc&) throw();
  152.  
  153.         _CharT*
  154.         _M_clone(const _Alloc&, size_type __res = 0);
  155.       };
  156.  
  157.       struct _Rep_empty
  158.       : public _Rep
  159.       {
  160.         _CharT              _M_terminal;
  161.       };
  162.  
  163.       static _Rep_empty     _S_empty_rep;
  164.  
  165.       // The maximum number of individual char_type elements of an
  166.       // individual string is determined by _S_max_size. This is the
  167.       // value that will be returned by max_size().  (Whereas npos
  168.       // is the maximum number of bytes the allocator can allocate.)
  169.       // If one was to divvy up the theoretical largest size string,
  170.       // with a terminating character and m _CharT elements, it'd
  171.       // look like this:
  172.       // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
  173.       //        + sizeof(_Rep) - 1
  174.       // (NB: last two terms for rounding reasons, see _M_create below)
  175.       // Solving for m:
  176.       // m = ((npos - 2 * sizeof(_Rep) + 1) / sizeof(_CharT)) - 1
  177.       // In addition, this implementation halves this amount.
  178.       enum { _S_max_size = (((static_cast<size_type>(-1) - 2 * sizeof(_Rep)
  179.                               + 1) / sizeof(_CharT)) - 1) / 2 };
  180.  
  181.       // Data Member (private):
  182.       mutable typename _Util_Base::template _Alloc_hider<_Alloc>  _M_dataplus;
  183.  
  184.       void
  185.       _M_data(_CharT* __p)
  186.       { _M_dataplus._M_p = __p; }
  187.  
  188.       _Rep*
  189.       _M_rep() const
  190.       { return &((reinterpret_cast<_Rep*>(_M_data()))[-1]); }
  191.  
  192.       _CharT*
  193.       _M_grab(const _Alloc& __alloc) const
  194.       {
  195.         return (!_M_is_leaked() && _M_get_allocator() == __alloc)
  196.                 ? _M_rep()->_M_refcopy() : _M_rep()->_M_clone(__alloc);
  197.       }
  198.  
  199.       void
  200.       _M_dispose()
  201.       {
  202.         // Be race-detector-friendly.  For more info see bits/c++config.
  203.         _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_rep()->_M_info.
  204.                                                 _M_refcount);
  205.         if (__exchange_and_add_dispatch(&_M_rep()->_M_info._M_refcount,
  206.                                         -1) <= 0)
  207.           {
  208.             _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_rep()->_M_info.
  209.                                                    _M_refcount);
  210.             _M_rep()->_M_destroy(_M_get_allocator());
  211.           }
  212.       }  // XXX MT
  213.  
  214.       bool
  215.       _M_is_leaked() const
  216.       { return _M_rep()->_M_info._M_refcount < 0; }
  217.  
  218.       void
  219.       _M_set_sharable()
  220.       { _M_rep()->_M_info._M_refcount = 0; }
  221.  
  222.       void
  223.       _M_leak_hard();
  224.  
  225.       // _S_construct_aux is used to implement the 21.3.1 para 15 which
  226.       // requires special behaviour if _InIterator is an integral type
  227.       template<typename _InIterator>
  228.         static _CharT*
  229.         _S_construct_aux(_InIterator __beg, _InIterator __end,
  230.                          const _Alloc& __a, std::__false_type)
  231.         {
  232.           typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
  233.           return _S_construct(__beg, __end, __a, _Tag());
  234.         }
  235.  
  236.       // _GLIBCXX_RESOLVE_LIB_DEFECTS
  237.       // 438. Ambiguity in the "do the right thing" clause
  238.       template<typename _Integer>
  239.         static _CharT*
  240.         _S_construct_aux(_Integer __beg, _Integer __end,
  241.                          const _Alloc& __a, std::__true_type)
  242.         { return _S_construct_aux_2(static_cast<size_type>(__beg),
  243.                                     __end, __a); }
  244.  
  245.       static _CharT*
  246.       _S_construct_aux_2(size_type __req, _CharT __c, const _Alloc& __a)
  247.       { return _S_construct(__req, __c, __a); }
  248.  
  249.       template<typename _InIterator>
  250.         static _CharT*
  251.         _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
  252.         {
  253.           typedef typename std::__is_integer<_InIterator>::__type _Integral;
  254.           return _S_construct_aux(__beg, __end, __a, _Integral());
  255.         }
  256.  
  257.       // For Input Iterators, used in istreambuf_iterators, etc.
  258.       template<typename _InIterator>
  259.         static _CharT*
  260.          _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  261.                       std::input_iterator_tag);
  262.  
  263.       // For forward_iterators up to random_access_iterators, used for
  264.       // string::iterator, _CharT*, etc.
  265.       template<typename _FwdIterator>
  266.         static _CharT*
  267.         _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
  268.                      std::forward_iterator_tag);
  269.  
  270.       static _CharT*
  271.       _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
  272.  
  273.     public:
  274.       size_type
  275.       _M_max_size() const
  276.       { return size_type(_S_max_size); }
  277.  
  278.       _CharT*
  279.       _M_data() const
  280.       { return _M_dataplus._M_p; }
  281.  
  282.       size_type
  283.       _M_length() const
  284.       { return _M_rep()->_M_info._M_length; }
  285.  
  286.       size_type
  287.       _M_capacity() const
  288.       { return _M_rep()->_M_info._M_capacity; }
  289.  
  290.       bool
  291.       _M_is_shared() const
  292.       { return _M_rep()->_M_info._M_refcount > 0; }
  293.  
  294.       void
  295.       _M_set_leaked()
  296.       { _M_rep()->_M_info._M_refcount = -1; }
  297.  
  298.       void
  299.       _M_leak()    // for use in begin() & non-const op[]
  300.       {
  301.         if (!_M_is_leaked())
  302.           _M_leak_hard();
  303.       }
  304.  
  305.       void
  306.       _M_set_length(size_type __n)
  307.       { _M_rep()->_M_set_length(__n); }
  308.  
  309.       __rc_string_base()
  310.       : _M_dataplus(_S_empty_rep._M_refcopy()) { }
  311.  
  312.       __rc_string_base(const _Alloc& __a);
  313.  
  314.       __rc_string_base(const __rc_string_base& __rcs);
  315.  
  316. #if __cplusplus >= 201103L
  317.       __rc_string_base(__rc_string_base&& __rcs)
  318.       : _M_dataplus(__rcs._M_dataplus)
  319.       { __rcs._M_data(_S_empty_rep._M_refcopy()); }
  320. #endif
  321.  
  322.       __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a);
  323.  
  324.       template<typename _InputIterator>
  325.         __rc_string_base(_InputIterator __beg, _InputIterator __end,
  326.                          const _Alloc& __a);
  327.  
  328.       ~__rc_string_base()
  329.       { _M_dispose(); }
  330.  
  331.       allocator_type&
  332.       _M_get_allocator()
  333.       { return _M_dataplus; }
  334.  
  335.       const allocator_type&
  336.       _M_get_allocator() const
  337.       { return _M_dataplus; }
  338.  
  339.       void
  340.       _M_swap(__rc_string_base& __rcs);
  341.  
  342.       void
  343.       _M_assign(const __rc_string_base& __rcs);
  344.  
  345.       void
  346.       _M_reserve(size_type __res);
  347.  
  348.       void
  349.       _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  350.                 size_type __len2);
  351.  
  352.       void
  353.       _M_erase(size_type __pos, size_type __n);
  354.  
  355.       void
  356.       _M_clear()
  357.       { _M_erase(size_type(0), _M_length()); }
  358.  
  359.       bool
  360.       _M_compare(const __rc_string_base&) const
  361.       { return false; }
  362.     };
  363.  
  364.   template<typename _CharT, typename _Traits, typename _Alloc>
  365.     typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
  366.     __rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
  367.  
  368.   template<typename _CharT, typename _Traits, typename _Alloc>
  369.     typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
  370.     __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  371.     _S_create(size_type __capacity, size_type __old_capacity,
  372.               const _Alloc& __alloc)
  373.     {
  374.       // _GLIBCXX_RESOLVE_LIB_DEFECTS
  375.       // 83.  String::npos vs. string::max_size()
  376.       if (__capacity > size_type(_S_max_size))
  377.         std::__throw_length_error(__N("__rc_string_base::_Rep::_S_create"));
  378.  
  379.       // The standard places no restriction on allocating more memory
  380.       // than is strictly needed within this layer at the moment or as
  381.       // requested by an explicit application call to reserve().
  382.  
  383.       // Many malloc implementations perform quite poorly when an
  384.       // application attempts to allocate memory in a stepwise fashion
  385.       // growing each allocation size by only 1 char.  Additionally,
  386.       // it makes little sense to allocate less linear memory than the
  387.       // natural blocking size of the malloc implementation.
  388.       // Unfortunately, we would need a somewhat low-level calculation
  389.       // with tuned parameters to get this perfect for any particular
  390.       // malloc implementation.  Fortunately, generalizations about
  391.       // common features seen among implementations seems to suffice.
  392.  
  393.       // __pagesize need not match the actual VM page size for good
  394.       // results in practice, thus we pick a common value on the low
  395.       // side.  __malloc_header_size is an estimate of the amount of
  396.       // overhead per memory allocation (in practice seen N * sizeof
  397.       // (void*) where N is 0, 2 or 4).  According to folklore,
  398.       // picking this value on the high side is better than
  399.       // low-balling it (especially when this algorithm is used with
  400.       // malloc implementations that allocate memory blocks rounded up
  401.       // to a size which is a power of 2).
  402.       const size_type __pagesize = 4096;
  403.       const size_type __malloc_header_size = 4 * sizeof(void*);
  404.  
  405.       // The below implements an exponential growth policy, necessary to
  406.       // meet amortized linear time requirements of the library: see
  407.       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
  408.       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
  409.         {
  410.           __capacity = 2 * __old_capacity;
  411.           // Never allocate a string bigger than _S_max_size.
  412.           if (__capacity > size_type(_S_max_size))
  413.             __capacity = size_type(_S_max_size);
  414.         }
  415.  
  416.       // NB: Need an array of char_type[__capacity], plus a terminating
  417.       // null char_type() element, plus enough for the _Rep data structure,
  418.       // plus sizeof(_Rep) - 1 to upper round to a size multiple of
  419.       // sizeof(_Rep).
  420.       // Whew. Seemingly so needy, yet so elemental.
  421.       size_type __size = ((__capacity + 1) * sizeof(_CharT)
  422.                           + 2 * sizeof(_Rep) - 1);
  423.  
  424.       const size_type __adj_size = __size + __malloc_header_size;
  425.       if (__adj_size > __pagesize && __capacity > __old_capacity)
  426.         {
  427.           const size_type __extra = __pagesize - __adj_size % __pagesize;
  428.           __capacity += __extra / sizeof(_CharT);
  429.           if (__capacity > size_type(_S_max_size))
  430.             __capacity = size_type(_S_max_size);
  431.           __size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
  432.         }
  433.  
  434.       // NB: Might throw, but no worries about a leak, mate: _Rep()
  435.       // does not throw.
  436.       _Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
  437.       _Rep* __p = new (__place) _Rep;
  438.       __p->_M_info._M_capacity = __capacity;
  439.       return __p;
  440.     }
  441.  
  442.   template<typename _CharT, typename _Traits, typename _Alloc>
  443.     void
  444.     __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  445.     _M_destroy(const _Alloc& __a) throw ()
  446.     {
  447.       const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
  448.                                 + 2 * sizeof(_Rep) - 1);
  449.       _Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
  450.     }
  451.  
  452.   template<typename _CharT, typename _Traits, typename _Alloc>
  453.     _CharT*
  454.     __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  455.     _M_clone(const _Alloc& __alloc, size_type __res)
  456.     {
  457.       // Requested capacity of the clone.
  458.       const size_type __requested_cap = _M_info._M_length + __res;
  459.       _Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
  460.                                   __alloc);
  461.  
  462.       if (_M_info._M_length)
  463.         __rc_string_base::_S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
  464.  
  465.       __r->_M_set_length(_M_info._M_length);
  466.       return __r->_M_refdata();
  467.     }
  468.  
  469.   template<typename _CharT, typename _Traits, typename _Alloc>
  470.     __rc_string_base<_CharT, _Traits, _Alloc>::
  471.     __rc_string_base(const _Alloc& __a)
  472.     : _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
  473.  
  474.   template<typename _CharT, typename _Traits, typename _Alloc>
  475.     __rc_string_base<_CharT, _Traits, _Alloc>::
  476.     __rc_string_base(const __rc_string_base& __rcs)
  477.     : _M_dataplus(__rcs._M_get_allocator(),
  478.                   __rcs._M_grab(__rcs._M_get_allocator())) { }
  479.  
  480.   template<typename _CharT, typename _Traits, typename _Alloc>
  481.     __rc_string_base<_CharT, _Traits, _Alloc>::
  482.     __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
  483.     : _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
  484.  
  485.   template<typename _CharT, typename _Traits, typename _Alloc>
  486.     template<typename _InputIterator>
  487.     __rc_string_base<_CharT, _Traits, _Alloc>::
  488.     __rc_string_base(_InputIterator __beg, _InputIterator __end,
  489.                      const _Alloc& __a)
  490.     : _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
  491.  
  492.   template<typename _CharT, typename _Traits, typename _Alloc>
  493.     void
  494.     __rc_string_base<_CharT, _Traits, _Alloc>::
  495.     _M_leak_hard()
  496.     {
  497.       if (_M_is_shared())
  498.         _M_erase(0, 0);
  499.       _M_set_leaked();
  500.     }
  501.  
  502.   // NB: This is the special case for Input Iterators, used in
  503.   // istreambuf_iterators, etc.
  504.   // Input Iterators have a cost structure very different from
  505.   // pointers, calling for a different coding style.
  506.   template<typename _CharT, typename _Traits, typename _Alloc>
  507.     template<typename _InIterator>
  508.       _CharT*
  509.       __rc_string_base<_CharT, _Traits, _Alloc>::
  510.       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  511.                    std::input_iterator_tag)
  512.       {
  513.         if (__beg == __end && __a == _Alloc())
  514.           return _S_empty_rep._M_refcopy();
  515.  
  516.         // Avoid reallocation for common case.
  517.         _CharT __buf[128];
  518.         size_type __len = 0;
  519.         while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
  520.           {
  521.             __buf[__len++] = *__beg;
  522.             ++__beg;
  523.           }
  524.         _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
  525.         _S_copy(__r->_M_refdata(), __buf, __len);
  526.         __try
  527.           {
  528.             while (__beg != __end)
  529.               {
  530.                 if (__len == __r->_M_info._M_capacity)
  531.                   {
  532.                     // Allocate more space.
  533.                     _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
  534.                     _S_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
  535.                     __r->_M_destroy(__a);
  536.                     __r = __another;
  537.                   }
  538.                 __r->_M_refdata()[__len++] = *__beg;
  539.                 ++__beg;
  540.               }
  541.           }
  542.         __catch(...)
  543.           {
  544.             __r->_M_destroy(__a);
  545.             __throw_exception_again;
  546.           }
  547.         __r->_M_set_length(__len);
  548.         return __r->_M_refdata();
  549.       }
  550.  
  551.   template<typename _CharT, typename _Traits, typename _Alloc>
  552.     template<typename _InIterator>
  553.       _CharT*
  554.       __rc_string_base<_CharT, _Traits, _Alloc>::
  555.       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  556.                    std::forward_iterator_tag)
  557.       {
  558.         if (__beg == __end && __a == _Alloc())
  559.           return _S_empty_rep._M_refcopy();
  560.  
  561.         // NB: Not required, but considered best practice.
  562.         if (__is_null_pointer(__beg) && __beg != __end)
  563.           std::__throw_logic_error(__N("__rc_string_base::"
  564.                                        "_S_construct null not valid"));
  565.  
  566.         const size_type __dnew = static_cast<size_type>(std::distance(__beg,
  567.                                                                       __end));
  568.         // Check for out_of_range and length_error exceptions.
  569.         _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
  570.         __try
  571.           { __rc_string_base::_S_copy_chars(__r->_M_refdata(), __beg, __end); }
  572.         __catch(...)
  573.           {
  574.             __r->_M_destroy(__a);
  575.             __throw_exception_again;
  576.           }
  577.         __r->_M_set_length(__dnew);
  578.         return __r->_M_refdata();
  579.       }
  580.  
  581.   template<typename _CharT, typename _Traits, typename _Alloc>
  582.     _CharT*
  583.     __rc_string_base<_CharT, _Traits, _Alloc>::
  584.     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
  585.     {
  586.       if (__n == 0 && __a == _Alloc())
  587.         return _S_empty_rep._M_refcopy();
  588.  
  589.       // Check for out_of_range and length_error exceptions.
  590.       _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
  591.       if (__n)
  592.         __rc_string_base::_S_assign(__r->_M_refdata(), __n, __c);
  593.  
  594.       __r->_M_set_length(__n);
  595.       return __r->_M_refdata();
  596.     }
  597.  
  598.   template<typename _CharT, typename _Traits, typename _Alloc>
  599.     void
  600.     __rc_string_base<_CharT, _Traits, _Alloc>::
  601.     _M_swap(__rc_string_base& __rcs)
  602.     {
  603.       if (_M_is_leaked())
  604.         _M_set_sharable();
  605.       if (__rcs._M_is_leaked())
  606.         __rcs._M_set_sharable();
  607.  
  608.       _CharT* __tmp = _M_data();
  609.       _M_data(__rcs._M_data());
  610.       __rcs._M_data(__tmp);
  611.  
  612.       // _GLIBCXX_RESOLVE_LIB_DEFECTS
  613.       // 431. Swapping containers with unequal allocators.
  614.       std::__alloc_swap<allocator_type>::_S_do_it(_M_get_allocator(),
  615.                                                   __rcs._M_get_allocator());
  616.     }
  617.  
  618.   template<typename _CharT, typename _Traits, typename _Alloc>
  619.     void
  620.     __rc_string_base<_CharT, _Traits, _Alloc>::
  621.     _M_assign(const __rc_string_base& __rcs)
  622.     {
  623.       if (_M_rep() != __rcs._M_rep())
  624.         {
  625.           _CharT* __tmp = __rcs._M_grab(_M_get_allocator());
  626.           _M_dispose();
  627.           _M_data(__tmp);
  628.         }
  629.     }
  630.  
  631.   template<typename _CharT, typename _Traits, typename _Alloc>
  632.     void
  633.     __rc_string_base<_CharT, _Traits, _Alloc>::
  634.     _M_reserve(size_type __res)
  635.     {
  636.       // Make sure we don't shrink below the current size.
  637.       if (__res < _M_length())
  638.         __res = _M_length();
  639.  
  640.       if (__res != _M_capacity() || _M_is_shared())
  641.         {
  642.           _CharT* __tmp = _M_rep()->_M_clone(_M_get_allocator(),
  643.                                              __res - _M_length());
  644.           _M_dispose();
  645.           _M_data(__tmp);
  646.         }
  647.     }
  648.  
  649.   template<typename _CharT, typename _Traits, typename _Alloc>
  650.     void
  651.     __rc_string_base<_CharT, _Traits, _Alloc>::
  652.     _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  653.               size_type __len2)
  654.     {
  655.       const size_type __how_much = _M_length() - __pos - __len1;
  656.  
  657.       _Rep* __r = _Rep::_S_create(_M_length() + __len2 - __len1,
  658.                                   _M_capacity(), _M_get_allocator());
  659.  
  660.       if (__pos)
  661.         this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
  662.       if (__s && __len2)
  663.         this->_S_copy(__r->_M_refdata() + __pos, __s, __len2);
  664.       if (__how_much)
  665.         this->_S_copy(__r->_M_refdata() + __pos + __len2,
  666.                 _M_data() + __pos + __len1, __how_much);
  667.  
  668.       _M_dispose();
  669.       _M_data(__r->_M_refdata());
  670.     }
  671.  
  672.   template<typename _CharT, typename _Traits, typename _Alloc>
  673.     void
  674.     __rc_string_base<_CharT, _Traits, _Alloc>::
  675.     _M_erase(size_type __pos, size_type __n)
  676.     {
  677.       const size_type __new_size = _M_length() - __n;
  678.       const size_type __how_much = _M_length() - __pos - __n;
  679.  
  680.       if (_M_is_shared())
  681.         {
  682.           // Must reallocate.
  683.           _Rep* __r = _Rep::_S_create(__new_size, _M_capacity(),
  684.                                       _M_get_allocator());
  685.  
  686.           if (__pos)
  687.             this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
  688.           if (__how_much)
  689.             this->_S_copy(__r->_M_refdata() + __pos,
  690.                     _M_data() + __pos + __n, __how_much);
  691.  
  692.           _M_dispose();
  693.           _M_data(__r->_M_refdata());
  694.         }
  695.       else if (__how_much && __n)
  696.         {
  697.           // Work in-place.
  698.           this->_S_move(_M_data() + __pos,
  699.                   _M_data() + __pos + __n, __how_much);
  700.         }
  701.  
  702.       _M_rep()->_M_set_length(__new_size);
  703.     }
  704.  
  705.   template<>
  706.     inline bool
  707.     __rc_string_base<char, std::char_traits<char>,
  708.                      std::allocator<char> >::
  709.     _M_compare(const __rc_string_base& __rcs) const
  710.     {
  711.       if (_M_rep() == __rcs._M_rep())
  712.         return true;
  713.       return false;
  714.     }
  715.  
  716. #ifdef _GLIBCXX_USE_WCHAR_T
  717.   template<>
  718.     inline bool
  719.     __rc_string_base<wchar_t, std::char_traits<wchar_t>,
  720.                      std::allocator<wchar_t> >::
  721.     _M_compare(const __rc_string_base& __rcs) const
  722.     {
  723.       if (_M_rep() == __rcs._M_rep())
  724.         return true;
  725.       return false;
  726.     }
  727. #endif
  728.  
  729. _GLIBCXX_END_NAMESPACE_VERSION
  730. } // namespace
  731.  
  732. #endif /* _RC_STRING_BASE_H */
  733.