diff --git a/include/boost/geometry/extensions/index/static_vector.hpp b/include/boost/geometry/extensions/index/static_vector.hpp index 1861a259e..663d11842 100644 --- a/include/boost/geometry/extensions/index/static_vector.hpp +++ b/include/boost/geometry/extensions/index/static_vector.hpp @@ -179,6 +179,8 @@ public: } else { + // TODO - should following lines check for exception and revert to the old size? + this->uninitialized_fill(this->end(), *(this->end() - 1)); // may throw ++m_size; // update end this->move_backward(position, this->end() - 2, this->end() - 1); // may throw @@ -205,6 +207,8 @@ public: { difference_type to_move = std::distance(position, this->end()); + // TODO - should following lines check for exception and revert to the old size? + if ( count < static_cast(to_move) ) { this->uninitialized_copy(this->end() - count, this->end(), this->end()); // may throw @@ -223,6 +227,14 @@ public: } } + // basic + template + void insert(iterator position, Iterator first, Iterator last) + { + typedef typename boost::iterator_traversal::type traversal; + this->insert_dispatch(position, first, last, traversal()); + } + // basic void erase(iterator position) { @@ -257,7 +269,7 @@ public: void assign(Iterator first, Iterator last) { typedef typename boost::iterator_traversal::type traversal; - assign_dispatch(first, last, traversal()); // may throw + this->assign_dispatch(first, last, traversal()); // may throw } // basic @@ -370,10 +382,63 @@ public: private: + // insert + + template + void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&) + { + // 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"); + + 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(); + + if ( position == this->end() ) + { + this->uninitialized_copy(first, last, position); // may throw + m_size += count; // update end + } + 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 + } + } + } + + template + 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)); + } + // assign template - void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const&) + void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/) { size_type s = std::distance(first, last); diff --git a/test/static_vector.cpp b/test/static_vector.cpp index 838be61fb..b2a519dc3 100644 --- a/test/static_vector.cpp +++ b/test/static_vector.cpp @@ -344,47 +344,79 @@ void test_erase_nd() } template -void test_insert_nd(T const& v) +void test_insert_nd(T const& val) { size_t h = N/2; - static_vector s; + static_vector s, ss; + std::vector v; + std::list l; for ( size_t i = 0 ; i < h ; ++i ) + { s.push_back(T(i)); - - { - static_vector s1(s); - for ( size_t i = 0 ; i < h ; ++i ) - s1.insert(s1.begin(), v); - BOOST_CHECK(s1.size() == 2*h); - for ( size_t i = 0 ; i < h ; ++i ) - BOOST_CHECK(s1[i] == v); - for ( size_t i = 0 ; i < h ; ++i ) - BOOST_CHECK(s1[i+h] == T(i)); - } - { - static_vector s1(s); - for ( size_t i = 0 ; i < h ; ++i ) - s1.insert(s1.end(), v); - BOOST_CHECK(s1.size() == 2*h); - for ( size_t i = 0 ; i < h ; ++i ) - BOOST_CHECK(s1[i] == T(i)); - for ( size_t i = 0 ; i < h ; ++i ) - BOOST_CHECK(s1[i+h] == v); + ss.push_back(T(100 + i)); + v.push_back(T(100 + i)); + l.push_back(T(100 + i)); } + // insert(pos, val) + { + for ( size_t i = 0 ; i <= h ; ++i ) + { + static_vector s1(s); + s1.insert(s1.begin() + i, val); + BOOST_CHECK(s1.size() == h+1); + for ( size_t j = 0 ; j < i ; ++j ) + BOOST_CHECK(s1[j] == T(j)); + BOOST_CHECK(s1[i] == val); + for ( size_t j = 0 ; j < h-i ; ++j ) + BOOST_CHECK(s1[j+i+1] == T(j+i)); + } + } + // insert(pos, n, val) { size_t n = size_t(h/1.5f); for ( size_t i = 0 ; i <= h ; ++i ) { static_vector s1(s); - s1.insert(s1.begin() + i, n, v); + s1.insert(s1.begin() + i, n, val); 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] == v); + BOOST_CHECK(s1[j+i] == val); + for ( size_t j = 0 ; j < h-i ; ++j ) + BOOST_CHECK(s1[j+i+n] == T(j+i)); + } + } + // insert(pos, first, last) + { + size_t n = size_t(h/1.5f); + for ( size_t i = 0 ; i <= h ; ++i ) + { + static_vector s1(s); + s1.insert(s1.begin() + i, ss.begin(), ss.begin() + n); + 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)); + } + } + { + size_t n = size_t(h/1.5f); + for ( size_t i = 0 ; i <= h ; ++i ) + { + static_vector s1(s); + s1.insert(s1.begin() + i, v.begin(), v.begin() + n); + 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)); }