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