This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3, v7-branch] Add alternate basic_string base class
- From: Paolo Carlini <pcarlini at suse dot de>
- To: "'gcc-patches at gcc dot gnu dot org'" <gcc-patches at gcc dot gnu dot org>
- Cc: Dan Kegel <dank at kegel dot com>
- Date: Fri, 10 Jun 2005 22:41:10 +0200
- Subject: [v3, v7-branch] Add alternate basic_string base class
Hi,
the below adds an alternate base class, not reference-counted and
(lightly) optimized for short strings (i.e., no dynamical memory
allocations for lengths <= 15): in principle, classes of heavily MT
applications should benefit from it. This is only a first stab - there
are rough spots and we have plans for additional improvements - but
should be already rather stable: I'm also changing the default in order
to facilitate further testing.
Tested x86-linux, check/check-performance.
Paolo.
///////////////////
2005-06-10 Paolo Carlini <pcarlini@suse.de>
* acinclude.m4: Add __sso_string and change the default.
* config/linker-map.gnu: Add symbols.
* config/string/sso_string_base.h: Add.
* include/Makefile.am: Add sso_string.h.
* include/ext/sso_string.h: New basic_string base class (not
reference counted + simple optimization for short strings).
* src/Makefile.am: Add sso_string-inst.cc, wsso_string-inst.cc.
* src/sso_string-inst.cc: __sso_string<char> instantiations.
* src/wsso_string-inst.cc: Likewise for wchar_t.
* configure: Regenerate.
* include/Makefile.in: Likewise.
* src/Makefile.in: Likewise.
diff -urN libstdc++-v3-orig/acinclude.m4 libstdc++-v3/acinclude.m4
--- libstdc++-v3-orig/acinclude.m4 2005-06-05 14:21:19.000000000 +0200
+++ libstdc++-v3/acinclude.m4 2005-06-09 14:16:11.000000000 +0200
@@ -1318,7 +1318,7 @@
AC_MSG_CHECKING([for std::basic_string base class to use])
GLIBCXX_ENABLE(libstdcxx-string,auto,[=KIND],
[use KIND for target std::basic_string base],
- [permit rc|yes|no|auto])
+ [permit rc|sso|yes|no|auto])
# If they didn't use this option switch, or if they specified --enable
# with no specific model, we'll have to look for one. If they
@@ -1338,10 +1338,10 @@
if test $enable_libstdcxx_string_flag = auto; then
case ${target_os} in
linux* | gnu* | kfreebsd*-gnu | knetbsd*-gnu)
- enable_libstdcxx_string_flag=rc
+ enable_libstdcxx_string_flag=sso
;;
*)
- enable_libstdcxx_string_flag=rc
+ enable_libstdcxx_string_flag=sso
;;
esac
fi
@@ -1354,6 +1354,10 @@
STRING_H=config/string/rc_string_base.h
STRING_NAME=__gnu_cxx::__rc_string
;;
+ sso)
+ STRING_H=config/string/sso_string_base.h
+ STRING_NAME=__gnu_cxx::__sso_string
+ ;;
esac
AC_SUBST(STRING_H)
diff -urN libstdc++-v3-orig/config/linker-map.gnu libstdc++-v3/config/linker-map.gnu
--- libstdc++-v3-orig/config/linker-map.gnu 2005-06-05 14:22:22.000000000 +0200
+++ libstdc++-v3/config/linker-map.gnu 2005-06-09 14:20:22.000000000 +0200
@@ -306,6 +306,10 @@
_ZZN9__gnu_cxx20__common_pool_policyINS_6__poolELb1EE18_S_initialize_onceEvE6__init;
_ZGVZN9__gnu_cxx20__common_pool_policyINS_6__poolELb1EE11_S_get_poolEvE7_S_pool;
+ _ZN9__gnu_cxx12__sso_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE*;
+ _ZNK9__gnu_cxx12__sso_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE*;
+ _ZZN9__gnu_cxx12__sso_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE*;
+
# DO NOT DELETE THIS LINE. Port-specific symbols, if any, will be here.
local:
diff -urN libstdc++-v3-orig/config/string/sso_string_base.h libstdc++-v3/config/string/sso_string_base.h
--- libstdc++-v3-orig/config/string/sso_string_base.h 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/config/string/sso_string_base.h 2005-06-09 14:15:14.000000000 +0200
@@ -0,0 +1,37 @@
+// Base to std::basic_string -*- C++ -*-
+
+// Copyright (C) 2005 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _CXX_STRING_H
+#define _CXX_STRING_H 1
+
+// Define sso_string as the base class to std::basic_string.
+#include <ext/sso_string.h>
+#define __glibcxx_base_string __gnu_cxx::__sso_string
+
+#endif
diff -urN libstdc++-v3-orig/include/Makefile.am libstdc++-v3/include/Makefile.am
--- libstdc++-v3-orig/include/Makefile.am 2005-06-05 14:22:27.000000000 +0200
+++ libstdc++-v3/include/Makefile.am 2005-06-09 14:18:53.000000000 +0200
@@ -221,6 +221,7 @@
${ext_srcdir}/pool_allocator.h \
${ext_srcdir}/rb_tree \
${ext_srcdir}/rc_string.h \
+ ${ext_srcdir}/sso_string.h \
${ext_srcdir}/string_util.h \
${ext_srcdir}/rope \
${ext_srcdir}/ropeimpl.h \
diff -urN libstdc++-v3-orig/include/ext/sso_string.h libstdc++-v3/include/ext/sso_string.h
--- libstdc++-v3-orig/include/ext/sso_string.h 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/include/ext/sso_string.h 2005-06-10 20:39:06.000000000 +0200
@@ -0,0 +1,596 @@
+// Short-string-optimized string -*- C++ -*-
+
+// Copyright (C) 2005 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file ext/sso_string.h
+ * This file is a GNU extension to the Standard C++ Library.
+ */
+
+#ifndef _SSO_STRING_H
+#define _SSO_STRING_H 1
+
+#include <bits/functexcept.h>
+#include <bits/stringfwd.h>
+#include <cstddef>
+#include <bits/stl_iterator_base_types.h>
+#include <bits/stl_iterator.h>
+#include <bits/cpp_type_traits.h>
+#include <algorithm>
+
+#include <ext/string_util.h>
+
+namespace __gnu_cxx
+{
+ // N.B. According to 3.9/10 and 9/4, POD types can have user-defined
+ // constructors: in that case, cannot be member of an union (9.5/1).
+ // See, f.i., class gnu_char_type in the testsuite.
+ template<typename _CharT, typename _Alloc,
+ bool = std::__is_scalar<_CharT>::__value>
+ struct __sso_string_base
+ {
+ typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+
+ enum { _S_local_capacity = 15 };
+
+ union
+ {
+ _CharT _M_local_data[_S_local_capacity + 1];
+ size_type _M_allocated_capacity;
+ };
+ };
+
+ template<typename _CharT, typename _Alloc>
+ struct __sso_string_base<_CharT, _Alloc, false>
+ {
+ typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+
+ enum { _S_local_capacity = 15 };
+
+ _CharT _M_local_data[_S_local_capacity + 1];
+ size_type _M_allocated_capacity;
+ };
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ class __sso_string
+ : public __string_utility<_CharT, _Traits, _Alloc>,
+ private __sso_string_base<_CharT, _Alloc>
+ {
+ typedef __sso_string_base<_CharT, _Alloc> _Base;
+
+ public:
+ typedef _Traits traits_type;
+ typedef typename _Traits::char_type value_type;
+ typedef _Alloc allocator_type;
+
+ typedef typename __string_utility<_CharT, _Traits, _Alloc>::
+ _CharT_alloc_type _CharT_alloc_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+
+ // The maximum number of individual char_type elements of an
+ // individual string is determined by _S_max_size. This is the
+ // value that will be returned by max_size(). (Whereas npos
+ // is the maximum number of bytes the allocator can allocate.)
+ // If one was to divvy up the theoretical largest size string,
+ // with a terminating character and m _CharT elements, it'd
+ // look like this:
+ // npos = m * sizeof(_CharT) + sizeof(_CharT)
+ // Solving for m:
+ // m = npos / sizeof(CharT) - 1
+ // In addition, this implementation quarters this amount.
+ static const size_type _S_max_size;
+ static const _CharT _S_terminal;
+
+ private:
+ using _Base::_S_local_capacity;
+ using _Base::_M_local_data;
+ using _Base::_M_allocated_capacity;
+
+ // Create & Destroy
+ static _CharT*
+ _S_create(size_type&, size_type, const _Alloc&);
+
+ void
+ _M_destroy(const _Alloc&) throw();
+
+ // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
+ struct _Alloc_hider : _Alloc
+ {
+ _Alloc_hider(const _Alloc& __a)
+ : _Alloc(__a), _M_p(0) { }
+
+ _CharT* _M_p; // The actual data.
+ };
+
+ // Data Member (private):
+ _Alloc_hider _M_dataplus;
+ size_type _M_string_length;
+
+ _CharT*
+ _M_data(_CharT* __p)
+ { return (_M_dataplus._M_p = __p); }
+
+ void
+ _M_length(size_type __length)
+ { _M_string_length = __length; }
+
+ void
+ _M_capacity(size_type __capacity)
+ { _M_allocated_capacity = __capacity; }
+
+ bool
+ _M_is_local() const
+ { return _M_data() == _M_local_data; }
+
+ // _S_construct_aux is used to implement the 21.3.1 para 15 which
+ // requires special behaviour if _InIter is an integral type
+ template<class _InIterator>
+ void
+ _S_construct_aux(_InIterator __beg, _InIterator __end,
+ const _Alloc& __a, __false_type)
+ {
+ typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
+ _S_construct(__beg, __end, __a, _Tag());
+ }
+
+ template<class _InIterator>
+ void
+ _S_construct_aux(_InIterator __beg, _InIterator __end,
+ const _Alloc& __a, __true_type)
+ { _S_construct(static_cast<size_type>(__beg),
+ static_cast<value_type>(__end), __a); }
+
+ template<class _InIterator>
+ void
+ _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
+ {
+ typedef typename std::__is_integer<_InIterator>::__type _Integral;
+ _S_construct_aux(__beg, __end, __a, _Integral());
+ }
+
+ // For Input Iterators, used in istreambuf_iterators, etc.
+ template<class _InIterator>
+ void
+ _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
+ std::input_iterator_tag);
+
+ // For forward_iterators up to random_access_iterators, used for
+ // string::iterator, _CharT*, etc.
+ template<class _FwdIterator>
+ void
+ _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
+ std::forward_iterator_tag);
+
+ void
+ _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
+
+ public:
+ _CharT*
+ _M_data() const
+ { return _M_dataplus._M_p; }
+
+ size_type
+ _M_length() const
+ { return _M_string_length; }
+
+ size_type
+ _M_capacity() const
+ {
+ return _M_is_local() ? size_type(_S_local_capacity)
+ : _M_allocated_capacity;
+ }
+
+ bool
+ _M_is_shared() const
+ { return false; }
+
+ bool
+ _M_is_leaked() const
+ { return false; }
+
+ void
+ _M_set_sharable() { }
+
+ void
+ _M_set_leaked() { }
+
+ void
+ _M_set_length(size_type __n)
+ {
+ _M_length(__n);
+ // grrr. (per 21.3.4)
+ // You cannot leave those LWG people alone for a second.
+ traits_type::assign(_M_data()[__n], _S_terminal);
+ }
+
+ void
+ _M_leak() { }
+
+ __sso_string()
+ : _M_dataplus(_Alloc())
+ {
+ _M_data(_M_local_data);
+ _M_set_length(0);
+ }
+
+ __sso_string(const _Alloc& __a);
+
+ __sso_string(const __sso_string& __rcs);
+
+ __sso_string(size_type __n, _CharT __c, const _Alloc& __a);
+
+ template<typename _InputIterator>
+ __sso_string(_InputIterator __beg, _InputIterator __end,
+ const _Alloc& __a);
+
+ ~__sso_string()
+ { _M_destroy(_M_get_allocator()); }
+
+ allocator_type
+ _M_get_allocator() const
+ { return _M_dataplus; }
+
+ void
+ _M_swap(__sso_string& __rcs);
+
+ void
+ _M_assign(const __sso_string& __rcs);
+
+ void
+ _M_reserve(size_type __res);
+
+ void
+ _M_mutate(size_type __pos, size_type __len1, size_type __len2);
+ };
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _M_swap(__sso_string& __rcs)
+ {
+ const bool __local = _M_is_local();
+ const bool __rcs_local = __rcs._M_is_local();
+
+ if (__local && __rcs_local)
+ {
+ _CharT __tmp_data[_S_local_capacity + 1];
+ const size_type __tmp_length = __rcs._M_length();
+ _S_copy(__tmp_data, __rcs._M_data(), __rcs._M_length() + 1);
+ __rcs._M_length(_M_length());
+ _S_copy(__rcs._M_data(), _M_data(), _M_length() + 1);
+ _M_length(__tmp_length);
+ _S_copy(_M_data(), __tmp_data, __tmp_length + 1);
+ }
+ else if (__local && !__rcs_local)
+ {
+ const size_type __tmp_capacity = __rcs._M_allocated_capacity;
+ const size_type __tmp_length = __rcs._M_length();
+ _CharT* __tmp_ptr = __rcs._M_data();
+ __rcs._M_data(__rcs._M_local_data);
+ _S_copy(__rcs._M_data(), _M_data(), _M_length() + 1);
+ __rcs._M_length(_M_length());
+ _M_data(__tmp_ptr);
+ _M_length(__tmp_length);
+ _M_capacity(__tmp_capacity);
+ }
+ else if (!__local && __rcs_local)
+ {
+ const size_type __tmp_capacity = _M_allocated_capacity;
+ const size_type __tmp_length = _M_length();
+ _CharT* __tmp_ptr = _M_data();
+ _M_data(_M_local_data);
+ _S_copy(_M_data(), __rcs._M_data(), __rcs._M_length() + 1);
+ _M_length(__rcs._M_length());
+ __rcs._M_data(__tmp_ptr);
+ __rcs._M_length(__tmp_length);
+ __rcs._M_capacity(__tmp_capacity);
+ }
+ else
+ {
+ const size_type __tmp_capacity = _M_allocated_capacity;
+ const size_type __tmp_length = _M_length();
+ _CharT* __tmp_ptr = _M_data();
+ _M_data(__rcs._M_data());
+ _M_length(__rcs._M_length());
+ _M_capacity(__rcs._M_allocated_capacity);
+ __rcs._M_data(__tmp_ptr);
+ __rcs._M_length(__tmp_length);
+ __rcs._M_capacity(__tmp_capacity);
+ }
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ const typename __sso_string<_CharT, _Traits, _Alloc>::size_type
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _S_max_size = ((static_cast<size_type>(-1) / sizeof(_CharT)) - 1) / 4;
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ const _CharT
+ __sso_string<_CharT, _Traits, _Alloc>::_S_terminal = _CharT();
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ _CharT*
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _S_create(size_type& __capacity, size_type __old_capacity,
+ const _Alloc& __alloc)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 83. String::npos vs. string::max_size()
+ if (__capacity > _S_max_size)
+ std::__throw_length_error(__N("__sso_string::_S_create"));
+
+ // The below implements an exponential growth policy, necessary to
+ // meet amortized linear time requirements of the library: see
+ // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
+ // It's active for allocations requiring an amount of memory above
+ // system pagesize. This is consistent with the requirements of the
+ // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
+ if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
+ __capacity = 2 * __old_capacity;
+
+ // NB: Need an array of char_type[__capacity], plus a terminating
+ // null char_type() element.
+ return _CharT_alloc_type(__alloc).allocate(__capacity + 1);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _M_destroy(const _Alloc& __a) throw ()
+ {
+ if (!_M_is_local())
+ _CharT_alloc_type(__a).deallocate(_M_data(), _M_allocated_capacity + 1);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ __sso_string<_CharT, _Traits, _Alloc>::
+ __sso_string(const _Alloc& __a)
+ : _M_dataplus(__a)
+ { _S_construct(size_type(), _CharT(), __a); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ __sso_string<_CharT, _Traits, _Alloc>::
+ __sso_string(const __sso_string& __rcs)
+ : _M_dataplus(__rcs._M_get_allocator())
+ { _S_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length(),
+ __rcs._M_get_allocator()); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ __sso_string<_CharT, _Traits, _Alloc>::
+ __sso_string(size_type __n, _CharT __c, const _Alloc& __a)
+ : _M_dataplus(__a)
+ { _S_construct(__n, __c, __a); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ template<typename _InputIterator>
+ __sso_string<_CharT, _Traits, _Alloc>::
+ __sso_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
+ : _M_dataplus(__a)
+ { _S_construct(__beg, __end, __a); }
+
+ // NB: This is the special case for Input Iterators, used in
+ // istreambuf_iterators, etc.
+ // Input Iterators have a cost structure very different from
+ // pointers, calling for a different coding style.
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ template<typename _InIterator>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
+ std::input_iterator_tag)
+ {
+ // Avoid reallocation for common case.
+ size_type __len = 0;
+ _M_data(_M_local_data);
+ size_type __capacity = size_type(_S_local_capacity);
+
+ while (__beg != __end && __len < __capacity)
+ {
+ _M_data()[__len++] = *__beg;
+ ++__beg;
+ }
+
+ try
+ {
+ while (__beg != __end)
+ {
+ if (__len == __capacity)
+ {
+ // Allocate more space.
+ __capacity = __len + 1;
+ _CharT* __another = _S_create(__capacity, __len, __a);
+ _S_copy(__another, _M_data(), __len);
+ _M_destroy(__a);
+ _M_data(__another);
+ _M_capacity(__capacity);
+ }
+ _M_data()[__len++] = *__beg;
+ ++__beg;
+ }
+ }
+ catch(...)
+ {
+ _M_destroy(__a);
+ __throw_exception_again;
+ }
+
+ _M_set_length(__len);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ template <typename _InIterator>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
+ std::forward_iterator_tag)
+ {
+ // NB: Not required, but considered best practice.
+ if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0))
+ std::__throw_logic_error(__N("__sso_string::"
+ "_S_construct NULL not valid"));
+
+ size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
+
+ if (__dnew <= size_type(_S_local_capacity))
+ _M_data(_M_local_data);
+ else
+ {
+ _M_data(_S_create(__dnew, size_type(0), __a));
+ _M_capacity(__dnew);
+ }
+
+ // Check for out_of_range and length_error exceptions.
+ try
+ { _S_copy_chars(_M_data(), __beg, __end); }
+ catch(...)
+ {
+ _M_destroy(__a);
+ __throw_exception_again;
+ }
+
+ _M_set_length(__dnew);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
+ {
+ if (__n <= size_type(_S_local_capacity))
+ _M_data(_M_local_data);
+ else
+ {
+ _M_data(_S_create(__n, size_type(0), __a));
+ _M_capacity(__n);
+ }
+
+ if (__n)
+ _S_assign(_M_data(), __n, __c);
+
+ _M_set_length(__n);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _M_assign(const __sso_string& __rcs)
+ {
+ if (this != &__rcs)
+ {
+ const allocator_type __a = _M_get_allocator();
+ size_type __size = __rcs._M_length();
+
+ _CharT* __tmp;
+ if (__size <= size_type(_S_local_capacity))
+ __tmp = _M_local_data;
+ else
+ __tmp = _S_create(__size, size_type(0), __a);
+
+ _M_destroy(__a);
+ _M_data(__tmp);
+
+ if (__size)
+ _S_copy(_M_data(), __rcs._M_data(), __size);
+
+ if (!_M_is_local())
+ _M_capacity(__size);
+
+ _M_set_length(__size);
+ }
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _M_reserve(size_type __res)
+ {
+ const size_type __capacity = _M_capacity();
+ const allocator_type __a = _M_get_allocator();
+
+ if (__res > __capacity
+ || __res > size_type(_S_local_capacity))
+ {
+ _CharT* __tmp = _S_create(__res, __capacity, __a);
+ if (_M_length())
+ _S_copy(__tmp, _M_data(), _M_length());
+ _M_destroy(__a);
+ _M_data(__tmp);
+ _M_capacity(__res);
+ }
+ else if (!_M_is_local())
+ {
+ const size_type __tmp_capacity = _M_allocated_capacity;
+ if (_M_length())
+ _S_copy(_M_local_data, _M_data(), _M_length());
+ // XXX
+ _CharT_alloc_type(__a).deallocate(_M_data(), __tmp_capacity + 1);
+ _M_data(_M_local_data);
+ }
+
+ _M_set_length(_M_length());
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __sso_string<_CharT, _Traits, _Alloc>::
+ _M_mutate(size_type __pos, size_type __len1, size_type __len2)
+ {
+ const size_type __old_size = _M_length();
+ const size_type __new_size = __old_size + __len2 - __len1;
+ const size_type __how_much = __old_size - __pos - __len1;
+
+ if (__new_size > _M_capacity())
+ {
+ // Must reallocate.
+ const allocator_type __a = _M_get_allocator();
+ size_type __new_capacity = __new_size;
+ _CharT* __r = _S_create(__new_capacity, _M_capacity(), __a);
+
+ if (__pos)
+ _S_copy(__r, _M_data(), __pos);
+ if (__how_much)
+ _S_copy(__r + __pos + __len2,
+ _M_data() + __pos + __len1, __how_much);
+
+ _M_destroy(__a);
+ _M_data(__r);
+ _M_capacity(__new_capacity);
+ }
+ else if (__how_much && __len1 != __len2)
+ {
+ // Work in-place.
+ _S_move(_M_data() + __pos + __len2,
+ _M_data() + __pos + __len1, __how_much);
+ }
+
+ _M_set_length(__new_size);
+ }
+} // namespace __gnu_cxx
+
+#endif /* _SSO_STRING_H */
diff -urN libstdc++-v3-orig/src/Makefile.am libstdc++-v3/src/Makefile.am
--- libstdc++-v3-orig/src/Makefile.am 2005-02-18 18:58:59.000000000 +0100
+++ libstdc++-v3/src/Makefile.am 2005-06-09 14:18:19.000000000 +0200
@@ -135,10 +135,12 @@
streambuf-inst.cc \
streambuf.cc \
rc_string-inst.cc \
+ sso_string-inst.cc \
string-inst.cc \
valarray-inst.cc \
wlocale-inst.cc \
wrc_string-inst.cc \
+ wsso_string-inst.cc \
wstring-inst.cc \
${host_sources} \
${host_sources_extra}
diff -urN libstdc++-v3-orig/src/sso_string-inst.cc libstdc++-v3/src/sso_string-inst.cc
--- libstdc++-v3-orig/src/sso_string-inst.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/src/sso_string-inst.cc 2005-06-10 16:37:18.000000000 +0200
@@ -0,0 +1,75 @@
+// Components for manipulating sequences of characters -*- C++ -*-
+
+// Copyright (C) 2005 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Librarbooly. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+//
+// ISO C++ 14882:
+//
+
+#include <bits/c++config.h>
+#include <ext/sso_string.h>
+#include <memory> // For allocator.
+#include <bits/char_traits.h>
+
+// Instantiation configuration.
+#ifndef C
+# define C char
+#endif
+
+namespace __gnu_cxx
+{
+ using std::allocator;
+
+ template class __sso_string<C, std::char_traits<C>, allocator<C> >;
+
+ typedef __sso_string<C, std::char_traits<C>, allocator<C> > RS;
+
+ template
+ RS::__sso_string(C*, C*, const allocator<C>&);
+
+ template
+ RS::__sso_string(const C*, const C*, const allocator<C>&);
+
+ template
+ RS::__sso_string(RS::iterator, RS::iterator, const allocator<C>&);
+
+ template
+ void
+ RS::_S_construct(RS::iterator, RS::iterator,
+ const allocator<C>&, std::forward_iterator_tag);
+
+ template
+ void
+ RS::_S_construct(C*, C*, const allocator<C>&,
+ std::forward_iterator_tag);
+
+ template
+ void
+ RS::_S_construct(const C*, const C*, const allocator<C>&,
+ std::forward_iterator_tag);
+} // namespace __gnu_cxx
diff -urN libstdc++-v3-orig/src/wsso_string-inst.cc libstdc++-v3/src/wsso_string-inst.cc
--- libstdc++-v3-orig/src/wsso_string-inst.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/src/wsso_string-inst.cc 2005-06-09 14:17:44.000000000 +0200
@@ -0,0 +1,39 @@
+// Components for manipulating sequences of characters -*- C++ -*-
+
+// Copyright (C) 2005 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Librarbooly. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+//
+// ISO C++ 14882:
+//
+
+#include <bits/c++config.h>
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+#define C wchar_t
+#include "sso_string-inst.cc"
+#endif