From a467bd017eaf1cd42c24f4bd3e52a740fe87391d Mon Sep 17 00:00:00 2001 From: Jan Gaspar Date: Sun, 11 Sep 2005 21:46:04 +0000 Subject: [PATCH] implemented new assign method [SVN r2713] --- include/boost/circular_buffer/base.hpp | 72 +++++++++++++++++++++----- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp index 77a6212..e53e8ae 100644 --- a/include/boost/circular_buffer/base.hpp +++ b/include/boost/circular_buffer/base.hpp @@ -545,10 +545,15 @@ public: \throws Whatever T::T(const T&) throws. \note For iterator invalidation see the documentation. */ - void assign(size_type n, param_value_type item) { do_assign(n, cb_details::assign_n(n, item, m_alloc)); } + void assign(size_type n, param_value_type item) { + do_assign(std::max(n, capacity()), n, cb_details::assign_n(n, item, m_alloc)); + } - // TODO - void assign(size_type capacity, size_type n, param_value_type item) {} + // TODO doc + void assign(size_type capacity, size_type n, param_value_type item) { + BOOST_CB_ASSERT(capacity >= n); // check for new capacity lower than n + do_assign(capacity, n, cb_details::assign_n(n, item, m_alloc)); + } //! Assign a copy of range. /*! @@ -566,9 +571,11 @@ public: assign(first, last, BOOST_DEDUCED_TYPENAME cb_details::iterator_cat_traits::tag()); } - // TODO + // TODO doc template - void assign(size_type capacity, InputIterator first, InputIterator last) {} + void assign(size_type capacity, InputIterator first, InputIterator last) { + assign(capacity, first, last, BOOST_DEDUCED_TYPENAME cb_details::iterator_cat_traits::tag()); + } //! Swap the contents of two circular buffers. /*! @@ -1246,27 +1253,68 @@ private: void assign(InputIterator first, InputIterator last, std::input_iterator_tag) { BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS; // check if the STL provides templated iterator constructors for containers std::deque tmp(first, last); - do_assign(tmp.size(), cb_details::assign_range::iterator, allocator_type>(tmp.begin(), tmp.end(), m_alloc)); + size_type distance = tmp.size(); + do_assign(std::max(distance, capacity()), distance, cb_details::assign_range::iterator, allocator_type>(tmp.begin(), tmp.end(), m_alloc)); } //! Specialized assign method. template void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) { BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - do_assign(std::distance(first, last), cb_details::assign_range(first, last, m_alloc)); + size_type distance = std::distance(first, last); + do_assign(std::max(distance, capacity()), distance, cb_details::assign_range(first, last, m_alloc)); + } + + //! Specialized assign method. + template + void assign(size_type capacity, IntegralType n, IntegralType item, cb_details::int_tag) { + assign(capacity, static_cast(n), item); + } + + //! Specialized assign method. + template + void assign(size_type capacity, Iterator first, Iterator last, cb_details::iterator_tag) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type + assign(capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); + } + + //! Specialized assign method. + template + void assign(size_type capacity, InputIterator first, InputIterator last, std::input_iterator_tag) { + BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS; // check if the STL provides templated iterator constructors for containers + std::deque tmp(first, last); + size_type distance = tmp.size(); + BOOST_DEDUCED_TYPENAME std::deque::iterator begin = tmp.begin(); + if (distance > capacity) { + std::advance(begin, distance - capacity); + distance = capacity; + } + do_assign(capacity, distance, cb_details::assign_range::iterator, allocator_type>(begin, tmp.end(), m_alloc)); + } + + //! Specialized assign method. + template + void assign(size_type capacity, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + size_type distance = std::distance(first, last); + if (distance > capacity) { + std::advance(first, distance - capacity); + distance = capacity; + } + do_assign(capacity, distance, cb_details::assign_range(first, last, m_alloc)); } //! Helper assign method. template - void do_assign(size_type n, const Functor& fnc) { - if (n > capacity()) { - pointer buff = allocate(n); + void do_assign(size_type new_capacity, size_type n, const Functor& fnc) { + if (new_capacity != capacity()) { + pointer buff = allocate(new_capacity); BOOST_CB_TRY fnc(buff); - BOOST_CB_UNWIND(deallocate(buff, n)) + BOOST_CB_UNWIND(deallocate(buff, new_capacity)) destroy(); m_buff = buff; - m_end = m_buff + n; + m_end = m_buff + new_capacity; } else { destroy_content(); BOOST_CB_TRY