From aaa1bd886ab822afdd6c8fa06e7149f99c636941 Mon Sep 17 00:00:00 2001 From: Jan Gaspar Date: Sun, 9 Oct 2005 22:12:18 +0000 Subject: [PATCH] Updated assign methods [SVN r2726] --- include/boost/circular_buffer/base.hpp | 98 +++++++++---------- .../boost/circular_buffer/space_optimized.hpp | 68 ++++++++----- test/common.cpp | 4 +- 3 files changed, 94 insertions(+), 76 deletions(-) diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp index b74053f..7fdf9c0 100644 --- a/include/boost/circular_buffer/base.hpp +++ b/include/boost/circular_buffer/base.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,9 @@ public: //! Const (random access) iterator used to iterate through a circular buffer. typedef cb_details::iterator< circular_buffer, cb_details::const_traits > const_iterator; + + + //! Iterator (random access) used to iterate through a circular buffer. typedef cb_details::iterator< circular_buffer, cb_details::nonconst_traits > iterator; @@ -535,32 +539,27 @@ public: //! Assign n items into the circular buffer. /*! - \post (*this).size() == n \&\& - (*this)[0] == (*this)[1] == ... == (*this).back() == item
- If the number of items to be assigned exceeds - the capacity of the circular buffer the capacity - is increased to n otherwise it stays unchanged. + \post (*this).capacity() == n \&\& (*this).size() == n \&\& + (*this)[0] == (*this)[1] == ... == (*this).back() == item \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). \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(std::max(n, capacity()), n, cb_details::assign_n(n, item, m_alloc)); + assign_n(n, n, cb_details::assign_n(n, item, m_alloc)); } // 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_n(capacity, n, cb_details::assign_n(n, item, m_alloc)); } //! Assign a copy of range. /*! \pre Valid range [first, last). - \post (*this).size() == std::distance(first, last)
- If the number of items to be assigned exceeds - the capacity of the circular buffer the capacity - is set to that number otherwise is stays unchanged. + \post (*this).capacity() == std::distance(first, last) \&\& + (*this).size() == std::distance(first, last) \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). \throws Whatever T::T(const T&) throws. \note For iterator invalidation see the documentation. @@ -584,6 +583,7 @@ public: void swap(circular_buffer& cb) { std::swap(m_alloc, cb.m_alloc); // in general this is not necessary, // because allocators should not have state + // TODO is_stateless::value -> std::swap(m_alloc, cb.m_alloc)); std::swap(m_buff, cb.m_buff); std::swap(m_end, cb.m_end); std::swap(m_first, cb.m_first); @@ -744,7 +744,7 @@ public: return; if (n > copy) n = copy; - insert_n_item(pos, n, cb_details::item_wrapper(item)); + insert_n(pos, n, cb_details::item_wrapper(item)); } //! Insert the range [first, last) before the given position. @@ -844,7 +844,7 @@ public: */ void rinsert(iterator pos, size_type n, param_value_type item) { BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator - rinsert_n_item(pos, n, cb_details::item_wrapper(item)); + rinsert_n(pos, n, cb_details::item_wrapper(item)); } //! Insert the range [first, last) before the given position. @@ -1153,7 +1153,7 @@ private: template void initialize(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); + std::deque tmp(first, last, m_alloc); size_type distance = tmp.size(); initialize(distance, tmp.begin(), tmp.last(), distance); } @@ -1252,7 +1252,7 @@ private: //! Specialized assign method. template void assign(IntegralType n, IntegralType item, cb_details::int_tag) { - assign(static_cast(n), item); + assign(static_cast(n), static_cast(item)); } //! Specialized assign method. @@ -1266,9 +1266,9 @@ private: template 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); + std::deque tmp(first, last, 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)); + assign_n(distance, distance, cb_details::assign_range::iterator, allocator_type>(tmp.begin(), tmp.end(), m_alloc)); } //! Specialized assign method. @@ -1276,64 +1276,62 @@ private: void assign(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); - do_assign(std::max(distance, capacity()), distance, cb_details::assign_range(first, last, m_alloc)); + assign_n(distance, 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); + void assign(size_type new_capacity, IntegralType n, IntegralType item, cb_details::int_tag) { + assign(new_capacity, static_cast(n), static_cast(item)); } //! Specialized assign method. template - void assign(size_type capacity, Iterator first, Iterator last, cb_details::iterator_tag) { + void assign(size_type new_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()); + assign(new_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)); + void assign(size_type new_capacity, InputIterator first, InputIterator last, std::input_iterator_tag) { + if (new_capacity == capacity()) { + clear(); + insert(begin(), first, last); + } else { + circular_buffer tmp(new_capacity, first, last, m_alloc); + tmp.swap(*this); + } } //! Specialized assign method. template - void assign(size_type capacity, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) { + void assign(size_type new_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) { + if (distance > new_capacity) { std::advance(first, distance - capacity); - distance = capacity; + distance = new_capacity; } - do_assign(capacity, distance, cb_details::assign_range(first, last, m_alloc)); + assign_n(new_capacity, distance, cb_details::assign_range(first, last, m_alloc)); } //! Helper assign method. template - void do_assign(size_type new_capacity, size_type n, const Functor& fnc) { - if (new_capacity != capacity()) { - pointer buff = allocate(new_capacity); + void assign_n(size_type new_capacity, size_type n, const Functor& fnc) { + if (new_capacity == capacity()) { + destroy_content(); + BOOST_CB_TRY + fnc(m_buff); + BOOST_CB_UNWIND(m_size = 0) + } else { + pointer buff = allocate(new_capacity); BOOST_CB_TRY fnc(buff); BOOST_CB_UNWIND(deallocate(buff, new_capacity)) destroy(); m_buff = buff; m_end = m_buff + new_capacity; - } else { - destroy_content(); - BOOST_CB_TRY - fnc(m_buff); - BOOST_CB_UNWIND(m_size = 0) } m_size = n; m_first = m_buff; @@ -1343,7 +1341,7 @@ private: //! Specialized insert method. template void insert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) { - insert(pos, static_cast(n), item); + insert(pos, static_cast(n), static_cast(item)); } //! Specialized insert method. @@ -1376,12 +1374,12 @@ private: std::advance(first, n - copy); n = copy; } - insert_n_item(pos, n, cb_details::iterator_wrapper(first)); + insert_n(pos, n, cb_details::iterator_wrapper(first)); } //! Helper insert method. template - void insert_n_item(iterator pos, size_type n, const Wrapper& wrapper) { + void insert_n(iterator pos, size_type n, const Wrapper& wrapper) { size_type construct = capacity() - size(); if (construct > n) construct = n; @@ -1426,7 +1424,7 @@ private: //! Specialized rinsert method. template void rinsert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) { - rinsert(pos, static_cast(n), item); + rinsert(pos, static_cast(n), static_cast(item)); } //! Specialized rinsert method. @@ -1449,12 +1447,12 @@ private: template void rinsert(iterator pos, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) { BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - rinsert_n_item(pos, std::distance(first, last), cb_details::iterator_wrapper(first)); + rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper(first)); } //! Helper rinsert method. template - void rinsert_n_item(iterator pos, size_type n, const Wrapper& wrapper) { + void rinsert_n(iterator pos, size_type n, const Wrapper& wrapper) { if (n == 0) return; size_type copy = capacity() - (pos - begin()); diff --git a/include/boost/circular_buffer/space_optimized.hpp b/include/boost/circular_buffer/space_optimized.hpp index 9dffbc9..6fac2db 100644 --- a/include/boost/circular_buffer/space_optimized.hpp +++ b/include/boost/circular_buffer/space_optimized.hpp @@ -220,7 +220,7 @@ public: size_type n, param_value_type item, const allocator_type& alloc = allocator_type()) - : circular_buffer(capacity_ctrl.m_capacity, n, item, alloc) + : circular_buffer(capacity_ctrl.m_capacity, n, item, alloc) // TODO wrong capacity initialization , m_capacity_ctrl(capacity_ctrl) {} // Default copy constructor @@ -263,10 +263,10 @@ public: InputIterator last, const allocator_type& alloc = allocator_type()) : circular_buffer( - init_capacity(capacity_ctrl, first, last), first, last, alloc) // TODO - , m_capacity_ctrl(capacity_ctrl) { - - } + init_capacity(capacity_ctrl, first, last, + BOOST_DEDUCED_TYPENAME cb_details::iterator_cat_traits::tag()), + first, last, alloc) + , m_capacity_ctrl(capacity_ctrl) {} // Default destructor @@ -306,10 +306,12 @@ public: check_high_capacity(); } - // TODO + //! See the circular_buffer source documentation. template void assign(capacity_control capacity_ctrl, InputIterator first, InputIterator last) { m_capacity_ctrl = capacity_ctrl; + circular_buffer::assign(capacity(), first, last); + check_high_capacity(); } //! See the circular_buffer source documentation. @@ -532,14 +534,32 @@ private: ensure_reserve(new_capacity, size())); } - //! Determine the initial capacity. - template - static size_type init_capacity(const capacity_control& capacity_ctrl, InputIterator first, InputIterator last) { - BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); // check for invalid iterator type - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - return std::min(capacity_ctrl.m_capacity, std::max(capacity_ctrl.m_min_capacity, - static_cast(std::distance(first, last)))); - } + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_control& capacity_ctrl, IntegralType n, IntegralType item, cb_details::int_tag) { + BOOST_CB_ASSERT(capacity_ctrl.m_capacity >= static_cast(n)); // check for capacity lower than n + return std::max(capacity_ctrl.m_min_capacity, static_cast(n)); + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_control& capacity_ctrl, Iterator first, Iterator last, cb_details::iterator_tag) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type + return init_capacity(capacity_ctrl, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_control& capacity_ctrl, InputIterator first, InputIterator last, std::input_iterator_tag) { + return capacity_ctrl.m_capacity; + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_control& capacity_ctrl, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + return std::min(capacity_ctrl.m_capacity, std::max(capacity_ctrl.m_min_capacity, static_cast(std::distance(first, last)))); + } //! Increase the size of the space optimized circular buffer. void increase_size(size_type new_size, param_value_type item) { @@ -549,28 +569,28 @@ private: } //! Specialized insert method. - template - void insert(iterator pos, InputIterator n, InputIterator item, cb_details::int_tag) { - insert(pos, static_cast(n), item); + template + void insert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) { + insert(pos, static_cast(n), static_cast(item)); } //! Specialized insert method. - template - void insert(iterator pos, InputIterator first, InputIterator last, cb_details::iterator_tag) { + template + void insert(iterator pos, Iterator first, Iterator last, cb_details::iterator_tag) { size_type index = pos - begin(); check_low_capacity(std::distance(first, last)); circular_buffer::insert(begin() + index, first, last); } //! Specialized rinsert method. - template - void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::int_tag) { - rinsert(pos, static_cast(n), item); + template + void rinsert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) { + rinsert(pos, static_cast(n), static_cast(item)); } //! Specialized rinsert method. - template - void rinsert(iterator pos, InputIterator first, InputIterator last, cb_details::iterator_tag) { + template + void rinsert(iterator pos, Iterator first, Iterator last, cb_details::iterator_tag) { size_type index = pos - begin(); check_low_capacity(std::distance(first, last)); circular_buffer::rinsert(begin() + index, first, last); diff --git a/test/common.cpp b/test/common.cpp index 69399a4..98595ff 100644 --- a/test/common.cpp +++ b/test/common.cpp @@ -572,7 +572,7 @@ void assign_test() { cb1.push_back(5); cb1.assign(3, 8); BOOST_CHECK(cb1.size() == 3); - BOOST_CHECK(cb1.capacity() == 4); + BOOST_CHECK(cb1.capacity() == 3); BOOST_CHECK(cb1[0] == 8); BOOST_CHECK(cb1[2] == 8); @@ -1266,7 +1266,7 @@ void assign_range_test() { cb2.push_back(2); cb2.assign(v.begin(), v.end()); - BOOST_CHECK(!cb1.full()); + BOOST_CHECK(cb1.capacity() == 2); BOOST_CHECK(cb1[0] == 12); BOOST_CHECK(cb1[1] == 13); BOOST_CHECK(cb2.full());