$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r82027 - in sandbox-branches/geometry/index: boost/geometry/extensions/index test
From: adam.wulkiewicz_at_[hidden]
Date: 2012-12-16 13:31:04
Author: awulkiew
Date: 2012-12-16 13:31:03 EST (Sun, 16 Dec 2012)
New Revision: 82027
URL: http://svn.boost.org/trac/boost/changeset/82027
Log:
Added statid_vector::insert(pos, first, last) for non random access iterators.
Added uninitialized_copy_checked() helper method.
Added tests.
Text files modified: 
   sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp |   107 +++++++++++++++++++++++++++++---------- 
   sandbox-branches/geometry/index/test/static_vector.cpp                            |    17 ++++++                                  
   2 files changed, 95 insertions(+), 29 deletions(-)
Modified: sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp
==============================================================================
--- sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp	(original)
+++ sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp	2012-12-16 13:31:03 EST (Sun, 16 Dec 2012)
@@ -408,35 +408,64 @@
         }
         else
         {
-            difference_type to_move = std::distance(position, this->end());
-
-            // TODO - should following lines check for exception and revert to the old size?
-
-            if ( count < to_move )
-            {
-                this->uninitialized_copy(this->end() - count, this->end(), this->end());        // may throw
-                m_size += count; // update end
-                this->move_backward(position, position + to_move - count, this->end() - count); // may throw
-                this->copy(first, last, position);                                              // may throw
-            }
-            else
-            {
-                this->uninitialized_copy(first + to_move, last, this->end());                   // may throw
-                m_size += count - to_move; // update end
-                this->uninitialized_copy(position, position + to_move, position + count);       // may throw
-                m_size += to_move; // update end
-                this->copy(first, first + to_move, position) ;                                  // may throw
-            }
+            this->insert_in_the_middle(position, first, last, count);                            // may throw
         }
     }
 
     template <typename Iterator, typename Traversal>
     void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)
     {
-        BOOST_MPL_ASSERT_MSG(
-            (false),
-            THIS_ITERATOR_IS_NOT_YET_SUPPORTED,
-            (static_vector));
+        // TODO change name of this macro
+        BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(difference_type dist = std::distance(this->begin(), position));
+        // TODO dist < distance(begin(), end())
+        BOOST_ASSERT_MSG(0 <= dist && (sizeof(dist)<=sizeof(m_size)?((size_type)dist<=m_size):(dist<=(difference_type)m_size)), "invalid iterator");
+
+        if ( position == this->end() )
+        {
+            std::pair<bool, size_type> copy_data =
+                this->uninitialized_copy_checked(first, last, position, std::distance(position, this->begin() + Capacity)); // may throw
+            
+            BOOST_ASSERT_MSG(copy_data.first, "size can't exceed the capacity");
+            // eventually throw bad_alloc
+
+            m_size += copy_data.second;
+        }
+        else
+        {
+            difference_type count = std::distance(first, last);
+            
+            BOOST_ASSERT_MSG(m_size + count <= Capacity, "size can't exceed the capacity");
+            //if ( Capacity < m_size + count ) throw std::bad_alloc();
+
+            this->insert_in_the_middle(position, first, last, count);                             // may throw
+        }
+    }
+
+    template <typename Iterator>
+    void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
+    {
+        difference_type to_move = std::distance(position, this->end());
+
+        // TODO - should following lines check for exception and revert to the old size?
+
+        if ( count < to_move )
+        {
+            this->uninitialized_copy(this->end() - count, this->end(), this->end());            // may throw
+            m_size += count; // update end
+            this->move_backward(position, position + to_move - count, this->end() - count);     // may throw
+            this->copy(first, last, position);                                                  // may throw
+        }
+        else
+        {
+            Iterator middle_iter = first;
+            std::advance(middle_iter, to_move);
+
+            this->uninitialized_copy(middle_iter, last, this->end());                           // may throw
+            m_size += count - to_move; // update end
+            this->uninitialized_copy(position, position + to_move, position + count);           // may throw
+            m_size += to_move; // update end
+            this->copy(first, middle_iter, position) ;                                          // may throw
+        }
     }
 
     // assign
@@ -452,6 +481,7 @@
         if ( m_size <= s )
         {
             this->copy(first, first + m_size, this->begin());                        // may throw
+            // TODO - perform uninitialized_copy first?
             this->uninitialized_copy(first + m_size, last, this->end());             // may throw
         }
         else
@@ -465,7 +495,7 @@
     template <typename Iterator, typename Traversal>
     void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
     {
-        size_t s = 0;
+        size_type s = 0;
         iterator it = this->begin();
 
         for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
@@ -473,20 +503,39 @@
 
         this->destroy(it, this->end());
 
+        std::pair<bool, size_type> copy_data =
+            this->uninitialized_copy_checked(first, last, it, std::distance(it, this->begin() + Capacity)); // may throw
+        s += copy_data.second;
+
+        BOOST_ASSERT_MSG(copy_data.first, "size can't exceed the capacity");
+        // eventually throw bad_alloc
+
+        m_size = s; // update end
+    }
+
+    // uninitialized_copy_checked
+
+    template <typename Iterator>
+    std::pair<bool, size_type> uninitialized_copy_checked(Iterator first, Iterator last, iterator dest, size_type max_count)
+    {
+        size_type count = 0;
+        iterator it = dest;
         try
         {
-            for ( ; first != last ; ++it, ++first, ++s )
+            for ( ; first != last ; ++it, ++first, ++count )
             {
-                BOOST_ASSERT_MSG(s < Capacity, "size can't exceed the capacity");
-                this->uninitialized_fill(it, *first);                               // may throw
+                if ( max_count <= count )
+                    return std::make_pair(false, count);
+
+                this->uninitialized_fill(it, *first);                              // may throw
             }
-            m_size = s; // update end
         }
         catch(...)
         {
-            this->destroy(this->begin() + m_size, it);
+            this->destroy(dest, it);
             throw;
         }
+        return std::make_pair(true, count);
     }
 
     // copy
Modified: sandbox-branches/geometry/index/test/static_vector.cpp
==============================================================================
--- sandbox-branches/geometry/index/test/static_vector.cpp	(original)
+++ sandbox-branches/geometry/index/test/static_vector.cpp	2012-12-16 13:31:03 EST (Sun, 16 Dec 2012)
@@ -421,6 +421,23 @@
                 BOOST_CHECK(s1[j+i+n] == T(j+i));
         }        
     }
+    {
+        size_t n = size_t(h/1.5f);
+        for ( size_t i = 0 ; i <= h ; ++i )
+        {
+            static_vector<T, N> s1(s);
+            std::list<T>::iterator it = l.begin();
+            std::advance(it, n);
+            s1.insert(s1.begin() + i, l.begin(), it);
+            BOOST_CHECK(s1.size() == h+n);
+            for ( size_t j = 0 ; j < i ; ++j )
+                BOOST_CHECK(s1[j] == T(j));
+            for ( size_t j = 0 ; j < n ; ++j )
+                BOOST_CHECK(s1[j+i] == T(100 + j));
+            for ( size_t j = 0 ; j < h-i ; ++j )
+                BOOST_CHECK(s1[j+i+n] == T(j+i));
+        }        
+    }
 }
 
 int test_main(int, char* [])