mirror of
https://github.com/boostorg/circular_buffer.git
synced 2026-02-10 23:32:21 +00:00
Initial revision.
[SVN r2447]
This commit is contained in:
62
include/boost/circular_buffer.hpp
Normal file
62
include/boost/circular_buffer.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Circular buffer library header file.
|
||||
|
||||
// Copyright (c) 2003-2004 Jan Gaspar
|
||||
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_CIRCULAR_BUFFER_HPP)
|
||||
#define BOOST_CIRCULAR_BUFFER_HPP
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
// Debug support control.
|
||||
#if defined(NDEBUG) || defined(BOOST_DISABLE_CB_DEBUG)
|
||||
#define BOOST_CB_ASSERT(Expr) ((void)0)
|
||||
#define BOOST_CB_ENABLE_DEBUG 0
|
||||
#else
|
||||
#include <boost/assert.hpp>
|
||||
#define BOOST_CB_ASSERT(Expr) BOOST_ASSERT(Expr)
|
||||
#define BOOST_CB_ENABLE_DEBUG 1
|
||||
#endif
|
||||
|
||||
// The macro definition which checks if Iterator::value_type is convertible to Type.
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0550) || \
|
||||
BOOST_WORKAROUND(__MWERKS__, <= 0x2407) || \
|
||||
BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
#define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) ((void)0)
|
||||
#else
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) \
|
||||
BOOST_STATIC_ASSERT((is_convertible<typename detail::iterator_traits<Iterator>::value_type, Type>::value));
|
||||
#endif
|
||||
|
||||
// Exception handling macros.
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
#define BOOST_CB_TRY try {
|
||||
#define BOOST_CB_UNWIND(action) } catch(...) { action; throw; }
|
||||
#else
|
||||
#define BOOST_CB_TRY {
|
||||
#define BOOST_CB_UNWIND(action) }
|
||||
#endif
|
||||
|
||||
#include "circular_buffer_fwd.hpp"
|
||||
#include "circular_buffer/debug.hpp"
|
||||
#include "circular_buffer/details.hpp"
|
||||
#include "circular_buffer/base.hpp"
|
||||
#include "circular_buffer/adaptor.hpp"
|
||||
|
||||
#undef BOOST_CB_UNWIND
|
||||
#undef BOOST_CB_TRY
|
||||
#undef BOOST_CB_IS_CONVERTIBLE
|
||||
#undef BOOST_CB_ENABLE_DEBUG
|
||||
#undef BOOST_CB_ASSERT
|
||||
|
||||
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_HPP)
|
||||
585
include/boost/circular_buffer/adaptor.hpp
Normal file
585
include/boost/circular_buffer/adaptor.hpp
Normal file
@@ -0,0 +1,585 @@
|
||||
// Implementation of the circular buffer adaptor.
|
||||
|
||||
// Copyright (c) 2003-2004 Jan Gaspar
|
||||
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
|
||||
#define BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
/*!
|
||||
\class circular_buffer_space_optimized
|
||||
\brief Space optimized circular buffer container adaptor.
|
||||
\param T The type of the elements stored in the space optimized circular buffer.
|
||||
\param Alloc The allocator type used for all internal memory management.
|
||||
\author <a href="mailto:jano_gaspar[at]yahoo.com">Jan Gaspar</a>
|
||||
\version 1.3
|
||||
\date 2004
|
||||
|
||||
For more information how to use the space optimized circular
|
||||
buffer see the <a href="../circular_buffer_adaptor.html">
|
||||
documentation</a>.
|
||||
*/
|
||||
template<class T, class Alloc>
|
||||
class circular_buffer_space_optimized : private circular_buffer<T, Alloc> {
|
||||
public:
|
||||
// Typedefs
|
||||
|
||||
typedef typename circular_buffer<T, Alloc>::value_type value_type;
|
||||
typedef typename circular_buffer<T, Alloc>::pointer pointer;
|
||||
typedef typename circular_buffer<T, Alloc>::const_pointer const_pointer;
|
||||
typedef typename circular_buffer<T, Alloc>::reference reference;
|
||||
typedef typename circular_buffer<T, Alloc>::const_reference const_reference;
|
||||
typedef typename circular_buffer<T, Alloc>::size_type size_type;
|
||||
typedef typename circular_buffer<T, Alloc>::difference_type difference_type;
|
||||
typedef typename circular_buffer<T, Alloc>::allocator_type allocator_type;
|
||||
typedef typename circular_buffer<T, Alloc>::param_value_type param_value_type;
|
||||
typedef typename circular_buffer<T, Alloc>::const_iterator const_iterator;
|
||||
typedef typename circular_buffer<T, Alloc>::iterator iterator;
|
||||
typedef typename circular_buffer<T, Alloc>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename circular_buffer<T, Alloc>::reverse_iterator reverse_iterator;
|
||||
|
||||
// Inherited
|
||||
|
||||
using circular_buffer<T, Alloc>::get_allocator;
|
||||
using circular_buffer<T, Alloc>::begin;
|
||||
using circular_buffer<T, Alloc>::end;
|
||||
using circular_buffer<T, Alloc>::rbegin;
|
||||
using circular_buffer<T, Alloc>::rend;
|
||||
using circular_buffer<T, Alloc>::at;
|
||||
using circular_buffer<T, Alloc>::front;
|
||||
using circular_buffer<T, Alloc>::back;
|
||||
using circular_buffer<T, Alloc>::data;
|
||||
using circular_buffer<T, Alloc>::size;
|
||||
using circular_buffer<T, Alloc>::max_size;
|
||||
using circular_buffer<T, Alloc>::empty;
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
reference operator [] (size_type n) { return circular_buffer<T, Alloc>::operator[](n); }
|
||||
return_value_type operator [] (size_type n) const { return circular_buffer<T, Alloc>::operator[](n); }
|
||||
#else
|
||||
using circular_buffer<T, Alloc>::operator[];
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Member variables
|
||||
|
||||
//! The capacity of the optimized circular buffer.
|
||||
size_type m_capacity;
|
||||
|
||||
//! The lowest guaranteed capacity of the adapted circular buffer.
|
||||
size_type m_min_capacity;
|
||||
|
||||
public:
|
||||
// Overridden
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
bool full() const { return size() == capacity(); }
|
||||
|
||||
//! Return the minimal guaranteed amount of allocated memory.
|
||||
/*!
|
||||
The allocated memory will never drop under this value.
|
||||
*/
|
||||
size_type min_capacity() const { return m_min_capacity; }
|
||||
|
||||
//! Change the minimal guaranteed amount of allocated memory.
|
||||
/*!
|
||||
\pre <code>(*this).capacity() >= new_min_capacity</code>
|
||||
\post <code>(*this).min_capacity() == new_min_capacity</code>
|
||||
Allocates memory specified by the <code>new_min_capacity</code> parameter.
|
||||
\note It is considered as a bug if the precondition is not met (i.e. if
|
||||
<code>new_min_capacity > (*this).capacity()</code>) and an assertion
|
||||
will be invoked in the debug mode.
|
||||
*/
|
||||
void set_min_capacity(size_type new_min_capacity) {
|
||||
BOOST_CB_ASSERT(capacity() >= new_min_capacity); // check for too large new min_capacity
|
||||
m_min_capacity = new_min_capacity;
|
||||
if (new_min_capacity > circular_buffer<T, Alloc>::capacity())
|
||||
circular_buffer<T, Alloc>::set_capacity(new_min_capacity);
|
||||
else
|
||||
check_high_capacity();
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
size_type capacity() const { return m_capacity; }
|
||||
|
||||
#if defined(BOOST_CB_TEST)
|
||||
|
||||
//! Return the current capacity of the adapted circular buffer.
|
||||
/*!
|
||||
\note This method is not intended to be used directly by the user.
|
||||
It is defined only for testing purposes.
|
||||
*/
|
||||
size_type internal_capacity() const { return circular_buffer<T, Alloc>::capacity(); }
|
||||
|
||||
#endif // #if defined(BOOST_CB_TEST)
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\pre <code>(*this).min_capacity() <= new_capacity</code>
|
||||
\note It is considered as a bug if the precondition is not met (i.e. if
|
||||
<code>new_capacity > (*this).min_capacity()</code>) and an assertion
|
||||
will be invoked in the debug mode.
|
||||
*/
|
||||
void set_capacity(size_type new_capacity, bool remove_front = true) {
|
||||
BOOST_CB_ASSERT(new_capacity >= min_capacity()); // check for too low new capacity
|
||||
if (new_capacity < circular_buffer<T, Alloc>::capacity())
|
||||
circular_buffer<T, Alloc>::set_capacity(new_capacity, remove_front);
|
||||
m_capacity = new_capacity;
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) {
|
||||
if (new_size > size()) {
|
||||
if (new_size > capacity())
|
||||
m_capacity = new_size;
|
||||
insert(end(), new_size - size(), item);
|
||||
} else {
|
||||
if (remove_front)
|
||||
erase(begin(), end() - new_size);
|
||||
else
|
||||
erase(begin() + new_size, end());
|
||||
}
|
||||
}
|
||||
|
||||
//! Create an empty space optimized circular buffer with a given capacity.
|
||||
/*!
|
||||
\param capacity The capacity of the buffer.
|
||||
\param min_capacity The minimal guaranteed amount of allocated memory.
|
||||
(The metrics of the min_capacity is number of items.)
|
||||
\param alloc The allocator.
|
||||
\pre <code>capacity >= min_capacity</code>
|
||||
\post <code>(*this).capacity() == capacity \&\& (*this).size == 0</code><br>
|
||||
Allocates memory specified by the <code>min_capacity</code> parameter.
|
||||
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if standard allocator is used).
|
||||
\note It is considered as a bug if the precondition is not met (i.e. if
|
||||
<code>capacity < min_capacity</code>) and an assertion will be invoked
|
||||
in the debug mode.
|
||||
*/
|
||||
explicit circular_buffer_space_optimized(
|
||||
size_type capacity,
|
||||
size_type min_capacity = 0,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: circular_buffer<T, Alloc>(min_capacity, alloc)
|
||||
, m_capacity(capacity)
|
||||
, m_min_capacity(min_capacity) {
|
||||
BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity
|
||||
}
|
||||
|
||||
//! Create a full space optimized circular buffer filled with copies of <code>item</code>.
|
||||
/*!
|
||||
\param capacity The capacity of the buffer.
|
||||
\param min_capacity The minimal guaranteed amount of allocated memory.
|
||||
(The metrics of the min_capacity is number of items.)
|
||||
\param item The item to be filled with.
|
||||
\param alloc The allocator.
|
||||
\pre <code>capacity >= min_capacity</code>
|
||||
\post <code>(*this).size() == capacity \&\& (*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 It is considered as a bug if the precondition is not met (i.e. if
|
||||
<code>capacity < min_capacity</code>) and an assertion will be invoked
|
||||
in the debug mode.
|
||||
*/
|
||||
circular_buffer_space_optimized(
|
||||
size_type capacity,
|
||||
size_type min_capacity,
|
||||
param_value_type item,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: circular_buffer<T, Alloc>(capacity, item, alloc)
|
||||
, m_capacity(capacity)
|
||||
, m_min_capacity(min_capacity) {
|
||||
BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity
|
||||
}
|
||||
|
||||
// Default copy constructor
|
||||
|
||||
//! Create a space optimized circular buffer with a copy of a range.
|
||||
/*!
|
||||
\param capacity The capacity of the buffer.
|
||||
\param min_capacity The minimal guaranteed amount of allocated memory.
|
||||
(The metrics of the min_capacity is number of items.)
|
||||
\param first The beginning of the range.
|
||||
\param last The end of the range.
|
||||
\param alloc The allocator.
|
||||
\pre <code>capacity >= min_capacity</code> and valid range <code>[first, last)</code>.
|
||||
\post <code>(*this).capacity() == capacity</code><br>
|
||||
Allocates at least as much memory as specified by the
|
||||
<code>min_capacity</code> parameter.<br>
|
||||
If the number of items to copy from the range
|
||||
<code>[first, last)</code> is greater than the specified
|
||||
<code>capacity</code> then only elements from the range
|
||||
<code>[last - capacity, last)</code> will be copied.
|
||||
\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 It is considered as a bug if the precondition is not met (i.e. if
|
||||
<code>capacity < min_capacity</code>) and an assertion will be invoked
|
||||
in the debug mode.
|
||||
*/
|
||||
template <class InputIterator>
|
||||
circular_buffer_space_optimized(
|
||||
size_type capacity,
|
||||
size_type min_capacity,
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: circular_buffer<T, Alloc>(
|
||||
init_capacity(capacity, min_capacity, first, last), first, last, alloc)
|
||||
, m_capacity(capacity)
|
||||
, m_min_capacity(min_capacity) {
|
||||
BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity
|
||||
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
||||
}
|
||||
|
||||
// Default destructor
|
||||
|
||||
// Default assign operator
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
void assign(size_type n, param_value_type item) {
|
||||
if (n > m_capacity)
|
||||
m_capacity = n;
|
||||
circular_buffer<T, Alloc>::assign(n, item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
template <class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last) {
|
||||
circular_buffer<T, Alloc>::assign(first, last);
|
||||
size_type capacity = circular_buffer<T, Alloc>::capacity();
|
||||
if (capacity > m_capacity)
|
||||
m_capacity = capacity;
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
void swap(circular_buffer_space_optimized& cb) {
|
||||
std::swap(m_capacity, cb.m_capacity);
|
||||
std::swap(m_min_capacity, cb.m_min_capacity);
|
||||
circular_buffer<T, Alloc>::swap(cb);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void push_back(param_value_type item) {
|
||||
check_low_capacity();
|
||||
circular_buffer<T, Alloc>::push_back(item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void push_back() { push_back(value_type()); }
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void push_front(param_value_type item) {
|
||||
check_low_capacity();
|
||||
circular_buffer<T, Alloc>::push_front(item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void push_front() { push_front(value_type()); }
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void pop_back() {
|
||||
circular_buffer<T, Alloc>::pop_back();
|
||||
check_high_capacity();
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void pop_front() {
|
||||
circular_buffer<T, Alloc>::pop_front();
|
||||
check_high_capacity();
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator insert(iterator pos, param_value_type item) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity();
|
||||
return circular_buffer<T, Alloc>::insert(begin() + index, item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator insert(iterator pos) { return insert(pos, value_type()); }
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void insert(iterator pos, size_type n, param_value_type item) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity(n);
|
||||
circular_buffer<T, Alloc>::insert(begin() + index, n, item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
template <class InputIterator>
|
||||
void insert(iterator pos, InputIterator first, InputIterator last) {
|
||||
insert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator rinsert(iterator pos, param_value_type item) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity();
|
||||
return circular_buffer<T, Alloc>::rinsert(begin() + index, item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
void rinsert(iterator pos, size_type n, param_value_type item) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity(n);
|
||||
circular_buffer<T, Alloc>::rinsert(begin() + index, n, item);
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
template <class InputIterator>
|
||||
void rinsert(iterator pos, InputIterator first, InputIterator last) {
|
||||
rinsert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator erase(iterator pos) {
|
||||
iterator it = circular_buffer<T, Alloc>::erase(pos);
|
||||
size_type index = it - begin();
|
||||
check_high_capacity();
|
||||
return begin() + index;
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
/*!
|
||||
\warning The rules for iterator invalidation differ from the original
|
||||
circular_buffer. See the <a href="../circular_buffer_adaptor.html#invalidation">
|
||||
documentation</a>.
|
||||
*/
|
||||
iterator erase(iterator first, iterator last) {
|
||||
iterator it = circular_buffer<T, Alloc>::erase(first, last);
|
||||
size_type index = it - begin();
|
||||
check_high_capacity();
|
||||
return begin() + index;
|
||||
}
|
||||
|
||||
//! See the circular_buffer source documentation.
|
||||
void clear() { erase(begin(), end()); }
|
||||
|
||||
private:
|
||||
// Helper methods
|
||||
|
||||
//! Ensure the reserve for possible growth up.
|
||||
size_type ensure_reserve(size_type new_capacity, size_type size) const {
|
||||
if (size + new_capacity / 5 >= new_capacity)
|
||||
new_capacity *= 2; // ensure at least 20% reserve
|
||||
if (new_capacity > capacity())
|
||||
return capacity();
|
||||
return new_capacity;
|
||||
}
|
||||
|
||||
//! Check for low capacity.
|
||||
/*
|
||||
\post If the capacity is low it will be increased.
|
||||
*/
|
||||
void check_low_capacity(size_type n = 1) {
|
||||
size_type new_size = size() + n;
|
||||
size_type new_capacity = circular_buffer<T, Alloc>::capacity();
|
||||
if (new_size > new_capacity) {
|
||||
if (new_capacity == 0)
|
||||
new_capacity = 1;
|
||||
for (; new_size > new_capacity; new_capacity *= 2);
|
||||
circular_buffer<T, Alloc>::set_capacity(
|
||||
ensure_reserve(new_capacity, new_size));
|
||||
}
|
||||
}
|
||||
|
||||
//! Check for high capacity.
|
||||
/*
|
||||
\post If the capacity is high it will be decreased.
|
||||
*/
|
||||
void check_high_capacity() {
|
||||
size_type new_capacity = circular_buffer<T, Alloc>::capacity();
|
||||
while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations
|
||||
new_capacity /= 2;
|
||||
if (new_capacity <= min_capacity()) {
|
||||
new_capacity = min_capacity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
circular_buffer<T, Alloc>::set_capacity(
|
||||
ensure_reserve(new_capacity, size()));
|
||||
}
|
||||
|
||||
//! Determine the initial capacity.
|
||||
template <class InputIterator>
|
||||
static size_type init_capacity(size_type capacity, size_type min_capacity, InputIterator first, InputIterator last) {
|
||||
BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
|
||||
return std::min(capacity, std::max(min_capacity,
|
||||
static_cast<size_type>(std::distance(first, last))));
|
||||
}
|
||||
|
||||
//! Helper insert method.
|
||||
template <class InputIterator>
|
||||
void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
|
||||
insert(pos, (size_type)n, item);
|
||||
}
|
||||
|
||||
//! Helper insert method.
|
||||
template <class InputIterator>
|
||||
void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity(std::distance(first, last));
|
||||
circular_buffer<T, Alloc>::insert(begin() + index, first, last);
|
||||
}
|
||||
|
||||
//! Helper rinsert method.
|
||||
template <class InputIterator>
|
||||
void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
|
||||
rinsert(pos, (size_type)n, item);
|
||||
}
|
||||
|
||||
//! Helper rinsert method.
|
||||
template <class InputIterator>
|
||||
void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
|
||||
size_type index = pos - begin();
|
||||
check_low_capacity(std::distance(first, last));
|
||||
circular_buffer<T, Alloc>::rinsert(begin() + index, first, last);
|
||||
}
|
||||
};
|
||||
|
||||
// Non-member functions
|
||||
|
||||
//! Test two space optimized circular buffers for equality.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator == (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return lhs.size() == rhs.size() &&
|
||||
std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
//! Lexicographical comparison.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator < (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
|
||||
|
||||
//! Test two space optimized circular buffers for non-equality.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator != (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
//! Lexicographical comparison.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator > (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
//! Lexicographical comparison.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator <= (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
//! Lexicographical comparison.
|
||||
template <class T, class Alloc>
|
||||
inline bool operator >= (const circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
const circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
//! Swap the contents of two space optimized circular buffers.
|
||||
template <class T, class Alloc>
|
||||
inline void swap(circular_buffer_space_optimized<T, Alloc>& lhs,
|
||||
circular_buffer_space_optimized<T, Alloc>& rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
|
||||
1439
include/boost/circular_buffer/base.hpp
Normal file
1439
include/boost/circular_buffer/base.hpp
Normal file
File diff suppressed because it is too large
Load Diff
211
include/boost/circular_buffer/debug.hpp
Normal file
211
include/boost/circular_buffer/debug.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// Debug support for the circular buffer library.
|
||||
|
||||
// Copyright (c) 2003-2004 Jan Gaspar
|
||||
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
|
||||
#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace cb_details {
|
||||
|
||||
#if BOOST_CB_ENABLE_DEBUG
|
||||
|
||||
class cb_iterator_base;
|
||||
|
||||
/*!
|
||||
\class cb_iterator_registry
|
||||
\brief Registry of valid iterators.
|
||||
|
||||
This class is intended to be a base class of a container.
|
||||
*/
|
||||
class cb_iterator_registry {
|
||||
|
||||
//! Pointer to the chain of valid iterators.
|
||||
mutable const cb_iterator_base* m_iterators;
|
||||
|
||||
public:
|
||||
// Methods
|
||||
|
||||
//! Default constructor.
|
||||
cb_iterator_registry() : m_iterators(0) {}
|
||||
|
||||
//! Register an iterator into the list of valid iterators.
|
||||
/*!
|
||||
\note The method is const in order to register iterators into const containers, too.
|
||||
*/
|
||||
void register_iterator(const cb_iterator_base* it) const; // the implementation is below
|
||||
|
||||
//! Unregister an iterator from the list of valid iterators.
|
||||
/*!
|
||||
\note The method is const in order to unregister iterators from const containers, too.
|
||||
*/
|
||||
void unregister_iterator(const cb_iterator_base* it) const; // the implementation is below
|
||||
|
||||
//! Invalidate all iterators.
|
||||
void invalidate_all_iterators(); // the implementation is below
|
||||
|
||||
//! Invalidate every iterator conforming to the condition.
|
||||
template<class Condition>
|
||||
void invalidate_iterators(const Condition& condition) {
|
||||
const cb_iterator_base* previous = 0;
|
||||
for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) {
|
||||
if (condition(p)) {
|
||||
p->invalidate();
|
||||
remove(p, previous);
|
||||
continue;
|
||||
}
|
||||
previous = p;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
|
||||
//! Remove the current iterator from the iterator chain.
|
||||
void remove(const cb_iterator_base* current,
|
||||
const cb_iterator_base* previous) const; // the implementation is below
|
||||
};
|
||||
|
||||
/*!
|
||||
\class cb_iterator_base
|
||||
\brief Registers/unregisters iterators into the registry of valid iterators.
|
||||
|
||||
This class is intended to be a base class of an iterator.
|
||||
*/
|
||||
class cb_iterator_base {
|
||||
|
||||
private:
|
||||
// Members
|
||||
|
||||
//! Iterator registry.
|
||||
mutable const cb_iterator_registry* m_registry;
|
||||
|
||||
//! Next iterator in the iterator chain.
|
||||
mutable const cb_iterator_base* m_next;
|
||||
|
||||
public:
|
||||
// Construction/destruction
|
||||
|
||||
//! Default constructor.
|
||||
cb_iterator_base() : m_registry(0), m_next(0) {}
|
||||
|
||||
//! Constructor taking the iterator registry as a parameter.
|
||||
cb_iterator_base(const cb_iterator_registry* registry)
|
||||
: m_registry(registry), m_next(0) {
|
||||
register_self();
|
||||
}
|
||||
|
||||
//! Copy constructor.
|
||||
cb_iterator_base(const cb_iterator_base& rhs)
|
||||
: m_registry(rhs.m_registry), m_next(0) {
|
||||
register_self();
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
~cb_iterator_base() { unregister_self(); }
|
||||
|
||||
//! Assign operator.
|
||||
cb_iterator_base& operator = (const cb_iterator_base& rhs) {
|
||||
if (m_registry == rhs.m_registry)
|
||||
return *this;
|
||||
unregister_self();
|
||||
m_registry = rhs.m_registry;
|
||||
register_self();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
//! Is the iterator valid?
|
||||
bool is_valid() const { return m_registry != 0; }
|
||||
|
||||
//! Invalidate the iterator.
|
||||
/*!
|
||||
\note The method is const in order to invalidate const iterators, too.
|
||||
*/
|
||||
void invalidate() const { m_registry = 0; }
|
||||
|
||||
//! Return the next iterator in the iterator chain.
|
||||
const cb_iterator_base* next() const { return m_next; }
|
||||
|
||||
//! Set the next iterator in the iterator chain.
|
||||
/*!
|
||||
\note The method is const in order to set a next iterator to a const iterator, too.
|
||||
*/
|
||||
void set_next(const cb_iterator_base* it) const { m_next = it; }
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
|
||||
//! Register self as a valid iterator.
|
||||
void register_self() {
|
||||
if (m_registry != 0)
|
||||
m_registry->register_iterator(this);
|
||||
}
|
||||
|
||||
//! Unregister self from valid iterators.
|
||||
void unregister_self() {
|
||||
if (m_registry != 0)
|
||||
m_registry->unregister_iterator(this);
|
||||
}
|
||||
};
|
||||
|
||||
inline void cb_iterator_registry::register_iterator(const cb_iterator_base* it) const {
|
||||
it->set_next(m_iterators);
|
||||
m_iterators = it;
|
||||
}
|
||||
|
||||
inline void cb_iterator_registry::unregister_iterator(const cb_iterator_base* it) const {
|
||||
const cb_iterator_base* previous = 0;
|
||||
for (const cb_iterator_base* p = m_iterators; p != it; previous = p, p = p->next());
|
||||
remove(it, previous);
|
||||
}
|
||||
|
||||
inline void cb_iterator_registry::invalidate_all_iterators() {
|
||||
for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next())
|
||||
p->invalidate();
|
||||
m_iterators = 0;
|
||||
}
|
||||
|
||||
inline void cb_iterator_registry::remove(const cb_iterator_base* current,
|
||||
const cb_iterator_base* previous) const {
|
||||
if (previous == 0)
|
||||
m_iterators = m_iterators->next();
|
||||
else
|
||||
previous->set_next(current->next());
|
||||
}
|
||||
|
||||
#else // #if BOOST_CB_ENABLE_DEBUG
|
||||
|
||||
class cb_iterator_registry {
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000)
|
||||
char dummy_; // BCB: by default empty structure has 8 bytes
|
||||
#endif
|
||||
};
|
||||
|
||||
class cb_iterator_base {
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000)
|
||||
char dummy_; // BCB: by default empty structure has 8 bytes
|
||||
#endif
|
||||
|
||||
public:
|
||||
cb_iterator_base() {}
|
||||
cb_iterator_base(const cb_iterator_registry*) {}
|
||||
};
|
||||
|
||||
#endif // #if BOOST_CB_ENABLE_DEBUG
|
||||
|
||||
} // namespace cb_details
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
|
||||
502
include/boost/circular_buffer/details.hpp
Normal file
502
include/boost/circular_buffer/details.hpp
Normal file
@@ -0,0 +1,502 @@
|
||||
// Helper classes and functions for the circular buffer.
|
||||
|
||||
// Copyright (c) 2003-2004 Jan Gaspar
|
||||
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
|
||||
#define BOOST_CIRCULAR_BUFFER_DETAILS_HPP
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace cb_details {
|
||||
|
||||
// The value the uninitialized memory is filled with.
|
||||
const int CB_Unitialized = 0xcc;
|
||||
|
||||
/*!
|
||||
\struct cb_int_iterator_tag
|
||||
\brief Identifying tag for integer types (not for iterators).
|
||||
*/
|
||||
struct cb_int_iterator_tag {
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000)
|
||||
char dummy_; // BCB: by default empty structure has 8 bytes
|
||||
#endif
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_iterator_category
|
||||
\brief Defines iterator category.
|
||||
*/
|
||||
template <bool>
|
||||
struct cb_iterator_category {
|
||||
//! Represents iterators.
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cb_iterator_category<true> {
|
||||
//! Represents integral types (not iterators).
|
||||
typedef cb_int_iterator_tag iterator_category;
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_iterator_category_traits
|
||||
\brief Defines the iterator category tag for the given iterator.
|
||||
*/
|
||||
template <class Iterator>
|
||||
struct cb_iterator_category_traits {
|
||||
//! Iterator category tag type.
|
||||
/*!
|
||||
Depending on the template parameter the <code>tag</code> distinguishes
|
||||
between iterators and non-iterators. If the template parameter
|
||||
is an iterator, the <code>tag</code> is typedef for <code>std::input_iterator_tag</code>.
|
||||
If the parameter is not an iterator, the <code>tag</code> is typedef for
|
||||
<code>cb_int_iterator_tag</code>.
|
||||
*/
|
||||
typedef typename cb_details::cb_iterator_category<
|
||||
is_integral<Iterator>::value>::iterator_category tag;
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_destroy_tag
|
||||
\brief Identifying tag for types which have to be destroyed when replaced.
|
||||
*/
|
||||
struct cb_destroy_tag {
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000)
|
||||
char dummy_; // BCB: by default empty structure has 8 bytes
|
||||
#endif
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_assign_tag
|
||||
\brief Identifying tag for types which do not have to be destroyed when replaced.
|
||||
*/
|
||||
struct cb_assign_tag {
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000)
|
||||
char dummy_; // BCB: by default empty structure has 8 bytes
|
||||
#endif
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_replace_category
|
||||
\brief Defines replace category for the given type.
|
||||
*/
|
||||
template <bool>
|
||||
struct cb_replace_category {
|
||||
//! Represents types which have to be destroyed.
|
||||
typedef cb_destroy_tag replace_category;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cb_replace_category<true> {
|
||||
//! Represents types which do not have to be destroyed.
|
||||
typedef cb_assign_tag replace_category;
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_replace_category_traits
|
||||
\brief Defines the replace category tag for the given type.
|
||||
*/
|
||||
template <class Type>
|
||||
struct cb_replace_category_traits {
|
||||
//! Replace category tag type.
|
||||
/*!
|
||||
Depending on the template parameter the <code>tag</code> distinguishes
|
||||
between types which have to be destroyed (e.g. class) and types which
|
||||
do not have to be (e.g. integral type) when replaced.
|
||||
*/
|
||||
typedef typename cb_details::cb_replace_category<
|
||||
is_scalar<Type>::value>::replace_category tag;
|
||||
};
|
||||
|
||||
template <class Traits> struct cb_nonconst_traits;
|
||||
|
||||
/*!
|
||||
\struct cb_const_traits
|
||||
\brief Defines the data types for a const iterator.
|
||||
\param Traits Defines the basic types.
|
||||
*/
|
||||
template <class Traits>
|
||||
struct cb_const_traits {
|
||||
// Basic types
|
||||
typedef typename Traits::value_type value_type;
|
||||
typedef typename Traits::const_pointer pointer;
|
||||
typedef typename Traits::const_reference reference;
|
||||
typedef typename Traits::size_type size_type;
|
||||
typedef typename Traits::difference_type difference_type;
|
||||
|
||||
// Non-const traits
|
||||
typedef cb_nonconst_traits<Traits> nonconst_traits;
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_nonconst_traits
|
||||
\brief Defines the data types for a non-const iterator.
|
||||
\param Traits Defines the basic types.
|
||||
*/
|
||||
template <class Traits>
|
||||
struct cb_nonconst_traits {
|
||||
// Basic types
|
||||
typedef typename Traits::value_type value_type;
|
||||
typedef typename Traits::pointer pointer;
|
||||
typedef typename Traits::reference reference;
|
||||
typedef typename Traits::size_type size_type;
|
||||
typedef typename Traits::difference_type difference_type;
|
||||
|
||||
// Non-const traits
|
||||
typedef cb_nonconst_traits<Traits> nonconst_traits;
|
||||
};
|
||||
|
||||
/*!
|
||||
\struct cb_helper_pointer
|
||||
\brief Helper pointer used in the cb_iterator.
|
||||
*/
|
||||
template <class Traits0>
|
||||
struct cb_helper_pointer {
|
||||
bool m_end;
|
||||
typename Traits0::pointer m_it;
|
||||
};
|
||||
|
||||
/*!
|
||||
\class cb_iterator
|
||||
\brief Random access iterator for the circular buffer.
|
||||
\param Buff The type of the underlying circular buffer.
|
||||
\param Traits Defines basic iterator types.
|
||||
\note This iterator is not circular. It was designed
|
||||
for iterating from begin() to end() of the circular buffer.
|
||||
*/
|
||||
template <class Buff, class Traits>
|
||||
class cb_iterator :
|
||||
public boost::iterator<
|
||||
std::random_access_iterator_tag,
|
||||
typename Traits::value_type,
|
||||
typename Traits::difference_type,
|
||||
typename Traits::pointer,
|
||||
typename Traits::reference>,
|
||||
public cb_iterator_base
|
||||
{
|
||||
private:
|
||||
// Helper types
|
||||
|
||||
//! Base iterator.
|
||||
typedef boost::iterator<
|
||||
std::random_access_iterator_tag,
|
||||
typename Traits::value_type,
|
||||
typename Traits::difference_type,
|
||||
typename Traits::pointer,
|
||||
typename Traits::reference> base_type;
|
||||
|
||||
//! Non-const iterator.
|
||||
typedef cb_iterator<Buff, typename Traits::nonconst_traits> nonconst_self;
|
||||
|
||||
public:
|
||||
// Basic types
|
||||
|
||||
//! The type of the elements stored in the circular buffer.
|
||||
typedef typename base_type::value_type value_type;
|
||||
|
||||
//! Pointer to the element.
|
||||
typedef typename base_type::pointer pointer;
|
||||
|
||||
//! Reference to the element.
|
||||
typedef typename base_type::reference reference;
|
||||
|
||||
//! Size type.
|
||||
typedef typename Traits::size_type size_type;
|
||||
|
||||
//! Difference type.
|
||||
typedef typename base_type::difference_type difference_type;
|
||||
|
||||
// Member variables
|
||||
|
||||
//! The circular buffer where the iterator points to.
|
||||
const Buff* m_buff;
|
||||
|
||||
//! An internal iterator.
|
||||
pointer m_it;
|
||||
|
||||
// Construction & assignment
|
||||
|
||||
// Default copy constructor.
|
||||
|
||||
//! Default constructor.
|
||||
cb_iterator() : m_buff(0), m_it(0) {}
|
||||
|
||||
//! Copy constructor (used for converting from a non-const to a const iterator).
|
||||
cb_iterator(const nonconst_self& it) : cb_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {}
|
||||
|
||||
//! Internal constructor.
|
||||
/*!
|
||||
\note This constructor is not intended to be used directly by the user.
|
||||
*/
|
||||
cb_iterator(const Buff* cb, const pointer it) : cb_iterator_base(cb), m_buff(cb), m_it(it) {}
|
||||
|
||||
// Assign operator.
|
||||
cb_iterator& operator = (const cb_iterator& it) {
|
||||
if (this == &it)
|
||||
return *this;
|
||||
cb_iterator_base::operator =(it);
|
||||
m_buff = it.m_buff;
|
||||
m_it = it.m_it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Random access iterator methods
|
||||
|
||||
//! Dereferencing operator.
|
||||
reference operator * () const {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end()
|
||||
return *m_it;
|
||||
}
|
||||
|
||||
//! Dereferencing operator.
|
||||
pointer operator -> () const { return &(operator*()); }
|
||||
|
||||
//! Difference operator.
|
||||
difference_type operator - (const cb_iterator& it) const {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers
|
||||
cb_helper_pointer<Traits> lhs = create_helper_pointer(*this);
|
||||
cb_helper_pointer<Traits> rhs = create_helper_pointer(it);
|
||||
if (less(rhs, lhs) && lhs.m_it <= rhs.m_it)
|
||||
return lhs.m_it + m_buff->capacity() - rhs.m_it;
|
||||
if (less(lhs, rhs) && lhs.m_it >= rhs.m_it)
|
||||
return lhs.m_it - m_buff->capacity() - rhs.m_it;
|
||||
return lhs.m_it - rhs.m_it;
|
||||
}
|
||||
|
||||
//! Increment operator (prefix).
|
||||
cb_iterator& operator ++ () {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end()
|
||||
m_buff->increment(m_it);
|
||||
if (m_it == m_buff->m_last)
|
||||
m_it = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Increment operator (postfix).
|
||||
cb_iterator operator ++ (int) {
|
||||
cb_iterator<Buff, Traits> tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//! Decrement operator (prefix).
|
||||
cb_iterator& operator -- () {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin()
|
||||
if (m_it == 0)
|
||||
m_it = m_buff->m_last;
|
||||
m_buff->decrement(m_it);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Decrement operator (postfix).
|
||||
cb_iterator operator -- (int) {
|
||||
cb_iterator<Buff, Traits> tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//! Iterator addition.
|
||||
cb_iterator& operator += (difference_type n) {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
if (n > 0) {
|
||||
BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n
|
||||
m_it = m_buff->add(m_it, n);
|
||||
if (m_it == m_buff->m_last)
|
||||
m_it = 0;
|
||||
} else if (n < 0) {
|
||||
*this -= -n;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Iterator addition.
|
||||
cb_iterator operator + (difference_type n) const { return cb_iterator<Buff, Traits>(*this) += n; }
|
||||
|
||||
//! Iterator subtraction.
|
||||
cb_iterator& operator -= (difference_type n) {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
if (n > 0) {
|
||||
BOOST_CB_ASSERT(m_buff->begin() - *this <= -n); // check for too large n
|
||||
m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n);
|
||||
} else if (n < 0) {
|
||||
*this += -n;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Iterator subtraction.
|
||||
cb_iterator operator - (difference_type n) const { return cb_iterator<Buff, Traits>(*this) -= n; }
|
||||
|
||||
//! Element access operator.
|
||||
reference operator [] (difference_type n) const { return *(*this + n); }
|
||||
|
||||
// Equality & comparison
|
||||
|
||||
//! Equality.
|
||||
template <class Traits0>
|
||||
bool operator == (const cb_iterator<Buff, Traits0>& it) const {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers
|
||||
return m_it == it.m_it;
|
||||
}
|
||||
|
||||
//! Inequality.
|
||||
template <class Traits0>
|
||||
bool operator != (const cb_iterator<Buff, Traits0>& it) const {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers
|
||||
return m_it != it.m_it;
|
||||
}
|
||||
|
||||
//! Less.
|
||||
template <class Traits0>
|
||||
bool operator < (const cb_iterator<Buff, Traits0>& it) const {
|
||||
BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator
|
||||
BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers
|
||||
return less(create_helper_pointer(*this), create_helper_pointer(it));
|
||||
}
|
||||
|
||||
//! Greater.
|
||||
template <class Traits0>
|
||||
bool operator > (const cb_iterator<Buff, Traits0>& it) const { return it < *this; }
|
||||
|
||||
//! Less or equal.
|
||||
template <class Traits0>
|
||||
bool operator <= (const cb_iterator<Buff, Traits0>& it) const { return !(it < *this); }
|
||||
|
||||
//! Greater or equal.
|
||||
template <class Traits0>
|
||||
bool operator >= (const cb_iterator<Buff, Traits0>& it) const { return !(*this < it); }
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
|
||||
//! Create helper pointer.
|
||||
template <class Traits0>
|
||||
cb_helper_pointer<Traits0> create_helper_pointer(const cb_iterator<Buff, Traits0>& it) const {
|
||||
cb_helper_pointer<Traits0> helper;
|
||||
helper.m_end = (it.m_it == 0);
|
||||
helper.m_it = helper.m_end ? m_buff->m_last : it.m_it;
|
||||
return helper;
|
||||
}
|
||||
|
||||
//! Compare two pointers.
|
||||
/*!
|
||||
\return 1 if p1 is greater than p2.
|
||||
\return 0 if p1 is equal to p2.
|
||||
\return -1 if p1 is lower than p2.
|
||||
*/
|
||||
template <class Pointer0, class Pointer1>
|
||||
static difference_type compare(Pointer0 p1, Pointer1 p2) {
|
||||
return p1 < p2 ? -1 : (p1 > p2 ? 1 : 0);
|
||||
}
|
||||
|
||||
//! Less.
|
||||
template <class InternalIterator0, class InternalIterator1>
|
||||
bool less(const InternalIterator0& lhs, const InternalIterator1& rhs) const {
|
||||
switch (compare(lhs.m_it, m_buff->m_first)) {
|
||||
case -1:
|
||||
switch (compare(rhs.m_it, m_buff->m_first)) {
|
||||
case -1: return lhs.m_it < rhs.m_it;
|
||||
case 0: return rhs.m_end;
|
||||
case 1: return false;
|
||||
}
|
||||
case 0:
|
||||
switch (compare(rhs.m_it, m_buff->m_first)) {
|
||||
case -1: return !lhs.m_end;
|
||||
case 0: return !lhs.m_end && rhs.m_end;
|
||||
case 1: return !lhs.m_end;
|
||||
}
|
||||
case 1:
|
||||
switch (compare(rhs.m_it, m_buff->m_first)) {
|
||||
case -1: return true;
|
||||
case 0: return rhs.m_end;
|
||||
case 1: return lhs.m_it < rhs.m_it;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//! Iterator addition.
|
||||
template <class Buff, class Traits>
|
||||
inline cb_iterator<Buff, Traits>
|
||||
operator + (typename Traits::difference_type n, const cb_iterator<Buff, Traits>& it) {
|
||||
return it + n;
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
|
||||
|
||||
//! Iterator category.
|
||||
template <class Buff, class Traits>
|
||||
inline std::random_access_iterator_tag iterator_category(const cb_iterator<Buff, Traits>&) {
|
||||
return std::random_access_iterator_tag();
|
||||
}
|
||||
|
||||
//! The type of the elements stored in the circular buffer.
|
||||
template <class Buff, class Traits>
|
||||
inline typename Traits::value_type* value_type(const cb_iterator<Buff, Traits>&) { return 0; }
|
||||
|
||||
//! Distance type.
|
||||
template <class Buff, class Traits>
|
||||
inline typename Traits::difference_type* distance_type(const cb_iterator<Buff, Traits>&) { return 0; }
|
||||
|
||||
#endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
|
||||
|
||||
/*!
|
||||
\fn FwdIterator uninitialized_copy(InputIterator first, InputIterator last, FwdIterator dest, Alloc& alloc)
|
||||
\brief Equivalent of <code>std::uninitialized_copy</code> with allocator.
|
||||
*/
|
||||
template<class InputIterator, class FwdIterator, class Alloc>
|
||||
inline FwdIterator uninitialized_copy(InputIterator first, InputIterator last, FwdIterator dest, Alloc& alloc) {
|
||||
FwdIterator next = dest;
|
||||
BOOST_CB_TRY
|
||||
for (; first != last; ++first, ++dest)
|
||||
alloc.construct(dest, *first);
|
||||
BOOST_CB_UNWIND(
|
||||
for (; next != dest; ++next)
|
||||
alloc.destroy(next);
|
||||
)
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void uninitialized_fill_n(FwdIterator first, Diff n, const T& item, Alloc& alloc)
|
||||
\brief Equivalent of <code>std::uninitialized_fill_n</code> with allocator.
|
||||
*/
|
||||
template<class FwdIterator, class Diff, class T, class Alloc>
|
||||
inline void uninitialized_fill_n(FwdIterator first, Diff n, const T& item, Alloc& alloc) {
|
||||
FwdIterator next = first;
|
||||
BOOST_CB_TRY
|
||||
for (; n > 0; ++first, --n)
|
||||
alloc.construct(first, item);
|
||||
BOOST_CB_UNWIND(
|
||||
for (; next != first; ++next)
|
||||
alloc.destroy(next);
|
||||
)
|
||||
}
|
||||
|
||||
} // namespace cb_details
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
|
||||
41
include/boost/circular_buffer_fwd.hpp
Normal file
41
include/boost/circular_buffer_fwd.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Forward declaration of the circular buffer and its adaptor.
|
||||
|
||||
// Copyright (c) 2003-2004 Jan Gaspar
|
||||
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP)
|
||||
#define BOOST_CIRCULAR_BUFFER_FWD_HPP
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if !defined(BOOST_NO_STD_ALLOCATOR)
|
||||
#include <memory>
|
||||
#else
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_NO_STD_ALLOCATOR)
|
||||
#define BOOST_CB_DEFAULT_ALLOCATOR(T) std::allocator<T>
|
||||
#else
|
||||
#define BOOST_CB_DEFAULT_ALLOCATOR(T) BOOST_DEDUCED_TYPENAME std::vector<T>::allocator_type
|
||||
#endif
|
||||
|
||||
template <class T, class Alloc = BOOST_CB_DEFAULT_ALLOCATOR(T)>
|
||||
class circular_buffer;
|
||||
|
||||
template <class T, class Alloc = BOOST_CB_DEFAULT_ALLOCATOR(T)>
|
||||
class circular_buffer_space_optimized;
|
||||
|
||||
#undef BOOST_CB_DEFAULT_ALLOCATOR
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP)
|
||||
Reference in New Issue
Block a user