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