OSDN Git Service

2009-02-03 Paolo Carlini <paolo.carlini@oracle.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / ext / sso_string_base.h
index c37bd88..a50f48f 100644 (file)
@@ -1,6 +1,6 @@
 // Short-string-optimized versatile string base -*- C++ -*-
 
-// Copyright (C) 2005 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007, 2008, 2009 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
@@ -36,8 +36,8 @@
 #ifndef _SSO_STRING_BASE_H
 #define _SSO_STRING_BASE_H 1
 
-namespace __gnu_cxx
-{
+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+
   template<typename _CharT, typename _Traits, typename _Alloc>
     class __sso_string_base
     : protected __vstring_utility<_CharT, _Traits, _Alloc>
@@ -45,51 +45,28 @@ namespace __gnu_cxx
     public:
       typedef _Traits                                      traits_type;
       typedef typename _Traits::char_type                  value_type;
-      typedef _Alloc                                       allocator_type;
 
-      typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
-        _CharT_alloc_type                                   _CharT_alloc_type;
+      typedef __vstring_utility<_CharT, _Traits, _Alloc>    _Util_Base;
+      typedef typename _Util_Base::_CharT_alloc_type        _CharT_alloc_type;
       typedef typename _CharT_alloc_type::size_type        size_type;
       
     private:
-      // 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.
-      enum { _S_max_size = (((static_cast<size_type>(-1)
-                             / sizeof(_CharT)) - 1) / 4) };
-
-      // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
-      struct _Alloc_hider : _Alloc
-      {
-       _Alloc_hider(const _Alloc& __a, _CharT* __ptr)
-       : _Alloc(__a), _M_p(__ptr) { }
-
-       _CharT* _M_p; // The actual data.
-      };
-
-      // Data Members (private):
-      _Alloc_hider             _M_dataplus;
-      size_type                 _M_string_length;
+      // Data Members:
+      typename _Util_Base::template _Alloc_hider<_CharT_alloc_type>
+                                                            _M_dataplus;
+      size_type                                             _M_string_length;
 
       enum { _S_local_capacity = 15 };
       
       union
       {
-       _CharT                  _M_local_data[_S_local_capacity + 1];
-       size_type               _M_allocated_capacity;
+       _CharT           _M_local_data[_S_local_capacity + 1];
+       size_type        _M_allocated_capacity;
       };
 
-      _CharT*
+      void
       _M_data(_CharT* __p)
-      { return (_M_dataplus._M_p = __p); }
+      { _M_dataplus._M_p = __p; }
 
       void
       _M_length(size_type __length)
@@ -108,32 +85,35 @@ namespace __gnu_cxx
       _M_create(size_type&, size_type);
       
       void
-      _M_dispose() throw()
+      _M_dispose()
       {
        if (!_M_is_local())
-         _M_destroy(_M_allocated_capacity + 1);
+         _M_destroy(_M_allocated_capacity);
       }
 
       void
-      _M_destroy(size_type) throw();
+      _M_destroy(size_type __size) throw()
+      { _M_get_allocator().deallocate(_M_data(), __size + 1); }
 
       // _M_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>
+      // requires special behaviour if _InIterator is an integral type
+      template<typename _InIterator>
         void
-        _M_construct_aux(_InIterator __beg, _InIterator __end, __false_type)
+        _M_construct_aux(_InIterator __beg, _InIterator __end, 
+                        std::__false_type)
        {
           typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
           _M_construct(__beg, __end, _Tag());
        }
 
-      template<class _InIterator>
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 438. Ambiguity in the "do the right thing" clause
+      template<typename _Integer>
         void
-        _M_construct_aux(_InIterator __beg, _InIterator __end, __true_type)
-       { _M_construct(static_cast<size_type>(__beg),
-                      static_cast<value_type>(__end)); }
+        _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
+       { _M_construct(static_cast<size_type>(__beg), __end); }
 
-      template<class _InIterator>
+      template<typename _InIterator>
         void
         _M_construct(_InIterator __beg, _InIterator __end)
        {
@@ -142,14 +122,14 @@ namespace __gnu_cxx
         }
 
       // For Input Iterators, used in istreambuf_iterators, etc.
-      template<class _InIterator>
+      template<typename _InIterator>
         void
         _M_construct(_InIterator __beg, _InIterator __end,
                     std::input_iterator_tag);
       
       // For forward_iterators up to random_access_iterators, used for
       // string::iterator, _CharT*, etc.
-      template<class _FwdIterator>
+      template<typename _FwdIterator>
         void
         _M_construct(_FwdIterator __beg, _FwdIterator __end,
                     std::forward_iterator_tag);
@@ -160,7 +140,7 @@ namespace __gnu_cxx
     public:
       size_type
       _M_max_size() const
-      { return size_type(_S_max_size); }
+      { return (_M_get_allocator().max_size() - 1) / 2; }
 
       _CharT*
       _M_data() const
@@ -181,36 +161,31 @@ namespace __gnu_cxx
       _M_is_shared() const
       { return false; }
 
-      bool
-      _M_is_leaked() const
-      { return false; }
-
       void
-      _M_set_sharable() { }
+      _M_set_leaked() { }
 
       void
-      _M_set_leaked() { }
+      _M_leak() { }
 
       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], _CharT());
       }
 
-      void
-      _M_leak() { }
-
       __sso_string_base()
-      : _M_dataplus(_Alloc(), _M_local_data)
+      : _M_dataplus(_M_local_data)
       { _M_set_length(0); }
 
       __sso_string_base(const _Alloc& __a);
 
       __sso_string_base(const __sso_string_base& __rcs);
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      __sso_string_base(__sso_string_base&& __rcs);
+#endif
+
       __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a);
 
       template<typename _InputIterator>
@@ -220,7 +195,11 @@ namespace __gnu_cxx
       ~__sso_string_base()
       { _M_dispose(); }
 
-      allocator_type
+      _CharT_alloc_type&
+      _M_get_allocator()
+      { return _M_dataplus; }
+
+      const _CharT_alloc_type&
       _M_get_allocator() const
       { return _M_dataplus; }
 
@@ -234,20 +213,31 @@ namespace __gnu_cxx
       _M_reserve(size_type __res);
 
       void
-      _M_mutate(size_type __pos, size_type __len1, size_type __len2);
-    };
+      _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+               size_type __len2);
 
-  template<typename _CharT, typename _Traits, typename _Alloc>
-    void
-    __sso_string_base<_CharT, _Traits, _Alloc>::
-    _M_destroy(size_type __size) throw()
-    { _CharT_alloc_type(_M_get_allocator()).deallocate(_M_data(), __size); }
+      void
+      _M_erase(size_type __pos, size_type __n);
+
+      void
+      _M_clear()
+      { _M_set_length(0); }
+
+      bool
+      _M_compare(const __sso_string_base&) const
+      { return false; }
+    };
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     __sso_string_base<_CharT, _Traits, _Alloc>::
     _M_swap(__sso_string_base& __rcs)
     {
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 431. Swapping containers with unequal allocators.
+      std::__alloc_swap<_CharT_alloc_type>::_S_do_it(_M_get_allocator(),
+                                                    __rcs._M_get_allocator());
+
       if (_M_is_local())
        if (__rcs._M_is_local())
          {
@@ -319,21 +309,23 @@ namespace __gnu_cxx
     {
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 83.  String::npos vs. string::max_size()
-      if (__capacity > size_type(_S_max_size))
+      if (__capacity > _M_max_size())
        std::__throw_length_error(__N("__sso_string_base::_M_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;
+       {
+         __capacity = 2 * __old_capacity;
+         // Never allocate a string bigger than max_size.
+         if (__capacity > _M_max_size())
+           __capacity = _M_max_size();
+       }
 
       // NB: Need an array of char_type[__capacity], plus a terminating
       // null char_type() element.
-      return _CharT_alloc_type(_M_get_allocator()).allocate(__capacity + 1);
+      return _M_get_allocator().allocate(__capacity + 1);
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -348,6 +340,30 @@ namespace __gnu_cxx
     : _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
     { _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length()); }
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    __sso_string_base<_CharT, _Traits, _Alloc>::
+    __sso_string_base(__sso_string_base&& __rcs)
+    : _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
+    {
+      if (__rcs._M_is_local())
+       {
+         if (__rcs._M_length())
+           traits_type::copy(_M_local_data, __rcs._M_local_data,
+                             _S_local_capacity + 1);
+       }
+      else
+       {
+         _M_data(__rcs._M_data());
+         _M_capacity(__rcs._M_allocated_capacity);
+       }
+
+      _M_length(__rcs._M_length());
+      __rcs._M_length(0);
+      __rcs._M_data(__rcs._M_local_data);
+    }
+#endif
+
   template<typename _CharT, typename _Traits, typename _Alloc>
     __sso_string_base<_CharT, _Traits, _Alloc>::
     __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a)
@@ -373,7 +389,6 @@ namespace __gnu_cxx
       _M_construct(_InIterator __beg, _InIterator __end,
                   std::input_iterator_tag)
       {
-       // Avoid reallocation for common case.
        size_type __len = 0;
        size_type __capacity = size_type(_S_local_capacity);
 
@@ -383,7 +398,7 @@ namespace __gnu_cxx
            ++__beg;
          }
        
-       try
+       __try
          {
            while (__beg != __end)
              {
@@ -401,7 +416,7 @@ namespace __gnu_cxx
                ++__beg;
              }
          }
-       catch(...)
+       __catch(...)
          {
            _M_dispose();
            __throw_exception_again;
@@ -411,14 +426,14 @@ namespace __gnu_cxx
       }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
-    template <typename _InIterator>
+    template<typename _InIterator>
       void
       __sso_string_base<_CharT, _Traits, _Alloc>::
       _M_construct(_InIterator __beg, _InIterator __end,
                   std::forward_iterator_tag)
       {
        // NB: Not required, but considered best practice.
-       if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
+       if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0))
          std::__throw_logic_error(__N("__sso_string_base::"
                                       "_M_construct NULL not valid"));
 
@@ -431,9 +446,9 @@ namespace __gnu_cxx
          }
 
        // Check for out_of_range and length_error exceptions.
-       try
+       __try
          { _S_copy_chars(_M_data(), __beg, __end); }
-       catch(...)
+       __catch(...)
          {
            _M_dispose();
            __throw_exception_again;
@@ -466,22 +481,22 @@ namespace __gnu_cxx
     {
       if (this != &__rcs)
        {
-         size_type __size = __rcs._M_length();
+         const size_type __rsize = __rcs._M_length();
+         const size_type __capacity = _M_capacity();
 
-         _CharT* __tmp = _M_local_data;
-         if (__size > size_type(_S_local_capacity))
-           __tmp = _M_create(__size, size_type(0));
-
-         _M_dispose();
-         _M_data(__tmp);
-
-         if (__size)
-           _S_copy(_M_data(), __rcs._M_data(), __size);
+         if (__rsize > __capacity)
+           {
+             size_type __new_capacity = __rsize;
+             _CharT* __tmp = _M_create(__new_capacity, __capacity);
+             _M_dispose();
+             _M_data(__tmp);
+             _M_capacity(__new_capacity);
+           }
 
-         if (!_M_is_local())
-           _M_capacity(__size);
+         if (__rsize)
+           _S_copy(_M_data(), __rcs._M_data(), __rsize);
 
-         _M_set_length(__size);
+         _M_set_length(__rsize);
        }
     }
 
@@ -490,70 +505,69 @@ namespace __gnu_cxx
     __sso_string_base<_CharT, _Traits, _Alloc>::
     _M_reserve(size_type __res)
     {
+      // Make sure we don't shrink below the current size.
+      if (__res < _M_length())
+       __res = _M_length();
+
       const size_type __capacity = _M_capacity();
       if (__res != __capacity)
        {
-         // Make sure we don't shrink below the current size.
-         if (__res < _M_length())
-           __res = _M_length();
-
          if (__res > __capacity
              || __res > size_type(_S_local_capacity))
            {
              _CharT* __tmp = _M_create(__res, __capacity);
-             if (_M_length())
-               _S_copy(__tmp, _M_data(), _M_length());
+             _S_copy(__tmp, _M_data(), _M_length() + 1);
              _M_dispose();
              _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());
-             _M_destroy(__tmp_capacity + 1);
+             _S_copy(_M_local_data, _M_data(), _M_length() + 1);
+             _M_destroy(__capacity);
              _M_data(_M_local_data);
-           }     
-         
-         _M_set_length(_M_length());
+           }
        }
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     __sso_string_base<_CharT, _Traits, _Alloc>::
-    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
+    _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+             const 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;
+      const size_type __how_much = _M_length() - __pos - __len1;
       
-      if (__new_size > _M_capacity())
-       {
-         // Must reallocate.
-         size_type __new_capacity = __new_size;
-         _CharT* __r = _M_create(__new_capacity, _M_capacity());
-
-         if (__pos)
-           _S_copy(__r, _M_data(), __pos);
-         if (__how_much)
-           _S_copy(__r + __pos + __len2,
-                   _M_data() + __pos + __len1, __how_much);
-
-         _M_dispose();
-         _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);
-       }
+      size_type __new_capacity = _M_length() + __len2 - __len1;
+      _CharT* __r = _M_create(__new_capacity, _M_capacity());
+
+      if (__pos)
+       _S_copy(__r, _M_data(), __pos);
+      if (__s && __len2)
+       _S_copy(__r + __pos, __s, __len2);
+      if (__how_much)
+       _S_copy(__r + __pos + __len2,
+               _M_data() + __pos + __len1, __how_much);
+      
+      _M_dispose();
+      _M_data(__r);
+      _M_capacity(__new_capacity);
+    }
 
-      _M_set_length(__new_size);
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    void
+    __sso_string_base<_CharT, _Traits, _Alloc>::
+    _M_erase(size_type __pos, size_type __n)
+    {
+      const size_type __how_much = _M_length() - __pos - __n;
+
+      if (__how_much && __n)
+       _S_move(_M_data() + __pos, _M_data() + __pos + __n,
+               __how_much);
+
+      _M_set_length(_M_length() - __n);
     }
-} // namespace __gnu_cxx
+
+_GLIBCXX_END_NAMESPACE
 
 #endif /* _SSO_STRING_BASE_H */