Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53207 - in trunk: boost/wave/util libs/wave
From: hartmut.kaiser_at_[hidden]
Date: 2009-05-23 11:36:09


Author: hkaiser
Date: 2009-05-23 11:36:08 EDT (Sat, 23 May 2009)
New Revision: 53207
URL: http://svn.boost.org/trac/boost/changeset/53207

Log:
Wave: Incorporated the changes from latest version of the flex_string class (fixes #2946)
Text files modified:
   trunk/boost/wave/util/flex_string.hpp | 246 ++++++++++++++++++++++++++++++---------
   trunk/libs/wave/ChangeLog | 2
   2 files changed, 191 insertions(+), 57 deletions(-)

Modified: trunk/boost/wave/util/flex_string.hpp
==============================================================================
--- trunk/boost/wave/util/flex_string.hpp (original)
+++ trunk/boost/wave/util/flex_string.hpp 2009-05-23 11:36:08 EDT (Sat, 23 May 2009)
@@ -26,6 +26,10 @@
 // #HK070307:
 // - Once again incorporated the changes from Andrei's latest version of
 // this class
+//
+// #HK090523:
+// - Incorporated the changes from latest version of flex_string as
+// maintained in Loki
 
 #ifndef FLEX_STRING_INC_
 #define FLEX_STRING_INC_
@@ -1442,9 +1446,10 @@
         }
     private:
         const flex_string& s_;
+ Invariant& operator=(const Invariant&);
     };
 #endif
-
+
 public:
     // types
     typedef T traits_type;
@@ -1647,7 +1652,7 @@
         Invariant checker(*this);
 #endif
         static std::less_equal<const value_type*> le;
- if (le(&*begin(), s) && le(s, &*end())) // aliasing
+ if (IsAliasedRange(s, s + n))
         {
             const size_type offset = s - &*begin();
             Storage::reserve(size() + n);
@@ -1760,6 +1765,51 @@
     }
     
 private:
+ // Care must be taken when dereferencing some iterator types.
+ //
+ // Users can implement this function in their namespace if their storage
+ // uses a special iterator type, the function will be found through ADL.
+ template<class Iterator>
+ const typename std::iterator_traits<Iterator>::value_type*
+ DereferenceValidIterator(Iterator it) const
+ {
+ return &*it;
+ }
+
+ // Care must be taken when dereferencing a reverse iterators, hence this
+ // special case. This isn't in the std namespace so as not to pollute it or
+ // create name clashes.
+ template<typename Iterator>
+ const typename std::iterator_traits<Iterator>::value_type*
+ DereferenceValidIterator(std::reverse_iterator<Iterator> it) const
+ {
+ return &*--it;
+ }
+
+ // Determine if the range aliases the current string.
+ //
+ // This method cannot be const because calling begin/end on copy-on-write
+ // implementations must have side effects.
+ // A const version wouldn't make the string unique through this call.
+ template<class Iterator>
+ bool IsAliasedRange(Iterator beginIterator, Iterator endIterator)
+ {
+ if(!empty() && beginIterator != endIterator)
+ {
+ typedef const typename std::iterator_traits<Iterator>::value_type *
+ pointer;
+
+ pointer myBegin(&*begin());
+ pointer myEnd(&*begin() + size());
+ pointer rangeBegin(DereferenceValidIterator(beginIterator));
+
+ const std::less_equal<pointer> less_equal = std::less_equal<pointer>();
+ if(less_equal(myBegin, rangeBegin) && less_equal(rangeBegin, myEnd))
+ return true;
+ }
+ return false;
+ }
+
     template <int i> class Selector {};
 
     flex_string& InsertImplDiscr(iterator p,
@@ -1768,24 +1818,32 @@
 #ifndef NDEBUG
         Invariant checker(*this);
 #endif
- assert(p >= begin() && p <= end());
- if (capacity() - size() < n)
+ assert(begin() <= p && p <= end());
+ const size_type insertOffset(p - begin());
+ const size_type originalSize(size());
+ if(n < originalSize - insertOffset)
+ {
+ // The new characters fit within the original string.
+ // The characters that are pushed back need to be moved because
+ // they're aliased.
+ // The appended characters will all be overwritten by the move.
+ append(n, value_type(0));
+ value_type* begin(&*begin());
+ flex_string_details::pod_move(begin + insertOffset,
+ begin + originalSize, begin + insertOffset + n);
+ std::fill(begin + insertOffset, begin + insertOffset + n, c);
+ }
+ else
         {
- const size_type sz = p - begin();
- reserve(size() + n);
- p = begin() + sz;
- }
- const iterator oldEnd = end();
- if (p + n < oldEnd)
- {
- append(oldEnd - n, oldEnd);
- flex_string_details::pod_move(&*p, &*oldEnd - n, &*p + n);
- std::fill(p, p + n, c);
- }
- else {
- append(n - (end() - p), c);
- append(p, oldEnd);
- std::fill(p, oldEnd, c);
+ // The new characters exceed the original string.
+ // The characters that are pushed back can simply be copied since
+ // they aren't aliased.
+ // The appended characters will partly be overwritten by the copy.
+ append(n, c);
+ value_type* begin(&*begin());
+ flex_string_details::pod_copy(begin + insertOffset,
+ begin + originalSize, begin + insertOffset + n);
+ std::fill(begin + insertOffset, begin + originalSize, c);
         }
         return *this;
     }
@@ -1803,12 +1861,29 @@
     void InsertImpl(iterator i,
         FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
     {
+ if(s1 == s2)
+ {
+ // Insert an empty range.
+ return;
+ }
+
+ if(IsAliasedRange(s1, s2))
+ {
+ // The source range is contained in the current string, copy it
+ // and recurse.
+ const flex_string temporary(s1, s2);
+ InsertImpl(i, temporary.begin(), temporary.end(),
+ typename std::iterator_traits<FwdIterator>::iterator_category());
+ return;
+ }
+
 #ifndef NDEBUG
         Invariant checker(*this);
 #endif
         const size_type pos = i - begin();
         const typename std::iterator_traits<FwdIterator>::difference_type n2 =
             std::distance(s1, s2);
+
         assert(n2 >= 0);
         using namespace flex_string_details;
         assert(pos <= size());
@@ -1817,10 +1892,8 @@
             capacity() - size();
         if (maxn2 < n2)
         {
- // realloc the string
- static const std::less_equal<const value_type*> le =
- std::less_equal<const value_type*>();
- assert(!(le(&*begin(), &*s1) && le(&*s1, &*end())));
+ // Reallocate the string.
+ assert(!IsAliasedRange(s1, s2));
             reserve(size() + n2);
             i = begin() + pos;
         }
@@ -1845,16 +1918,17 @@
     }
 
     template <class InputIterator>
- void InsertImpl(iterator i1, iterator i2,
- InputIterator b, InputIterator e, std::input_iterator_tag)
- {
- flex_string temp(begin(), i1);
- for (; b != e; ++b)
+ void InsertImpl(iterator insertPosition,
+ InputIterator inputBegin, InputIterator inputEnd,
+ std::input_iterator_tag)
+ {
+ flex_string temporary(begin(), insertPosition);
+ for (; inputBegin != inputEnd; ++inputBegin)
         {
- temp.push_back(*b);
+ temporary.push_back(*inputBegin);
         }
- temp.append(i2, end());
- swap(temp);
+ temporary.append(insertPosition, end());
+ swap(temporary);
     }
 
 public:
@@ -1983,29 +2057,25 @@
         std::distance(s1, s2);
         assert(n2 >= 0);
 
- // Handle aliased replace
- static const std::less_equal<const value_type*> le =
- std::less_equal<const value_type*>();
- const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
- if (aliased /* && capacity() < size() - n1 + n2 */)
- {
- // Aliased replace, copy to new string
- flex_string temp;
- temp.reserve(size() - n1 + n2);
- temp.append(begin(), i1).append(s1, s2).append(i2, end());
- swap(temp);
+ if (IsAliasedRange(s1, s2))
+ {
+ // Aliased replace, copy to new string.
+ flex_string temporary;
+ temporary.reserve(size() - n1 + n2);
+ temporary.append(begin(), i1).append(s1, s2).append(i2, end());
+ swap(temporary);
             return;
         }
 
         if (n1 > n2)
         {
- // shrinks
+ // Shrinks
             std::copy(s1, s2, i1);
             erase(i1 + n2, i2);
         }
         else
         {
- // grows
+ // Grows
             flex_string_details::copy_n(s1, n1, i1);
             std::advance(s1, n1);
             insert(i2, s1, s2);
@@ -2063,10 +2133,13 @@
     
     size_type find(const flex_string& str, size_type pos = 0) const
     { return find(str.data(), pos, str.length()); }
-
+
     size_type find (const value_type* s, size_type pos, size_type n) const
     {
- for (; pos <= size(); ++pos)
+ const size_type size(size());
+ if (n + pos > size)
+ return npos;
+ for (; pos < size; ++pos)
         {
             if (traits_type::compare(&*begin() + pos, s, n) == 0)
             {
@@ -2255,12 +2328,8 @@
     {
         Enforce(pos1 <= size(), (std::out_of_range*)0, "");
         Procust(n1, size() - pos1);
- const int r = traits_type::compare(data()+pos1, s, Min(n1, n2));
- return
- r != 0 ? r :
- n1 > n2 ? 1 :
- n1 < n2 ? -1 :
- 0;
+ const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
+ return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
     }
 
     std::ptrdiff_t compare(size_type pos1, size_type n1,
@@ -2273,7 +2342,11 @@
 
     std::ptrdiff_t compare(const value_type* s) const
     {
- return traits_type::compare(data(), s, traits_type::length(s));
+ // Could forward to compare(0, size(), s, traits_type::length(s))
+ // but that does two extra checks
+ const size_type n1(size()), n2(traits_type::length(s));
+ const int r = traits_type::compare(data(), s, Min(n1, n2));
+ return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
     }
 };
 
@@ -2427,8 +2500,12 @@
     const flex_string<E, T, A, S>& rhs)
 { return !(lhs < rhs); }
 
-// subclause 21.3.7.8:
-//void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs); // to do
+template <typename E, class T, class A, class S>
+void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs)
+{
+ // subclause 21.3.7.8:
+ lhs.swap(rhs);
+}
 
 template <typename E, class T, class A, class S>
 inline std::basic_istream<typename flex_string<E, T, A, S>::value_type,
@@ -2447,6 +2524,23 @@
     const flex_string<E, T, A, S>& str)
 { return os << str.c_str(); }
 
+
+// The getline below implementations are from the SGI STL (http://www.sgi.com/tech/stl/)
+// and come with the following copyright:
+//
+// Permission to use, copy, modify, distribute and sell this software and its
+// documentation for any purpose is hereby granted without fee, provided that
+// the below copyright notice appears in all copies and that both the copyright
+// notice and this permission notice appear in supporting documentation. Silicon
+// Graphics makes no representations about the suitability of this software for
+// any purpose. It is provided "as is" without express or implied warranty.
+//
+// Copyright © 1997-1999
+// Silicon Graphics Computer Systems, Inc.
+//
+// Copyright © 1994
+// Hewlett-Packard Company
+
 template <typename E, class T, class A, class S>
 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
     typename flex_string<E, T, A, S>::traits_type>&
@@ -2454,7 +2548,42 @@
     std::basic_istream<typename flex_string<E, T, A, S>::value_type,
         typename flex_string<E, T, A, S>::traits_type>& is,
     flex_string<E, T, A, S>& str,
- typename flex_string<E, T, A, S>::value_type delim);
+ typename flex_string<E, T, A, S>::value_type delim)
+{
+ size_t nread = 0;
+ typename basic_istream<typename flex_string<E, T, A, S>::value_type,
+ typename flex_string<E, T, A, S>::traits_type>::sentry sentry(is, true);
+
+ if (sentry) {
+ basic_streambuf<typename flex_string<E, T, A, S>::value_type,
+ typename flex_string<E, T, A, S>::traits_type>* buf = is.rdbuf();
+ str.clear();
+
+ while (nread < str.max_size()) {
+ int c1 = buf->sbumpc();
+ if (flex_string<E, T, A, S>::traits_type::eq_int_type(c1,
+ flex_string<E, T, A, S>::traits_type::eof()))
+ {
+ is.setstate(ios_base::eofbit);
+ break;
+ }
+ else {
+ ++nread;
+ typename flex_string<E, T, A, S>::value_type c =
+ flex_string<E, T, A, S>::traits_type::to_char_type(c1);
+
+ if (!flex_string<E, T, A, S>::traits_type::eq(c, delim))
+ str.push_back(c);
+ else
+ break; // Character is extracted but not appended.
+ }
+ }
+ }
+ if (nread == 0 || nread >= str.max_size())
+ is.setstate(ios_base::failbit);
+
+ return is;
+}
 
 template <typename E, class T, class A, class S>
 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
@@ -2462,7 +2591,10 @@
 getline(
     std::basic_istream<typename flex_string<E, T, A, S>::value_type,
         typename flex_string<E, T, A, S>::traits_type>& is,
- flex_string<E, T, A, S>& str);
+ flex_string<E, T, A, S>& str)
+{
+ return getline(is, str, is.widen('\n'));
+}
 
 template <typename E1, class T, class A, class S>
 const typename flex_string<E1, T, A, S>::size_type

Modified: trunk/libs/wave/ChangeLog
==============================================================================
--- trunk/libs/wave/ChangeLog (original)
+++ trunk/libs/wave/ChangeLog 2009-05-23 11:36:08 EDT (Sat, 23 May 2009)
@@ -32,6 +32,8 @@
   introduced in V2.0 broke this part.
 - Fixed a long standing race condition inhibiting to use Wave in multi threaded
   environments.
+- Removed old code related to pre Boost V1.31 (V1 of iterator library)
+- Incorporated the changes from latest version of the flex_string class.
 
 Boost V1.39.0
 - V2.0.1


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk