00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef _RC_STRING_BASE_H
00033 #define _RC_STRING_BASE_H 1
00034
00035 #include <ext/atomicity.h>
00036 #include <bits/stl_iterator_base_funcs.h>
00037
00038 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 template<typename _CharT, typename _Traits, typename _Alloc>
00082 class __rc_string_base
00083 : protected __vstring_utility<_CharT, _Traits, _Alloc>
00084 {
00085 public:
00086 typedef _Traits traits_type;
00087 typedef typename _Traits::char_type value_type;
00088 typedef _Alloc allocator_type;
00089
00090 typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
00091 typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
00092 typedef typename _CharT_alloc_type::size_type size_type;
00093
00094 private:
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 struct _Rep
00109 {
00110 union
00111 {
00112 struct
00113 {
00114 size_type _M_length;
00115 size_type _M_capacity;
00116 _Atomic_word _M_refcount;
00117 } _M_info;
00118
00119
00120 _CharT _M_align;
00121 };
00122
00123 typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
00124
00125 _CharT*
00126 _M_refdata() throw()
00127 { return reinterpret_cast<_CharT*>(this + 1); }
00128
00129 _CharT*
00130 _M_refcopy() throw()
00131 {
00132 __atomic_add_dispatch(&_M_info._M_refcount, 1);
00133 return _M_refdata();
00134 }
00135
00136 void
00137 _M_set_length(size_type __n)
00138 {
00139 _M_info._M_refcount = 0;
00140 _M_info._M_length = __n;
00141
00142
00143 traits_type::assign(_M_refdata()[__n], _CharT());
00144 }
00145
00146
00147 static _Rep*
00148 _S_create(size_type, size_type, const _Alloc&);
00149
00150 void
00151 _M_destroy(const _Alloc&) throw();
00152
00153 _CharT*
00154 _M_clone(const _Alloc&, size_type __res = 0);
00155 };
00156
00157 struct _Rep_empty
00158 : public _Rep
00159 {
00160 _CharT _M_terminal;
00161 };
00162
00163 static _Rep_empty _S_empty_rep;
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 enum { _S_max_size = (((static_cast<size_type>(-1) - 2 * sizeof(_Rep)
00179 + 1) / sizeof(_CharT)) - 1) / 2 };
00180
00181
00182 mutable typename _Util_Base::template _Alloc_hider<_Alloc> _M_dataplus;
00183
00184 void
00185 _M_data(_CharT* __p)
00186 { _M_dataplus._M_p = __p; }
00187
00188 _Rep*
00189 _M_rep() const
00190 { return &((reinterpret_cast<_Rep*>(_M_data()))[-1]); }
00191
00192 _CharT*
00193 _M_grab(const _Alloc& __alloc) const
00194 {
00195 return (!_M_is_leaked() && _M_get_allocator() == __alloc)
00196 ? _M_rep()->_M_refcopy() : _M_rep()->_M_clone(__alloc);
00197 }
00198
00199 void
00200 _M_dispose()
00201 {
00202
00203 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_rep()->_M_info.
00204 _M_refcount);
00205 if (__exchange_and_add_dispatch(&_M_rep()->_M_info._M_refcount,
00206 -1) <= 0)
00207 {
00208 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_rep()->_M_info.
00209 _M_refcount);
00210 _M_rep()->_M_destroy(_M_get_allocator());
00211 }
00212 }
00213
00214 bool
00215 _M_is_leaked() const
00216 { return _M_rep()->_M_info._M_refcount < 0; }
00217
00218 void
00219 _M_set_sharable()
00220 { _M_rep()->_M_info._M_refcount = 0; }
00221
00222 void
00223 _M_leak_hard();
00224
00225
00226
00227 template<typename _InIterator>
00228 static _CharT*
00229 _S_construct_aux(_InIterator __beg, _InIterator __end,
00230 const _Alloc& __a, std::__false_type)
00231 {
00232 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
00233 return _S_construct(__beg, __end, __a, _Tag());
00234 }
00235
00236
00237
00238 template<typename _Integer>
00239 static _CharT*
00240 _S_construct_aux(_Integer __beg, _Integer __end,
00241 const _Alloc& __a, std::__true_type)
00242 { return _S_construct_aux_2(static_cast<size_type>(__beg),
00243 __end, __a); }
00244
00245 static _CharT*
00246 _S_construct_aux_2(size_type __req, _CharT __c, const _Alloc& __a)
00247 { return _S_construct(__req, __c, __a); }
00248
00249 template<typename _InIterator>
00250 static _CharT*
00251 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
00252 {
00253 typedef typename std::__is_integer<_InIterator>::__type _Integral;
00254 return _S_construct_aux(__beg, __end, __a, _Integral());
00255 }
00256
00257
00258 template<typename _InIterator>
00259 static _CharT*
00260 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
00261 std::input_iterator_tag);
00262
00263
00264
00265 template<typename _FwdIterator>
00266 static _CharT*
00267 _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
00268 std::forward_iterator_tag);
00269
00270 static _CharT*
00271 _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
00272
00273 public:
00274 size_type
00275 _M_max_size() const
00276 { return size_type(_S_max_size); }
00277
00278 _CharT*
00279 _M_data() const
00280 { return _M_dataplus._M_p; }
00281
00282 size_type
00283 _M_length() const
00284 { return _M_rep()->_M_info._M_length; }
00285
00286 size_type
00287 _M_capacity() const
00288 { return _M_rep()->_M_info._M_capacity; }
00289
00290 bool
00291 _M_is_shared() const
00292 { return _M_rep()->_M_info._M_refcount > 0; }
00293
00294 void
00295 _M_set_leaked()
00296 { _M_rep()->_M_info._M_refcount = -1; }
00297
00298 void
00299 _M_leak()
00300 {
00301 if (!_M_is_leaked())
00302 _M_leak_hard();
00303 }
00304
00305 void
00306 _M_set_length(size_type __n)
00307 { _M_rep()->_M_set_length(__n); }
00308
00309 __rc_string_base()
00310 : _M_dataplus(_S_empty_rep._M_refcopy()) { }
00311
00312 __rc_string_base(const _Alloc& __a);
00313
00314 __rc_string_base(const __rc_string_base& __rcs);
00315
00316 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00317 __rc_string_base(__rc_string_base&& __rcs)
00318 : _M_dataplus(__rcs._M_dataplus)
00319 { __rcs._M_data(_S_empty_rep._M_refcopy()); }
00320 #endif
00321
00322 __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a);
00323
00324 template<typename _InputIterator>
00325 __rc_string_base(_InputIterator __beg, _InputIterator __end,
00326 const _Alloc& __a);
00327
00328 ~__rc_string_base()
00329 { _M_dispose(); }
00330
00331 allocator_type&
00332 _M_get_allocator()
00333 { return _M_dataplus; }
00334
00335 const allocator_type&
00336 _M_get_allocator() const
00337 { return _M_dataplus; }
00338
00339 void
00340 _M_swap(__rc_string_base& __rcs);
00341
00342 void
00343 _M_assign(const __rc_string_base& __rcs);
00344
00345 void
00346 _M_reserve(size_type __res);
00347
00348 void
00349 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
00350 size_type __len2);
00351
00352 void
00353 _M_erase(size_type __pos, size_type __n);
00354
00355 void
00356 _M_clear()
00357 { _M_erase(size_type(0), _M_length()); }
00358
00359 bool
00360 _M_compare(const __rc_string_base&) const
00361 { return false; }
00362 };
00363
00364 template<typename _CharT, typename _Traits, typename _Alloc>
00365 typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
00366 __rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
00367
00368 template<typename _CharT, typename _Traits, typename _Alloc>
00369 typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
00370 __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
00371 _S_create(size_type __capacity, size_type __old_capacity,
00372 const _Alloc& __alloc)
00373 {
00374
00375
00376 if (__capacity > size_type(_S_max_size))
00377 std::__throw_length_error(__N("__rc_string_base::_Rep::_S_create"));
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 const size_type __pagesize = 4096;
00403 const size_type __malloc_header_size = 4 * sizeof(void*);
00404
00405
00406
00407
00408 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
00409 {
00410 __capacity = 2 * __old_capacity;
00411
00412 if (__capacity > size_type(_S_max_size))
00413 __capacity = size_type(_S_max_size);
00414 }
00415
00416
00417
00418
00419
00420
00421 size_type __size = ((__capacity + 1) * sizeof(_CharT)
00422 + 2 * sizeof(_Rep) - 1);
00423
00424 const size_type __adj_size = __size + __malloc_header_size;
00425 if (__adj_size > __pagesize && __capacity > __old_capacity)
00426 {
00427 const size_type __extra = __pagesize - __adj_size % __pagesize;
00428 __capacity += __extra / sizeof(_CharT);
00429 if (__capacity > size_type(_S_max_size))
00430 __capacity = size_type(_S_max_size);
00431 __size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
00432 }
00433
00434
00435
00436 _Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
00437 _Rep* __p = new (__place) _Rep;
00438 __p->_M_info._M_capacity = __capacity;
00439 return __p;
00440 }
00441
00442 template<typename _CharT, typename _Traits, typename _Alloc>
00443 void
00444 __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
00445 _M_destroy(const _Alloc& __a) throw ()
00446 {
00447 const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
00448 + 2 * sizeof(_Rep) - 1);
00449 _Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
00450 }
00451
00452 template<typename _CharT, typename _Traits, typename _Alloc>
00453 _CharT*
00454 __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
00455 _M_clone(const _Alloc& __alloc, size_type __res)
00456 {
00457
00458 const size_type __requested_cap = _M_info._M_length + __res;
00459 _Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
00460 __alloc);
00461
00462 if (_M_info._M_length)
00463 _S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
00464
00465 __r->_M_set_length(_M_info._M_length);
00466 return __r->_M_refdata();
00467 }
00468
00469 template<typename _CharT, typename _Traits, typename _Alloc>
00470 __rc_string_base<_CharT, _Traits, _Alloc>::
00471 __rc_string_base(const _Alloc& __a)
00472 : _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
00473
00474 template<typename _CharT, typename _Traits, typename _Alloc>
00475 __rc_string_base<_CharT, _Traits, _Alloc>::
00476 __rc_string_base(const __rc_string_base& __rcs)
00477 : _M_dataplus(__rcs._M_get_allocator(),
00478 __rcs._M_grab(__rcs._M_get_allocator())) { }
00479
00480 template<typename _CharT, typename _Traits, typename _Alloc>
00481 __rc_string_base<_CharT, _Traits, _Alloc>::
00482 __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
00483 : _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
00484
00485 template<typename _CharT, typename _Traits, typename _Alloc>
00486 template<typename _InputIterator>
00487 __rc_string_base<_CharT, _Traits, _Alloc>::
00488 __rc_string_base(_InputIterator __beg, _InputIterator __end,
00489 const _Alloc& __a)
00490 : _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
00491
00492 template<typename _CharT, typename _Traits, typename _Alloc>
00493 void
00494 __rc_string_base<_CharT, _Traits, _Alloc>::
00495 _M_leak_hard()
00496 {
00497 if (_M_is_shared())
00498 _M_erase(0, 0);
00499 _M_set_leaked();
00500 }
00501
00502
00503
00504
00505
00506 template<typename _CharT, typename _Traits, typename _Alloc>
00507 template<typename _InIterator>
00508 _CharT*
00509 __rc_string_base<_CharT, _Traits, _Alloc>::
00510 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
00511 std::input_iterator_tag)
00512 {
00513 if (__beg == __end && __a == _Alloc())
00514 return _S_empty_rep._M_refcopy();
00515
00516
00517 _CharT __buf[128];
00518 size_type __len = 0;
00519 while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
00520 {
00521 __buf[__len++] = *__beg;
00522 ++__beg;
00523 }
00524 _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
00525 _S_copy(__r->_M_refdata(), __buf, __len);
00526 __try
00527 {
00528 while (__beg != __end)
00529 {
00530 if (__len == __r->_M_info._M_capacity)
00531 {
00532
00533 _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
00534 _S_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
00535 __r->_M_destroy(__a);
00536 __r = __another;
00537 }
00538 __r->_M_refdata()[__len++] = *__beg;
00539 ++__beg;
00540 }
00541 }
00542 __catch(...)
00543 {
00544 __r->_M_destroy(__a);
00545 __throw_exception_again;
00546 }
00547 __r->_M_set_length(__len);
00548 return __r->_M_refdata();
00549 }
00550
00551 template<typename _CharT, typename _Traits, typename _Alloc>
00552 template<typename _InIterator>
00553 _CharT*
00554 __rc_string_base<_CharT, _Traits, _Alloc>::
00555 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
00556 std::forward_iterator_tag)
00557 {
00558 if (__beg == __end && __a == _Alloc())
00559 return _S_empty_rep._M_refcopy();
00560
00561
00562 if (__is_null_pointer(__beg) && __beg != __end)
00563 std::__throw_logic_error(__N("__rc_string_base::"
00564 "_S_construct null not valid"));
00565
00566 const size_type __dnew = static_cast<size_type>(std::distance(__beg,
00567 __end));
00568
00569 _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
00570 __try
00571 { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
00572 __catch(...)
00573 {
00574 __r->_M_destroy(__a);
00575 __throw_exception_again;
00576 }
00577 __r->_M_set_length(__dnew);
00578 return __r->_M_refdata();
00579 }
00580
00581 template<typename _CharT, typename _Traits, typename _Alloc>
00582 _CharT*
00583 __rc_string_base<_CharT, _Traits, _Alloc>::
00584 _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
00585 {
00586 if (__n == 0 && __a == _Alloc())
00587 return _S_empty_rep._M_refcopy();
00588
00589
00590 _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
00591 if (__n)
00592 _S_assign(__r->_M_refdata(), __n, __c);
00593
00594 __r->_M_set_length(__n);
00595 return __r->_M_refdata();
00596 }
00597
00598 template<typename _CharT, typename _Traits, typename _Alloc>
00599 void
00600 __rc_string_base<_CharT, _Traits, _Alloc>::
00601 _M_swap(__rc_string_base& __rcs)
00602 {
00603 if (_M_is_leaked())
00604 _M_set_sharable();
00605 if (__rcs._M_is_leaked())
00606 __rcs._M_set_sharable();
00607
00608 _CharT* __tmp = _M_data();
00609 _M_data(__rcs._M_data());
00610 __rcs._M_data(__tmp);
00611
00612
00613
00614 std::__alloc_swap<allocator_type>::_S_do_it(_M_get_allocator(),
00615 __rcs._M_get_allocator());
00616 }
00617
00618 template<typename _CharT, typename _Traits, typename _Alloc>
00619 void
00620 __rc_string_base<_CharT, _Traits, _Alloc>::
00621 _M_assign(const __rc_string_base& __rcs)
00622 {
00623 if (_M_rep() != __rcs._M_rep())
00624 {
00625 _CharT* __tmp = __rcs._M_grab(_M_get_allocator());
00626 _M_dispose();
00627 _M_data(__tmp);
00628 }
00629 }
00630
00631 template<typename _CharT, typename _Traits, typename _Alloc>
00632 void
00633 __rc_string_base<_CharT, _Traits, _Alloc>::
00634 _M_reserve(size_type __res)
00635 {
00636
00637 if (__res < _M_length())
00638 __res = _M_length();
00639
00640 if (__res != _M_capacity() || _M_is_shared())
00641 {
00642 _CharT* __tmp = _M_rep()->_M_clone(_M_get_allocator(),
00643 __res - _M_length());
00644 _M_dispose();
00645 _M_data(__tmp);
00646 }
00647 }
00648
00649 template<typename _CharT, typename _Traits, typename _Alloc>
00650 void
00651 __rc_string_base<_CharT, _Traits, _Alloc>::
00652 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
00653 size_type __len2)
00654 {
00655 const size_type __how_much = _M_length() - __pos - __len1;
00656
00657 _Rep* __r = _Rep::_S_create(_M_length() + __len2 - __len1,
00658 _M_capacity(), _M_get_allocator());
00659
00660 if (__pos)
00661 _S_copy(__r->_M_refdata(), _M_data(), __pos);
00662 if (__s && __len2)
00663 _S_copy(__r->_M_refdata() + __pos, __s, __len2);
00664 if (__how_much)
00665 _S_copy(__r->_M_refdata() + __pos + __len2,
00666 _M_data() + __pos + __len1, __how_much);
00667
00668 _M_dispose();
00669 _M_data(__r->_M_refdata());
00670 }
00671
00672 template<typename _CharT, typename _Traits, typename _Alloc>
00673 void
00674 __rc_string_base<_CharT, _Traits, _Alloc>::
00675 _M_erase(size_type __pos, size_type __n)
00676 {
00677 const size_type __new_size = _M_length() - __n;
00678 const size_type __how_much = _M_length() - __pos - __n;
00679
00680 if (_M_is_shared())
00681 {
00682
00683 _Rep* __r = _Rep::_S_create(__new_size, _M_capacity(),
00684 _M_get_allocator());
00685
00686 if (__pos)
00687 _S_copy(__r->_M_refdata(), _M_data(), __pos);
00688 if (__how_much)
00689 _S_copy(__r->_M_refdata() + __pos,
00690 _M_data() + __pos + __n, __how_much);
00691
00692 _M_dispose();
00693 _M_data(__r->_M_refdata());
00694 }
00695 else if (__how_much && __n)
00696 {
00697
00698 _S_move(_M_data() + __pos,
00699 _M_data() + __pos + __n, __how_much);
00700 }
00701
00702 _M_rep()->_M_set_length(__new_size);
00703 }
00704
00705 template<>
00706 inline bool
00707 __rc_string_base<char, std::char_traits<char>,
00708 std::allocator<char> >::
00709 _M_compare(const __rc_string_base& __rcs) const
00710 {
00711 if (_M_rep() == __rcs._M_rep())
00712 return true;
00713 return false;
00714 }
00715
00716 #ifdef _GLIBCXX_USE_WCHAR_T
00717 template<>
00718 inline bool
00719 __rc_string_base<wchar_t, std::char_traits<wchar_t>,
00720 std::allocator<wchar_t> >::
00721 _M_compare(const __rc_string_base& __rcs) const
00722 {
00723 if (_M_rep() == __rcs._M_rep())
00724 return true;
00725 return false;
00726 }
00727 #endif
00728
00729 _GLIBCXX_END_NAMESPACE
00730
00731 #endif