// Implementation of the circular buffer adaptor.
// Copyright (c) 2003
// Jan Gaspar, Whitestein Technologies
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
#if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
#define BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP
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@yahoo.com">Jan Gaspar</a>
\version 1.0
\date 2003
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>::operator[];
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;
private:
// Member variables
//! The capacity of the optimized circular buffer.
size_type m_final_capacity;
public:
// Overridden
//! See the circular_buffer source documentation.
bool full() const { return size() == capacity(); }
//! See the circular_buffer source documentation.
size_type capacity() const { return m_final_capacity; }
//! See the circular_buffer source documentation.
void set_capacity(size_type new_capacity) {
if (m_final_capacity > new_capacity)
circular_buffer<T, Alloc>::set_capacity(new_capacity);
m_final_capacity = new_capacity;
}
//! See the circular_buffer source documentation.
void resize(size_type new_size, param_value_type item = T()) {
if (new_size > size()) {
if (new_size > capacity())
m_final_capacity = new_size;
insert(end(), new_size - size(), item);
} else {
erase(begin(), end() - new_size);
}
}
//! See the circular_buffer source documentation.
explicit circular_buffer_space_optimized(
size_type capacity,
const allocator_type& a = allocator_type())
: circular_buffer<T, Alloc>(0, a), m_final_capacity(capacity) {}
//! See the circular_buffer source documentation.
circular_buffer_space_optimized(
size_type capacity,
param_value_type item,
const allocator_type& a = allocator_type())
: circular_buffer<T, Alloc>(capacity, item, a), m_final_capacity(capacity) {}
// Default copy constructor
//! See the circular_buffer source documentation.
template <class InputIterator>
circular_buffer_space_optimized(
size_type capacity,
InputIterator first,
InputIterator last,
const allocator_type& a = allocator_type())
: circular_buffer<T, Alloc>(init_capacity(capacity, first, last), first, last, a)
, m_final_capacity(capacity) {}
// Default destructor
// Default assign operator
//! See the circular_buffer source documentation.
void assign(size_type n, param_value_type item) {
if (n > m_final_capacity)
m_final_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_final_capacity)
m_final_capacity = capacity;
}
//! See the circular_buffer source documentation.
void swap(circular_buffer_space_optimized& cb) {
std::swap(m_final_capacity, cb.m_final_capacity);
circular_buffer<T, Alloc>::swap(cb);
}
//! See the circular_buffer source documentation.
void push_back(param_value_type item) {
check_low_capacity();
circular_buffer<T, Alloc>::push_back(item);
}
//! See the circular_buffer source documentation.
void push_back() { push_back(value_type()); }
//! See the circular_buffer source documentation.
void push_front(param_value_type item) {
check_low_capacity();
circular_buffer<T, Alloc>::push_front(item);
}
//! See the circular_buffer source documentation.
void push_front() { push_front(value_type()); }
//! See the circular_buffer source documentation.
void pop_back() {
circular_buffer<T, Alloc>::pop_back();
check_high_capacity();
}
//! See the circular_buffer source documentation.
void pop_front() {
circular_buffer<T, Alloc>::pop_front();
check_high_capacity();
}
//! See the circular_buffer source documentation.
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.
iterator insert(iterator pos) { return insert(pos, value_type()); }
//! See the circular_buffer source documentation.
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.
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.
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.
iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
//! See the circular_buffer source documentation.
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.
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.
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.
iterator erase(iterator first, iterator last) {
iterator it = circular_buffer<T, Alloc>::erase(first, last);
size_type index = it - begin();
circular_buffer<T, Alloc>::set_capacity(size());
return begin() + index;
}
//! See the circular_buffer source documentation.
void clear() { circular_buffer<T, Alloc>::set_capacity(0); }
private:
// Helper methods
//! Check for low capacity.
/*
\post If the capacity is low it will be increased.
*/
void check_low_capacity() {
if (circular_buffer<T, Alloc>::full() && size() < m_final_capacity) {
size_type new_capacity = empty() ? 1 : size() << 1; // (size * 2)
if (new_capacity > m_final_capacity)
new_capacity = m_final_capacity;
circular_buffer<T, Alloc>::set_capacity(new_capacity);
}
}
//! Check for low capacity.
/*
\post If the capacity is low it will be increased.
*/
void check_low_capacity(size_type n) {
size_type new_capacity = size() + n;
if (new_capacity > m_final_capacity)
new_capacity = m_final_capacity;
if (new_capacity > circular_buffer<T, Alloc>::capacity())
circular_buffer<T, Alloc>::set_capacity(new_capacity);
}
//! 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() >> 1; // (capacity / 2)
if (new_capacity >= size())
circular_buffer<T, Alloc>::set_capacity(new_capacity);
}
//! Determine the initial capacity.
template <class InputIterator>
static size_type init_capacity(size_type capacity, InputIterator first, InputIterator last) {
size_type diff = std::distance(first, last);
return diff > capacity ? capacity : diff;
}
//! 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) || defined(BOOST_MSVC)
//! 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) || defined(BOOST_MSVC)
} // namespace boost
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
syntax highlighted by Code2HTML, v. 0.9.1