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