Initial revision.

[SVN r2447]
This commit is contained in:
Jan Gaspar
2005-01-19 09:45:55 +00:00
parent b683dba9be
commit d8021d4ff2
34 changed files with 13000 additions and 0 deletions

View 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)

View 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)

File diff suppressed because it is too large Load Diff

View 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)

View 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)

View 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)