1*f8a1b7d9SAlexander Kabaev // Short-string-optimized versatile string base -*- C++ -*-
2*f8a1b7d9SAlexander Kabaev 
3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4*f8a1b7d9SAlexander Kabaev //
5*f8a1b7d9SAlexander Kabaev // This file is part of the GNU ISO C++ Library.  This library is free
6*f8a1b7d9SAlexander Kabaev // software; you can redistribute it and/or modify it under the
7*f8a1b7d9SAlexander Kabaev // terms of the GNU General Public License as published by the
8*f8a1b7d9SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option)
9*f8a1b7d9SAlexander Kabaev // any later version.
10*f8a1b7d9SAlexander Kabaev 
11*f8a1b7d9SAlexander Kabaev // This library is distributed in the hope that it will be useful,
12*f8a1b7d9SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*f8a1b7d9SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*f8a1b7d9SAlexander Kabaev // GNU General Public License for more details.
15*f8a1b7d9SAlexander Kabaev 
16*f8a1b7d9SAlexander Kabaev // You should have received a copy of the GNU General Public License along
17*f8a1b7d9SAlexander Kabaev // with this library; see the file COPYING.  If not, write to the Free
18*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19*f8a1b7d9SAlexander Kabaev // USA.
20*f8a1b7d9SAlexander Kabaev 
21*f8a1b7d9SAlexander Kabaev // As a special exception, you may use this file as part of a free software
22*f8a1b7d9SAlexander Kabaev // library without restriction.  Specifically, if other files instantiate
23*f8a1b7d9SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile
24*f8a1b7d9SAlexander Kabaev // this file and link it with other files to produce an executable, this
25*f8a1b7d9SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by
26*f8a1b7d9SAlexander Kabaev // the GNU General Public License.  This exception does not however
27*f8a1b7d9SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by
28*f8a1b7d9SAlexander Kabaev // the GNU General Public License.
29*f8a1b7d9SAlexander Kabaev 
30*f8a1b7d9SAlexander Kabaev /** @file ext/sso_string_base.h
31*f8a1b7d9SAlexander Kabaev  *  This file is a GNU extension to the Standard C++ Library.
32*f8a1b7d9SAlexander Kabaev  *  This is an internal header file, included by other library headers.
33*f8a1b7d9SAlexander Kabaev  *  You should not attempt to use it directly.
34*f8a1b7d9SAlexander Kabaev  */
35*f8a1b7d9SAlexander Kabaev 
36*f8a1b7d9SAlexander Kabaev #ifndef _SSO_STRING_BASE_H
37*f8a1b7d9SAlexander Kabaev #define _SSO_STRING_BASE_H 1
38*f8a1b7d9SAlexander Kabaev 
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)39*f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
40*f8a1b7d9SAlexander Kabaev 
41*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
42*f8a1b7d9SAlexander Kabaev     class __sso_string_base
43*f8a1b7d9SAlexander Kabaev     : protected __vstring_utility<_CharT, _Traits, _Alloc>
44*f8a1b7d9SAlexander Kabaev     {
45*f8a1b7d9SAlexander Kabaev     public:
46*f8a1b7d9SAlexander Kabaev       typedef _Traits					    traits_type;
47*f8a1b7d9SAlexander Kabaev       typedef typename _Traits::char_type		    value_type;
48*f8a1b7d9SAlexander Kabaev 
49*f8a1b7d9SAlexander Kabaev       typedef __vstring_utility<_CharT, _Traits, _Alloc>    _Util_Base;
50*f8a1b7d9SAlexander Kabaev       typedef typename _Util_Base::_CharT_alloc_type        _CharT_alloc_type;
51*f8a1b7d9SAlexander Kabaev       typedef typename _CharT_alloc_type::size_type	    size_type;
52*f8a1b7d9SAlexander Kabaev 
53*f8a1b7d9SAlexander Kabaev     private:
54*f8a1b7d9SAlexander Kabaev       // Data Members:
55*f8a1b7d9SAlexander Kabaev       typename _Util_Base::template _Alloc_hider<_CharT_alloc_type>
56*f8a1b7d9SAlexander Kabaev                                                             _M_dataplus;
57*f8a1b7d9SAlexander Kabaev       size_type                                             _M_string_length;
58*f8a1b7d9SAlexander Kabaev 
59*f8a1b7d9SAlexander Kabaev       enum { _S_local_capacity = 15 };
60*f8a1b7d9SAlexander Kabaev 
61*f8a1b7d9SAlexander Kabaev       union
62*f8a1b7d9SAlexander Kabaev       {
63*f8a1b7d9SAlexander Kabaev 	_CharT           _M_local_data[_S_local_capacity + 1];
64*f8a1b7d9SAlexander Kabaev 	size_type        _M_allocated_capacity;
65*f8a1b7d9SAlexander Kabaev       };
66*f8a1b7d9SAlexander Kabaev 
67*f8a1b7d9SAlexander Kabaev       void
68*f8a1b7d9SAlexander Kabaev       _M_data(_CharT* __p)
69*f8a1b7d9SAlexander Kabaev       { _M_dataplus._M_p = __p; }
70*f8a1b7d9SAlexander Kabaev 
71*f8a1b7d9SAlexander Kabaev       void
72*f8a1b7d9SAlexander Kabaev       _M_length(size_type __length)
73*f8a1b7d9SAlexander Kabaev       { _M_string_length = __length; }
74*f8a1b7d9SAlexander Kabaev 
75*f8a1b7d9SAlexander Kabaev       void
76*f8a1b7d9SAlexander Kabaev       _M_capacity(size_type __capacity)
77*f8a1b7d9SAlexander Kabaev       { _M_allocated_capacity = __capacity; }
78*f8a1b7d9SAlexander Kabaev 
79*f8a1b7d9SAlexander Kabaev       bool
80*f8a1b7d9SAlexander Kabaev       _M_is_local() const
81*f8a1b7d9SAlexander Kabaev       { return _M_data() == _M_local_data; }
82*f8a1b7d9SAlexander Kabaev 
83*f8a1b7d9SAlexander Kabaev       // Create & Destroy
84*f8a1b7d9SAlexander Kabaev       _CharT*
85*f8a1b7d9SAlexander Kabaev       _M_create(size_type&, size_type);
86*f8a1b7d9SAlexander Kabaev 
87*f8a1b7d9SAlexander Kabaev       void
88*f8a1b7d9SAlexander Kabaev       _M_dispose()
89*f8a1b7d9SAlexander Kabaev       {
90*f8a1b7d9SAlexander Kabaev 	if (!_M_is_local())
91*f8a1b7d9SAlexander Kabaev 	  _M_destroy(_M_allocated_capacity);
92*f8a1b7d9SAlexander Kabaev       }
93*f8a1b7d9SAlexander Kabaev 
94*f8a1b7d9SAlexander Kabaev       void
95*f8a1b7d9SAlexander Kabaev       _M_destroy(size_type __size) throw()
96*f8a1b7d9SAlexander Kabaev       { _M_get_allocator().deallocate(_M_data(), __size + 1); }
97*f8a1b7d9SAlexander Kabaev 
98*f8a1b7d9SAlexander Kabaev       // _M_construct_aux is used to implement the 21.3.1 para 15 which
99*f8a1b7d9SAlexander Kabaev       // requires special behaviour if _InIterator is an integral type
100*f8a1b7d9SAlexander Kabaev       template<typename _InIterator>
101*f8a1b7d9SAlexander Kabaev         void
102*f8a1b7d9SAlexander Kabaev         _M_construct_aux(_InIterator __beg, _InIterator __end,
103*f8a1b7d9SAlexander Kabaev 			 std::__false_type)
104*f8a1b7d9SAlexander Kabaev 	{
105*f8a1b7d9SAlexander Kabaev           typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
106*f8a1b7d9SAlexander Kabaev           _M_construct(__beg, __end, _Tag());
107*f8a1b7d9SAlexander Kabaev 	}
108*f8a1b7d9SAlexander Kabaev 
109*f8a1b7d9SAlexander Kabaev       template<typename _InIterator>
110*f8a1b7d9SAlexander Kabaev         void
111*f8a1b7d9SAlexander Kabaev         _M_construct_aux(_InIterator __beg, _InIterator __end,
112*f8a1b7d9SAlexander Kabaev 			 std::__true_type)
113*f8a1b7d9SAlexander Kabaev 	{ _M_construct(static_cast<size_type>(__beg),
114*f8a1b7d9SAlexander Kabaev 		       static_cast<value_type>(__end)); }
115*f8a1b7d9SAlexander Kabaev 
116*f8a1b7d9SAlexander Kabaev       template<typename _InIterator>
117*f8a1b7d9SAlexander Kabaev         void
118*f8a1b7d9SAlexander Kabaev         _M_construct(_InIterator __beg, _InIterator __end)
119*f8a1b7d9SAlexander Kabaev 	{
120*f8a1b7d9SAlexander Kabaev 	  typedef typename std::__is_integer<_InIterator>::__type _Integral;
121*f8a1b7d9SAlexander Kabaev 	  _M_construct_aux(__beg, __end, _Integral());
122*f8a1b7d9SAlexander Kabaev         }
123*f8a1b7d9SAlexander Kabaev 
124*f8a1b7d9SAlexander Kabaev       // For Input Iterators, used in istreambuf_iterators, etc.
125*f8a1b7d9SAlexander Kabaev       template<typename _InIterator>
126*f8a1b7d9SAlexander Kabaev         void
127*f8a1b7d9SAlexander Kabaev         _M_construct(_InIterator __beg, _InIterator __end,
128*f8a1b7d9SAlexander Kabaev 		     std::input_iterator_tag);
129*f8a1b7d9SAlexander Kabaev 
130*f8a1b7d9SAlexander Kabaev       // For forward_iterators up to random_access_iterators, used for
131*f8a1b7d9SAlexander Kabaev       // string::iterator, _CharT*, etc.
132*f8a1b7d9SAlexander Kabaev       template<typename _FwdIterator>
133*f8a1b7d9SAlexander Kabaev         void
134*f8a1b7d9SAlexander Kabaev         _M_construct(_FwdIterator __beg, _FwdIterator __end,
135*f8a1b7d9SAlexander Kabaev 		     std::forward_iterator_tag);
136*f8a1b7d9SAlexander Kabaev 
137*f8a1b7d9SAlexander Kabaev       void
138*f8a1b7d9SAlexander Kabaev       _M_construct(size_type __req, _CharT __c);
139*f8a1b7d9SAlexander Kabaev 
140*f8a1b7d9SAlexander Kabaev     public:
141*f8a1b7d9SAlexander Kabaev       size_type
142*f8a1b7d9SAlexander Kabaev       _M_max_size() const
143*f8a1b7d9SAlexander Kabaev       { return (_M_get_allocator().max_size() - 1) / 2; }
144*f8a1b7d9SAlexander Kabaev 
145*f8a1b7d9SAlexander Kabaev       _CharT*
146*f8a1b7d9SAlexander Kabaev       _M_data() const
147*f8a1b7d9SAlexander Kabaev       { return _M_dataplus._M_p; }
148*f8a1b7d9SAlexander Kabaev 
149*f8a1b7d9SAlexander Kabaev       size_type
150*f8a1b7d9SAlexander Kabaev       _M_length() const
151*f8a1b7d9SAlexander Kabaev       { return _M_string_length; }
152*f8a1b7d9SAlexander Kabaev 
153*f8a1b7d9SAlexander Kabaev       size_type
154*f8a1b7d9SAlexander Kabaev       _M_capacity() const
155*f8a1b7d9SAlexander Kabaev       {
156*f8a1b7d9SAlexander Kabaev 	return _M_is_local() ? size_type(_S_local_capacity)
157*f8a1b7d9SAlexander Kabaev 	                     : _M_allocated_capacity;
158*f8a1b7d9SAlexander Kabaev       }
159*f8a1b7d9SAlexander Kabaev 
160*f8a1b7d9SAlexander Kabaev       bool
161*f8a1b7d9SAlexander Kabaev       _M_is_shared() const
162*f8a1b7d9SAlexander Kabaev       { return false; }
163*f8a1b7d9SAlexander Kabaev 
164*f8a1b7d9SAlexander Kabaev       void
165*f8a1b7d9SAlexander Kabaev       _M_set_leaked() { }
166*f8a1b7d9SAlexander Kabaev 
167*f8a1b7d9SAlexander Kabaev       void
168*f8a1b7d9SAlexander Kabaev       _M_leak() { }
169*f8a1b7d9SAlexander Kabaev 
170*f8a1b7d9SAlexander Kabaev       void
171*f8a1b7d9SAlexander Kabaev       _M_set_length(size_type __n)
172*f8a1b7d9SAlexander Kabaev       {
173*f8a1b7d9SAlexander Kabaev 	_M_length(__n);
174*f8a1b7d9SAlexander Kabaev 	traits_type::assign(_M_data()[__n], _CharT());
175*f8a1b7d9SAlexander Kabaev       }
176*f8a1b7d9SAlexander Kabaev 
177*f8a1b7d9SAlexander Kabaev       __sso_string_base()
178*f8a1b7d9SAlexander Kabaev       : _M_dataplus(_Alloc(), _M_local_data)
179*f8a1b7d9SAlexander Kabaev       { _M_set_length(0); }
180*f8a1b7d9SAlexander Kabaev 
181*f8a1b7d9SAlexander Kabaev       __sso_string_base(const _Alloc& __a);
182*f8a1b7d9SAlexander Kabaev 
183*f8a1b7d9SAlexander Kabaev       __sso_string_base(const __sso_string_base& __rcs);
184*f8a1b7d9SAlexander Kabaev 
185*f8a1b7d9SAlexander Kabaev       __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a);
186*f8a1b7d9SAlexander Kabaev 
187*f8a1b7d9SAlexander Kabaev       template<typename _InputIterator>
188*f8a1b7d9SAlexander Kabaev         __sso_string_base(_InputIterator __beg, _InputIterator __end,
189*f8a1b7d9SAlexander Kabaev 			  const _Alloc& __a);
190*f8a1b7d9SAlexander Kabaev 
191*f8a1b7d9SAlexander Kabaev       ~__sso_string_base()
192*f8a1b7d9SAlexander Kabaev       { _M_dispose(); }
193*f8a1b7d9SAlexander Kabaev 
194*f8a1b7d9SAlexander Kabaev       _CharT_alloc_type&
195*f8a1b7d9SAlexander Kabaev       _M_get_allocator()
196*f8a1b7d9SAlexander Kabaev       { return _M_dataplus; }
197*f8a1b7d9SAlexander Kabaev 
198*f8a1b7d9SAlexander Kabaev       const _CharT_alloc_type&
199*f8a1b7d9SAlexander Kabaev       _M_get_allocator() const
200*f8a1b7d9SAlexander Kabaev       { return _M_dataplus; }
201*f8a1b7d9SAlexander Kabaev 
202*f8a1b7d9SAlexander Kabaev       void
203*f8a1b7d9SAlexander Kabaev       _M_swap(__sso_string_base& __rcs);
204*f8a1b7d9SAlexander Kabaev 
205*f8a1b7d9SAlexander Kabaev       void
206*f8a1b7d9SAlexander Kabaev       _M_assign(const __sso_string_base& __rcs);
207*f8a1b7d9SAlexander Kabaev 
208*f8a1b7d9SAlexander Kabaev       void
209*f8a1b7d9SAlexander Kabaev       _M_reserve(size_type __res);
210*f8a1b7d9SAlexander Kabaev 
211*f8a1b7d9SAlexander Kabaev       void
212*f8a1b7d9SAlexander Kabaev       _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
213*f8a1b7d9SAlexander Kabaev 		size_type __len2);
214*f8a1b7d9SAlexander Kabaev 
215*f8a1b7d9SAlexander Kabaev       void
216*f8a1b7d9SAlexander Kabaev       _M_erase(size_type __pos, size_type __n);
217*f8a1b7d9SAlexander Kabaev 
218*f8a1b7d9SAlexander Kabaev       void
219*f8a1b7d9SAlexander Kabaev       _M_clear()
220*f8a1b7d9SAlexander Kabaev       { _M_set_length(0); }
221*f8a1b7d9SAlexander Kabaev 
222*f8a1b7d9SAlexander Kabaev       bool
223*f8a1b7d9SAlexander Kabaev       _M_compare(const __sso_string_base&) const
224*f8a1b7d9SAlexander Kabaev       { return false; }
225*f8a1b7d9SAlexander Kabaev     };
226*f8a1b7d9SAlexander Kabaev 
227*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
228*f8a1b7d9SAlexander Kabaev     void
229*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_swap(__sso_string_base & __rcs)230*f8a1b7d9SAlexander Kabaev     _M_swap(__sso_string_base& __rcs)
231*f8a1b7d9SAlexander Kabaev     {
232*f8a1b7d9SAlexander Kabaev       // _GLIBCXX_RESOLVE_LIB_DEFECTS
233*f8a1b7d9SAlexander Kabaev       // 431. Swapping containers with unequal allocators.
234*f8a1b7d9SAlexander Kabaev       std::__alloc_swap<_CharT_alloc_type>::_S_do_it(_M_get_allocator(),
235*f8a1b7d9SAlexander Kabaev 						     __rcs._M_get_allocator());
236*f8a1b7d9SAlexander Kabaev 
237*f8a1b7d9SAlexander Kabaev       if (_M_is_local())
238*f8a1b7d9SAlexander Kabaev 	if (__rcs._M_is_local())
239*f8a1b7d9SAlexander Kabaev 	  {
240*f8a1b7d9SAlexander Kabaev 	    if (_M_length() && __rcs._M_length())
241*f8a1b7d9SAlexander Kabaev 	      {
242*f8a1b7d9SAlexander Kabaev 		_CharT __tmp_data[_S_local_capacity + 1];
243*f8a1b7d9SAlexander Kabaev 		traits_type::copy(__tmp_data, __rcs._M_local_data,
244*f8a1b7d9SAlexander Kabaev 				  _S_local_capacity + 1);
245*f8a1b7d9SAlexander Kabaev 		traits_type::copy(__rcs._M_local_data, _M_local_data,
246*f8a1b7d9SAlexander Kabaev 				  _S_local_capacity + 1);
247*f8a1b7d9SAlexander Kabaev 		traits_type::copy(_M_local_data, __tmp_data,
248*f8a1b7d9SAlexander Kabaev 				  _S_local_capacity + 1);
249*f8a1b7d9SAlexander Kabaev 	      }
250*f8a1b7d9SAlexander Kabaev 	    else if (__rcs._M_length())
251*f8a1b7d9SAlexander Kabaev 	      {
252*f8a1b7d9SAlexander Kabaev 		traits_type::copy(_M_local_data, __rcs._M_local_data,
253*f8a1b7d9SAlexander Kabaev 				  _S_local_capacity + 1);
254*f8a1b7d9SAlexander Kabaev 		_M_length(__rcs._M_length());
255*f8a1b7d9SAlexander Kabaev 		__rcs._M_set_length(0);
256*f8a1b7d9SAlexander Kabaev 		return;
257*f8a1b7d9SAlexander Kabaev 	      }
258*f8a1b7d9SAlexander Kabaev 	    else if (_M_length())
259*f8a1b7d9SAlexander Kabaev 	      {
260*f8a1b7d9SAlexander Kabaev 		traits_type::copy(__rcs._M_local_data, _M_local_data,
261*f8a1b7d9SAlexander Kabaev 				  _S_local_capacity + 1);
262*f8a1b7d9SAlexander Kabaev 		__rcs._M_length(_M_length());
263*f8a1b7d9SAlexander Kabaev 		_M_set_length(0);
264*f8a1b7d9SAlexander Kabaev 		return;
265*f8a1b7d9SAlexander Kabaev 	      }
266*f8a1b7d9SAlexander Kabaev 	  }
267*f8a1b7d9SAlexander Kabaev 	else
268*f8a1b7d9SAlexander Kabaev 	  {
269*f8a1b7d9SAlexander Kabaev 	    const size_type __tmp_capacity = __rcs._M_allocated_capacity;
270*f8a1b7d9SAlexander Kabaev 	    traits_type::copy(__rcs._M_local_data, _M_local_data,
271*f8a1b7d9SAlexander Kabaev 			      _S_local_capacity + 1);
272*f8a1b7d9SAlexander Kabaev 	    _M_data(__rcs._M_data());
273*f8a1b7d9SAlexander Kabaev 	    __rcs._M_data(__rcs._M_local_data);
274*f8a1b7d9SAlexander Kabaev 	    _M_capacity(__tmp_capacity);
275*f8a1b7d9SAlexander Kabaev 	  }
276*f8a1b7d9SAlexander Kabaev       else
277*f8a1b7d9SAlexander Kabaev 	{
278*f8a1b7d9SAlexander Kabaev 	  const size_type __tmp_capacity = _M_allocated_capacity;
279*f8a1b7d9SAlexander Kabaev 	  if (__rcs._M_is_local())
280*f8a1b7d9SAlexander Kabaev 	    {
281*f8a1b7d9SAlexander Kabaev 	      traits_type::copy(_M_local_data, __rcs._M_local_data,
282*f8a1b7d9SAlexander Kabaev 				_S_local_capacity + 1);
283*f8a1b7d9SAlexander Kabaev 	      __rcs._M_data(_M_data());
284*f8a1b7d9SAlexander Kabaev 	      _M_data(_M_local_data);
285*f8a1b7d9SAlexander Kabaev 	    }
286*f8a1b7d9SAlexander Kabaev 	  else
287*f8a1b7d9SAlexander Kabaev 	    {
288*f8a1b7d9SAlexander Kabaev 	      _CharT* __tmp_ptr = _M_data();
289*f8a1b7d9SAlexander Kabaev 	      _M_data(__rcs._M_data());
290*f8a1b7d9SAlexander Kabaev 	      __rcs._M_data(__tmp_ptr);
291*f8a1b7d9SAlexander Kabaev 	      _M_capacity(__rcs._M_allocated_capacity);
292*f8a1b7d9SAlexander Kabaev 	    }
293*f8a1b7d9SAlexander Kabaev 	  __rcs._M_capacity(__tmp_capacity);
294*f8a1b7d9SAlexander Kabaev 	}
295*f8a1b7d9SAlexander Kabaev 
296*f8a1b7d9SAlexander Kabaev       const size_type __tmp_length = _M_length();
297*f8a1b7d9SAlexander Kabaev       _M_length(__rcs._M_length());
298*f8a1b7d9SAlexander Kabaev       __rcs._M_length(__tmp_length);
299*f8a1b7d9SAlexander Kabaev     }
300*f8a1b7d9SAlexander Kabaev 
301*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
302*f8a1b7d9SAlexander Kabaev     _CharT*
303*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_create(size_type & __capacity,size_type __old_capacity)304*f8a1b7d9SAlexander Kabaev     _M_create(size_type& __capacity, size_type __old_capacity)
305*f8a1b7d9SAlexander Kabaev     {
306*f8a1b7d9SAlexander Kabaev       // _GLIBCXX_RESOLVE_LIB_DEFECTS
307*f8a1b7d9SAlexander Kabaev       // 83.  String::npos vs. string::max_size()
308*f8a1b7d9SAlexander Kabaev       if (__capacity > _M_max_size())
309*f8a1b7d9SAlexander Kabaev 	std::__throw_length_error(__N("__sso_string_base::_M_create"));
310*f8a1b7d9SAlexander Kabaev 
311*f8a1b7d9SAlexander Kabaev       // The below implements an exponential growth policy, necessary to
312*f8a1b7d9SAlexander Kabaev       // meet amortized linear time requirements of the library: see
313*f8a1b7d9SAlexander Kabaev       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
314*f8a1b7d9SAlexander Kabaev       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
315*f8a1b7d9SAlexander Kabaev 	{
316*f8a1b7d9SAlexander Kabaev 	  __capacity = 2 * __old_capacity;
317*f8a1b7d9SAlexander Kabaev 	  // Never allocate a string bigger than max_size.
318*f8a1b7d9SAlexander Kabaev 	  if (__capacity > _M_max_size())
319*f8a1b7d9SAlexander Kabaev 	    __capacity = _M_max_size();
320*f8a1b7d9SAlexander Kabaev 	}
321*f8a1b7d9SAlexander Kabaev 
322*f8a1b7d9SAlexander Kabaev       // NB: Need an array of char_type[__capacity], plus a terminating
323*f8a1b7d9SAlexander Kabaev       // null char_type() element.
324*f8a1b7d9SAlexander Kabaev       return _M_get_allocator().allocate(__capacity + 1);
325*f8a1b7d9SAlexander Kabaev     }
326*f8a1b7d9SAlexander Kabaev 
327*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
328*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(const _Alloc & __a)329*f8a1b7d9SAlexander Kabaev     __sso_string_base(const _Alloc& __a)
330*f8a1b7d9SAlexander Kabaev     : _M_dataplus(__a, _M_local_data)
331*f8a1b7d9SAlexander Kabaev     { _M_set_length(0); }
332*f8a1b7d9SAlexander Kabaev 
333*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
334*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(const __sso_string_base & __rcs)335*f8a1b7d9SAlexander Kabaev     __sso_string_base(const __sso_string_base& __rcs)
336*f8a1b7d9SAlexander Kabaev     : _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
337*f8a1b7d9SAlexander Kabaev     { _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length()); }
338*f8a1b7d9SAlexander Kabaev 
339*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
340*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(size_type __n,_CharT __c,const _Alloc & __a)341*f8a1b7d9SAlexander Kabaev     __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a)
342*f8a1b7d9SAlexander Kabaev     : _M_dataplus(__a, _M_local_data)
343*f8a1b7d9SAlexander Kabaev     { _M_construct(__n, __c); }
344*f8a1b7d9SAlexander Kabaev 
345*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
346*f8a1b7d9SAlexander Kabaev     template<typename _InputIterator>
347*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(_InputIterator __beg,_InputIterator __end,const _Alloc & __a)348*f8a1b7d9SAlexander Kabaev     __sso_string_base(_InputIterator __beg, _InputIterator __end,
349*f8a1b7d9SAlexander Kabaev 		      const _Alloc& __a)
350*f8a1b7d9SAlexander Kabaev     : _M_dataplus(__a, _M_local_data)
351*f8a1b7d9SAlexander Kabaev     { _M_construct(__beg, __end); }
352*f8a1b7d9SAlexander Kabaev 
353*f8a1b7d9SAlexander Kabaev   // NB: This is the special case for Input Iterators, used in
354*f8a1b7d9SAlexander Kabaev   // istreambuf_iterators, etc.
355*f8a1b7d9SAlexander Kabaev   // Input Iterators have a cost structure very different from
356*f8a1b7d9SAlexander Kabaev   // pointers, calling for a different coding style.
357*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
358*f8a1b7d9SAlexander Kabaev     template<typename _InIterator>
359*f8a1b7d9SAlexander Kabaev       void
360*f8a1b7d9SAlexander Kabaev       __sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(_InIterator __beg,_InIterator __end,std::input_iterator_tag)361*f8a1b7d9SAlexander Kabaev       _M_construct(_InIterator __beg, _InIterator __end,
362*f8a1b7d9SAlexander Kabaev 		   std::input_iterator_tag)
363*f8a1b7d9SAlexander Kabaev       {
364*f8a1b7d9SAlexander Kabaev 	size_type __len = 0;
365*f8a1b7d9SAlexander Kabaev 	size_type __capacity = size_type(_S_local_capacity);
366*f8a1b7d9SAlexander Kabaev 
367*f8a1b7d9SAlexander Kabaev 	while (__beg != __end && __len < __capacity)
368*f8a1b7d9SAlexander Kabaev 	  {
369*f8a1b7d9SAlexander Kabaev 	    _M_data()[__len++] = *__beg;
370*f8a1b7d9SAlexander Kabaev 	    ++__beg;
371*f8a1b7d9SAlexander Kabaev 	  }
372*f8a1b7d9SAlexander Kabaev 
373*f8a1b7d9SAlexander Kabaev 	try
374*f8a1b7d9SAlexander Kabaev 	  {
375*f8a1b7d9SAlexander Kabaev 	    while (__beg != __end)
376*f8a1b7d9SAlexander Kabaev 	      {
377*f8a1b7d9SAlexander Kabaev 		if (__len == __capacity)
378*f8a1b7d9SAlexander Kabaev 		  {
379*f8a1b7d9SAlexander Kabaev 		    // Allocate more space.
380*f8a1b7d9SAlexander Kabaev 		    __capacity = __len + 1;
381*f8a1b7d9SAlexander Kabaev 		    _CharT* __another = _M_create(__capacity, __len);
382*f8a1b7d9SAlexander Kabaev 		    _S_copy(__another, _M_data(), __len);
383*f8a1b7d9SAlexander Kabaev 		    _M_dispose();
384*f8a1b7d9SAlexander Kabaev 		    _M_data(__another);
385*f8a1b7d9SAlexander Kabaev 		    _M_capacity(__capacity);
386*f8a1b7d9SAlexander Kabaev 		  }
387*f8a1b7d9SAlexander Kabaev 		_M_data()[__len++] = *__beg;
388*f8a1b7d9SAlexander Kabaev 		++__beg;
389*f8a1b7d9SAlexander Kabaev 	      }
390*f8a1b7d9SAlexander Kabaev 	  }
391*f8a1b7d9SAlexander Kabaev 	catch(...)
392*f8a1b7d9SAlexander Kabaev 	  {
393*f8a1b7d9SAlexander Kabaev 	    _M_dispose();
394*f8a1b7d9SAlexander Kabaev 	    __throw_exception_again;
395*f8a1b7d9SAlexander Kabaev 	  }
396*f8a1b7d9SAlexander Kabaev 
397*f8a1b7d9SAlexander Kabaev 	_M_set_length(__len);
398*f8a1b7d9SAlexander Kabaev       }
399*f8a1b7d9SAlexander Kabaev 
400*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
401*f8a1b7d9SAlexander Kabaev     template<typename _InIterator>
402*f8a1b7d9SAlexander Kabaev       void
403*f8a1b7d9SAlexander Kabaev       __sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(_InIterator __beg,_InIterator __end,std::forward_iterator_tag)404*f8a1b7d9SAlexander Kabaev       _M_construct(_InIterator __beg, _InIterator __end,
405*f8a1b7d9SAlexander Kabaev 		   std::forward_iterator_tag)
406*f8a1b7d9SAlexander Kabaev       {
407*f8a1b7d9SAlexander Kabaev 	// NB: Not required, but considered best practice.
408*f8a1b7d9SAlexander Kabaev 	if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
409*f8a1b7d9SAlexander Kabaev 	  std::__throw_logic_error(__N("__sso_string_base::"
410*f8a1b7d9SAlexander Kabaev 				       "_M_construct NULL not valid"));
411*f8a1b7d9SAlexander Kabaev 
412*f8a1b7d9SAlexander Kabaev 	size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
413*f8a1b7d9SAlexander Kabaev 
414*f8a1b7d9SAlexander Kabaev 	if (__dnew > size_type(_S_local_capacity))
415*f8a1b7d9SAlexander Kabaev 	  {
416*f8a1b7d9SAlexander Kabaev 	    _M_data(_M_create(__dnew, size_type(0)));
417*f8a1b7d9SAlexander Kabaev 	    _M_capacity(__dnew);
418*f8a1b7d9SAlexander Kabaev 	  }
419*f8a1b7d9SAlexander Kabaev 
420*f8a1b7d9SAlexander Kabaev 	// Check for out_of_range and length_error exceptions.
421*f8a1b7d9SAlexander Kabaev 	try
422*f8a1b7d9SAlexander Kabaev 	  { _S_copy_chars(_M_data(), __beg, __end); }
423*f8a1b7d9SAlexander Kabaev 	catch(...)
424*f8a1b7d9SAlexander Kabaev 	  {
425*f8a1b7d9SAlexander Kabaev 	    _M_dispose();
426*f8a1b7d9SAlexander Kabaev 	    __throw_exception_again;
427*f8a1b7d9SAlexander Kabaev 	  }
428*f8a1b7d9SAlexander Kabaev 
429*f8a1b7d9SAlexander Kabaev 	_M_set_length(__dnew);
430*f8a1b7d9SAlexander Kabaev       }
431*f8a1b7d9SAlexander Kabaev 
432*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
433*f8a1b7d9SAlexander Kabaev     void
434*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(size_type __n,_CharT __c)435*f8a1b7d9SAlexander Kabaev     _M_construct(size_type __n, _CharT __c)
436*f8a1b7d9SAlexander Kabaev     {
437*f8a1b7d9SAlexander Kabaev       if (__n > size_type(_S_local_capacity))
438*f8a1b7d9SAlexander Kabaev 	{
439*f8a1b7d9SAlexander Kabaev 	  _M_data(_M_create(__n, size_type(0)));
440*f8a1b7d9SAlexander Kabaev 	  _M_capacity(__n);
441*f8a1b7d9SAlexander Kabaev 	}
442*f8a1b7d9SAlexander Kabaev 
443*f8a1b7d9SAlexander Kabaev       if (__n)
444*f8a1b7d9SAlexander Kabaev 	_S_assign(_M_data(), __n, __c);
445*f8a1b7d9SAlexander Kabaev 
446*f8a1b7d9SAlexander Kabaev       _M_set_length(__n);
447*f8a1b7d9SAlexander Kabaev     }
448*f8a1b7d9SAlexander Kabaev 
449*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
450*f8a1b7d9SAlexander Kabaev     void
451*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_assign(const __sso_string_base & __rcs)452*f8a1b7d9SAlexander Kabaev     _M_assign(const __sso_string_base& __rcs)
453*f8a1b7d9SAlexander Kabaev     {
454*f8a1b7d9SAlexander Kabaev       if (this != &__rcs)
455*f8a1b7d9SAlexander Kabaev 	{
456*f8a1b7d9SAlexander Kabaev 	  const size_type __rsize = __rcs._M_length();
457*f8a1b7d9SAlexander Kabaev 	  const size_type __capacity = _M_capacity();
458*f8a1b7d9SAlexander Kabaev 
459*f8a1b7d9SAlexander Kabaev 	  if (__rsize > __capacity)
460*f8a1b7d9SAlexander Kabaev 	    {
461*f8a1b7d9SAlexander Kabaev 	      size_type __new_capacity = __rsize;
462*f8a1b7d9SAlexander Kabaev 	      _CharT* __tmp = _M_create(__new_capacity, __capacity);
463*f8a1b7d9SAlexander Kabaev 	      _M_dispose();
464*f8a1b7d9SAlexander Kabaev 	      _M_data(__tmp);
465*f8a1b7d9SAlexander Kabaev 	      _M_capacity(__new_capacity);
466*f8a1b7d9SAlexander Kabaev 	    }
467*f8a1b7d9SAlexander Kabaev 
468*f8a1b7d9SAlexander Kabaev 	  if (__rsize)
469*f8a1b7d9SAlexander Kabaev 	    _S_copy(_M_data(), __rcs._M_data(), __rsize);
470*f8a1b7d9SAlexander Kabaev 
471*f8a1b7d9SAlexander Kabaev 	  _M_set_length(__rsize);
472*f8a1b7d9SAlexander Kabaev 	}
473*f8a1b7d9SAlexander Kabaev     }
474*f8a1b7d9SAlexander Kabaev 
475*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
476*f8a1b7d9SAlexander Kabaev     void
477*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_reserve(size_type __res)478*f8a1b7d9SAlexander Kabaev     _M_reserve(size_type __res)
479*f8a1b7d9SAlexander Kabaev     {
480*f8a1b7d9SAlexander Kabaev       // Make sure we don't shrink below the current size.
481*f8a1b7d9SAlexander Kabaev       if (__res < _M_length())
482*f8a1b7d9SAlexander Kabaev 	__res = _M_length();
483*f8a1b7d9SAlexander Kabaev 
484*f8a1b7d9SAlexander Kabaev       const size_type __capacity = _M_capacity();
485*f8a1b7d9SAlexander Kabaev       if (__res != __capacity)
486*f8a1b7d9SAlexander Kabaev 	{
487*f8a1b7d9SAlexander Kabaev 	  if (__res > __capacity
488*f8a1b7d9SAlexander Kabaev 	      || __res > size_type(_S_local_capacity))
489*f8a1b7d9SAlexander Kabaev 	    {
490*f8a1b7d9SAlexander Kabaev 	      _CharT* __tmp = _M_create(__res, __capacity);
491*f8a1b7d9SAlexander Kabaev 	      _S_copy(__tmp, _M_data(), _M_length() + 1);
492*f8a1b7d9SAlexander Kabaev 	      _M_dispose();
493*f8a1b7d9SAlexander Kabaev 	      _M_data(__tmp);
494*f8a1b7d9SAlexander Kabaev 	      _M_capacity(__res);
495*f8a1b7d9SAlexander Kabaev 	    }
496*f8a1b7d9SAlexander Kabaev 	  else if (!_M_is_local())
497*f8a1b7d9SAlexander Kabaev 	    {
498*f8a1b7d9SAlexander Kabaev 	      _S_copy(_M_local_data, _M_data(), _M_length() + 1);
499*f8a1b7d9SAlexander Kabaev 	      _M_destroy(__capacity);
500*f8a1b7d9SAlexander Kabaev 	      _M_data(_M_local_data);
501*f8a1b7d9SAlexander Kabaev 	    }
502*f8a1b7d9SAlexander Kabaev 	}
503*f8a1b7d9SAlexander Kabaev     }
504*f8a1b7d9SAlexander Kabaev 
505*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
506*f8a1b7d9SAlexander Kabaev     void
507*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_mutate(size_type __pos,size_type __len1,const _CharT * __s,const size_type __len2)508*f8a1b7d9SAlexander Kabaev     _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
509*f8a1b7d9SAlexander Kabaev 	      const size_type __len2)
510*f8a1b7d9SAlexander Kabaev     {
511*f8a1b7d9SAlexander Kabaev       const size_type __how_much = _M_length() - __pos - __len1;
512*f8a1b7d9SAlexander Kabaev 
513*f8a1b7d9SAlexander Kabaev       size_type __new_capacity = _M_length() + __len2 - __len1;
514*f8a1b7d9SAlexander Kabaev       _CharT* __r = _M_create(__new_capacity, _M_capacity());
515*f8a1b7d9SAlexander Kabaev 
516*f8a1b7d9SAlexander Kabaev       if (__pos)
517*f8a1b7d9SAlexander Kabaev 	_S_copy(__r, _M_data(), __pos);
518*f8a1b7d9SAlexander Kabaev       if (__s && __len2)
519*f8a1b7d9SAlexander Kabaev 	_S_copy(__r + __pos, __s, __len2);
520*f8a1b7d9SAlexander Kabaev       if (__how_much)
521*f8a1b7d9SAlexander Kabaev 	_S_copy(__r + __pos + __len2,
522*f8a1b7d9SAlexander Kabaev 		_M_data() + __pos + __len1, __how_much);
523*f8a1b7d9SAlexander Kabaev 
524*f8a1b7d9SAlexander Kabaev       _M_dispose();
525*f8a1b7d9SAlexander Kabaev       _M_data(__r);
526*f8a1b7d9SAlexander Kabaev       _M_capacity(__new_capacity);
527*f8a1b7d9SAlexander Kabaev     }
528*f8a1b7d9SAlexander Kabaev 
529*f8a1b7d9SAlexander Kabaev   template<typename _CharT, typename _Traits, typename _Alloc>
530*f8a1b7d9SAlexander Kabaev     void
531*f8a1b7d9SAlexander Kabaev     __sso_string_base<_CharT, _Traits, _Alloc>::
_M_erase(size_type __pos,size_type __n)532*f8a1b7d9SAlexander Kabaev     _M_erase(size_type __pos, size_type __n)
533*f8a1b7d9SAlexander Kabaev     {
534*f8a1b7d9SAlexander Kabaev       const size_type __how_much = _M_length() - __pos - __n;
535*f8a1b7d9SAlexander Kabaev 
536*f8a1b7d9SAlexander Kabaev       if (__how_much && __n)
537*f8a1b7d9SAlexander Kabaev 	_S_move(_M_data() + __pos, _M_data() + __pos + __n,
538*f8a1b7d9SAlexander Kabaev 		__how_much);
539*f8a1b7d9SAlexander Kabaev 
540*f8a1b7d9SAlexander Kabaev       _M_set_length(_M_length() - __n);
541*f8a1b7d9SAlexander Kabaev     }
542*f8a1b7d9SAlexander Kabaev 
543*f8a1b7d9SAlexander Kabaev   template<>
544*f8a1b7d9SAlexander Kabaev     inline bool
545*f8a1b7d9SAlexander Kabaev     __sso_string_base<char, std::char_traits<char>,
546*f8a1b7d9SAlexander Kabaev 		      std::allocator<char> >::
_M_compare(const __sso_string_base & __rcs)547*f8a1b7d9SAlexander Kabaev     _M_compare(const __sso_string_base& __rcs) const
548*f8a1b7d9SAlexander Kabaev     {
549*f8a1b7d9SAlexander Kabaev       if (this == &__rcs)
550*f8a1b7d9SAlexander Kabaev 	return true;
551*f8a1b7d9SAlexander Kabaev       return false;
552*f8a1b7d9SAlexander Kabaev     }
553*f8a1b7d9SAlexander Kabaev 
554*f8a1b7d9SAlexander Kabaev #ifdef _GLIBCXX_USE_WCHAR_T
555*f8a1b7d9SAlexander Kabaev   template<>
556*f8a1b7d9SAlexander Kabaev     inline bool
557*f8a1b7d9SAlexander Kabaev     __sso_string_base<wchar_t, std::char_traits<wchar_t>,
558*f8a1b7d9SAlexander Kabaev 		      std::allocator<wchar_t> >::
_M_compare(const __sso_string_base & __rcs)559*f8a1b7d9SAlexander Kabaev     _M_compare(const __sso_string_base& __rcs) const
560*f8a1b7d9SAlexander Kabaev     {
561*f8a1b7d9SAlexander Kabaev       if (this == &__rcs)
562*f8a1b7d9SAlexander Kabaev 	return true;
563*f8a1b7d9SAlexander Kabaev       return false;
564*f8a1b7d9SAlexander Kabaev     }
565*f8a1b7d9SAlexander Kabaev #endif
566*f8a1b7d9SAlexander Kabaev 
567*f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE
568*f8a1b7d9SAlexander Kabaev 
569*f8a1b7d9SAlexander Kabaev #endif /* _SSO_STRING_BASE_H */
570