This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]