mirror of
https://github.com/boostorg/circular_buffer.git
synced 2026-02-13 12:22:19 +00:00
Updated assign methods
[SVN r2726]
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/type_traits/is_stateless.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <deque>
|
||||
@@ -87,6 +88,9 @@ public:
|
||||
|
||||
//! Const (random access) iterator used to iterate through a circular buffer.
|
||||
typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::const_traits<Alloc> > const_iterator;
|
||||
|
||||
|
||||
|
||||
|
||||
//! Iterator (random access) used to iterate through a circular buffer.
|
||||
typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::nonconst_traits<Alloc> > iterator;
|
||||
@@ -535,32 +539,27 @@ public:
|
||||
|
||||
//! Assign <code>n</code> items into the circular buffer.
|
||||
/*!
|
||||
\post <code>(*this).size() == n \&\&
|
||||
(*this)[0] == (*this)[1] == ... == (*this).back() == item</code><br>
|
||||
If the number of items to be assigned exceeds
|
||||
the capacity of the circular buffer the capacity
|
||||
is increased to <code>n</code> otherwise it stays unchanged.
|
||||
\post <code>(*this).capacity() == n \&\& (*this).size() == n \&\&
|
||||
(*this)[0] == (*this)[1] == ... == (*this).back() == item</code>
|
||||
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if standard allocator is used).
|
||||
\throws Whatever T::T(const T&) throws.
|
||||
\note For iterator invalidation see the <a href="../circular_buffer.html#invalidation">documentation</a>.
|
||||
*/
|
||||
void assign(size_type n, param_value_type item) {
|
||||
do_assign(std::max(n, capacity()), n, cb_details::assign_n<param_value_type, allocator_type>(n, item, m_alloc));
|
||||
assign_n(n, n, cb_details::assign_n<param_value_type, allocator_type>(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<param_value_type, allocator_type>(n, item, m_alloc));
|
||||
assign_n(capacity, n, cb_details::assign_n<param_value_type, allocator_type>(n, item, m_alloc));
|
||||
}
|
||||
|
||||
//! Assign a copy of range.
|
||||
/*!
|
||||
\pre Valid range <code>[first, last)</code>.
|
||||
\post <code>(*this).size() == std::distance(first, last)</code><br>
|
||||
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 <code>(*this).capacity() == std::distance(first, last) \&\&
|
||||
(*this).size() == std::distance(first, last)</code>
|
||||
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if standard allocator is used).
|
||||
\throws Whatever T::T(const T&) throws.
|
||||
\note For iterator invalidation see the <a href="../circular_buffer.html#invalidation">documentation</a>.
|
||||
@@ -584,6 +583,7 @@ public:
|
||||
void swap(circular_buffer<T, Alloc>& cb) {
|
||||
std::swap(m_alloc, cb.m_alloc); // in general this is not necessary,
|
||||
// because allocators should not have state
|
||||
// TODO is_stateless<allocator_type>::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<const_pointer, param_value_type>(item));
|
||||
insert_n(pos, n, cb_details::item_wrapper<const_pointer, param_value_type>(item));
|
||||
}
|
||||
|
||||
//! Insert the range <code>[first, last)</code> 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<const_pointer, param_value_type>(item));
|
||||
rinsert_n(pos, n, cb_details::item_wrapper<const_pointer, param_value_type>(item));
|
||||
}
|
||||
|
||||
//! Insert the range <code>[first, last)</code> before the given position.
|
||||
@@ -1153,7 +1153,7 @@ private:
|
||||
template <class InputIterator>
|
||||
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<value_type> tmp(first, last);
|
||||
std::deque<value_type, allocator_type> 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 <class IntegralType>
|
||||
void assign(IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
assign(static_cast<size_type>(n), item);
|
||||
assign(static_cast<size_type>(n), static_cast<value_type>(item));
|
||||
}
|
||||
|
||||
//! Specialized assign method.
|
||||
@@ -1266,9 +1266,9 @@ private:
|
||||
template <class InputIterator>
|
||||
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<value_type> tmp(first, last);
|
||||
std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
|
||||
size_type distance = tmp.size();
|
||||
do_assign(std::max(distance, capacity()), distance, cb_details::assign_range<BOOST_DEDUCED_TYPENAME std::deque<value_type>::iterator, allocator_type>(tmp.begin(), tmp.end(), m_alloc));
|
||||
assign_n(distance, distance, cb_details::assign_range<BOOST_DEDUCED_TYPENAME std::deque<value_type, allocator_type>::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<ForwardIterator, allocator_type>(first, last, m_alloc));
|
||||
assign_n(distance, distance, cb_details::assign_range<ForwardIterator, allocator_type>(first, last, m_alloc));
|
||||
}
|
||||
|
||||
//! Specialized assign method.
|
||||
template <class IntegralType>
|
||||
void assign(size_type capacity, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
assign(capacity, static_cast<size_type>(n), item);
|
||||
void assign(size_type new_capacity, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
assign(new_capacity, static_cast<size_type>(n), static_cast<value_type>(item));
|
||||
}
|
||||
|
||||
//! Specialized assign method.
|
||||
template <class Iterator>
|
||||
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<Iterator>::type());
|
||||
assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
|
||||
}
|
||||
|
||||
//! Specialized assign method.
|
||||
template <class InputIterator>
|
||||
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<value_type> tmp(first, last);
|
||||
size_type distance = tmp.size();
|
||||
BOOST_DEDUCED_TYPENAME std::deque<value_type>::iterator begin = tmp.begin();
|
||||
if (distance > capacity) {
|
||||
std::advance(begin, distance - capacity);
|
||||
distance = capacity;
|
||||
}
|
||||
do_assign(capacity, distance, cb_details::assign_range<BOOST_DEDUCED_TYPENAME std::deque<value_type>::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<value_type, allocator_type> tmp(new_capacity, first, last, m_alloc);
|
||||
tmp.swap(*this);
|
||||
}
|
||||
}
|
||||
|
||||
//! Specialized assign method.
|
||||
template <class ForwardIterator>
|
||||
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<ForwardIterator, allocator_type>(first, last, m_alloc));
|
||||
assign_n(new_capacity, distance, cb_details::assign_range<ForwardIterator, allocator_type>(first, last, m_alloc));
|
||||
}
|
||||
|
||||
//! Helper assign method.
|
||||
template <class Functor>
|
||||
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 <class IntegralType>
|
||||
void insert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
insert(pos, static_cast<size_type>(n), item);
|
||||
insert(pos, static_cast<size_type>(n), static_cast<value_type>(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<ForwardIterator>(first));
|
||||
insert_n(pos, n, cb_details::iterator_wrapper<ForwardIterator>(first));
|
||||
}
|
||||
|
||||
//! Helper insert method.
|
||||
template <class Wrapper>
|
||||
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 <class IntegralType>
|
||||
void rinsert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
rinsert(pos, static_cast<size_type>(n), item);
|
||||
rinsert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
|
||||
}
|
||||
|
||||
//! Specialized rinsert method.
|
||||
@@ -1449,12 +1447,12 @@ private:
|
||||
template <class ForwardIterator>
|
||||
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<ForwardIterator>(first));
|
||||
rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper<ForwardIterator>(first));
|
||||
}
|
||||
|
||||
//! Helper rinsert method.
|
||||
template <class Wrapper>
|
||||
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());
|
||||
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
size_type n,
|
||||
param_value_type item,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: circular_buffer<T, Alloc>(capacity_ctrl.m_capacity, n, item, alloc)
|
||||
: circular_buffer<T, Alloc>(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<T, Alloc>(
|
||||
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<InputIterator>::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 <class InputIterator>
|
||||
void assign(capacity_control capacity_ctrl, InputIterator first, InputIterator last) {
|
||||
m_capacity_ctrl = capacity_ctrl;
|
||||
circular_buffer<T, Alloc>::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 <class InputIterator>
|
||||
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<size_type>(std::distance(first, last))));
|
||||
}
|
||||
//! Specialized method for determining the initial capacity.
|
||||
template <class IntegralType>
|
||||
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<size_type>(n)); // check for capacity lower than n
|
||||
return std::max(capacity_ctrl.m_min_capacity, static_cast<size_type>(n));
|
||||
}
|
||||
|
||||
//! Specialized method for determining the initial capacity.
|
||||
template <class Iterator>
|
||||
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<Iterator>::type());
|
||||
}
|
||||
|
||||
//! Specialized method for determining the initial capacity.
|
||||
template <class InputIterator>
|
||||
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 <class ForwardIterator>
|
||||
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<size_type>(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 <class InputIterator>
|
||||
void insert(iterator pos, InputIterator n, InputIterator item, cb_details::int_tag) {
|
||||
insert(pos, static_cast<size_type>(n), item);
|
||||
template <class IntegralType>
|
||||
void insert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
insert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
|
||||
}
|
||||
|
||||
//! Specialized insert method.
|
||||
template <class InputIterator>
|
||||
void insert(iterator pos, InputIterator first, InputIterator last, cb_details::iterator_tag) {
|
||||
template <class Iterator>
|
||||
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<T, Alloc>::insert(begin() + index, first, last);
|
||||
}
|
||||
|
||||
//! Specialized rinsert method.
|
||||
template <class InputIterator>
|
||||
void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::int_tag) {
|
||||
rinsert(pos, static_cast<size_type>(n), item);
|
||||
template <class IntegralType>
|
||||
void rinsert(iterator pos, IntegralType n, IntegralType item, cb_details::int_tag) {
|
||||
rinsert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
|
||||
}
|
||||
|
||||
//! Specialized rinsert method.
|
||||
template <class InputIterator>
|
||||
void rinsert(iterator pos, InputIterator first, InputIterator last, cb_details::iterator_tag) {
|
||||
template <class Iterator>
|
||||
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<T, Alloc>::rinsert(begin() + index, first, last);
|
||||
|
||||
Reference in New Issue
Block a user