Files
scandocs/uni/masterarbeit/source/moversight/common/container/CircularBuffer.h
2014-06-30 13:58:10 +02:00

390 lines
13 KiB
C++

/*
* File: CircularBuffer.h
* Author: jgaebler
*
* Created on October 26, 2012, 1:57 PM
*/
#pragma once
#ifndef CIRCULARBUFFER_H
#define CIRCULARBUFFER_H
#include <boost/circular_buffer.hpp>
namespace ubeeme {
namespace moversight {
/**
* @class CircularBuffer
* @brief Provides a circular buffer for objects.
*
* Provides a circular buffer for objects. The circular buffer
* should not be used for storing pointers to dynamically allocated objects.
* When a circular buffer becomes full, further insertion will overwrite
* the stored pointers - resulting in a memory leak. One recommend alternative
* is the use of smart pointers.
* @ingroup Moversight
* @author Jan G&auml;bler
*/
template <typename T>
class CircularBuffer {
public:
CircularBuffer(size_t size);
CircularBuffer(const CircularBuffer & orig);
virtual ~CircularBuffer();
void add(const T & t);
void clear();
size_t size() const;
size_t maxSize() const;
bool isEmpty() const;
bool isFull() const;
size_t getReserve() const;
void resetCapacity(size_t new_capacity);
size_t getCapacity() const;
void setCapacity(size_t new_capacity);
void resize(size_t new_size);
void pop();
T & get(size_t index);
T const & get(size_t index) const;
protected:
typedef boost::circular_buffer<T> CBuffer;
CBuffer buffer;
public:
typedef typename CBuffer::iterator iterator_type;
typedef typename CBuffer::const_iterator const_iterator_type;
iterator_type erase(iterator_type pos);
iterator_type erase(iterator_type first, iterator_type last);
iterator_type rerase(iterator_type pos);
iterator_type rerase(iterator_type first, iterator_type last);
iterator_type begin();
iterator_type end();
const_iterator_type begin() const;
const_iterator_type end() const;
};
template <typename T>
std::ostream operator<<(std::ostream & s, typename CircularBuffer<T>::iterator_type it){
return s<<*it;
}
/**
* @brief Constructor
* @param size the size of the circular buffer.
*/
template <typename T>
CircularBuffer<T>::CircularBuffer(size_t size) : buffer(size) {
}
/**
* @brief Copy constructor
* @param orig the list to copy
*/
template <typename T>
CircularBuffer<T>::CircularBuffer(const CircularBuffer & orig) : buffer(orig.buffer) {
}
/**
* @brief Destructor
*/
template <typename T>
CircularBuffer<T>::~CircularBuffer() {
}
/**
* @brief Clears the buffer
*/
template <typename T>
void
CircularBuffer<T>::clear() {
buffer.clear();
}
/**
* @brief Adds a object to the buffer
* @param t the object to add
* @return This list.
*/
template <typename T>
void
CircularBuffer<T>::add(const T & t) {
buffer.push_back(t);
}
/**
* @brief Get the number of elements currently stored in the circular buffer.
* @returns The number of elements currently stored in the buffer.
*/
template <typename T>
size_t
CircularBuffer<T>::size() const {
return buffer.size();
}
/**
* @brief Get the largest possible size or capacity of the circular buffer.
* @returns The largest possible size or capacity of the circular buffer.
*/
template <typename T>
size_t
CircularBuffer<T>::maxSize() const {
return buffer.max_size();
}
/**
* @brief Is the circular buffer empty?
* @returns True if there are no elements stored in the buffer; False otherwise.
*/
template <typename T>
bool
CircularBuffer<T>::isEmpty() const {
return buffer.empty();
}
/**
* @brief Is the circular buffer full?
* @returns True if the number of elements stored in the buffer equals the capacity of the buffer; false otherwise.
*/
template <typename T>
bool
CircularBuffer<T>::isFull() const {
return buffer.full();
}
/**
* @brief Get the maximum number of elements which can be inserted into
* the buffer without overwriting any of already stored elements.
* @returns getCapacity() - size()
*/
template <typename T>
size_t
CircularBuffer<T>::getReserve() const {
return buffer.reserve();
}
/**
* @brief Change the capacity of the buffer.
* Effect: getCapacity() == new_capacity && size() <= new_capacity
* If the current number of elements stored in the buffer is greater
* than the desired new capacity then number of [size() - new_capacity]
* first elements will be removed and the new size will be equal to new_capacity.
* @param new_capacity The new capacity.
* @throw An allocation error if memory is exhausted.
*/
template <typename T>
void
CircularBuffer<T>::resetCapacity(size_t new_capacity) {
buffer.rset_capacity(new_capacity);
}
/**
* @brief Get the capacity of the buffer.
* @returns The maximum number of elements which can be stored in the buffer.
*/
template <typename T>
size_t
CircularBuffer<T>::getCapacity() const {
return buffer.capacity();
}
/**
* @brief Change the capacity of the circular_buffer.
* Effect: getCapacity() == new_capacity && size() <= new_capacity
* If the current number of elements stored in the buffer is greater
* than the desired new capacity then number of [size() - new_capacity]
* last elements will be removed and the new size will be equal to new_capacity.
*
* @param new_capacity The new capacity.
* @throw An allocation error if memory is exhausted
*/
template <typename T>
void
CircularBuffer<T>::setCapacity(size_t new_capacity) {
buffer.set_capacity(new_capacity);
}
/**
* @brief Change the size of the buffer.
* Effect: size() == new_size && getCapacity() >= new_size
*
* If the new size is greater than the current size, copies of item will
* be inserted at the back of the of the buffer in order to
* achieve the desired size. In the case the resulting size exceeds the
* current capacity the capacity will be set to new_size.
*
* If the current number of elements stored in the buffer is greater
* than the desired new size then number of [size() - new_size] last
* elements will be removed. (The capacity will remain unchanged.)
*
* @param new_size The new size.
* @throw An allocation error if memory is exhausted.
**/
template <typename T>
void
CircularBuffer<T>::resize(size_t new_size) {
buffer.resize(new_size);
}
/**
* @brief Pops the first element from the buffer.
*/
template <typename T>
void
CircularBuffer<T>::pop() {
buffer.pop_front();
}
/**
* @brief Returns the object from the buffer, which is located at the given index.
* @throws IndexOutOfBounceException if the given index larger than the current size of the buffer
* @param index the index of the element to return
* @return the desired element
*/
template <typename T>
T &
CircularBuffer<T>::get(size_t index) {
if (index > buffer.size()) {
throw IndexOutOfBounceException("index out of bounce");
}//End if
return buffer[index];
}
/**
* @brief Returns the object from the buffer, which is located at the given index.
* @throws IndexOutOfBounceException if the given index larger than the current size of the buffer
* @param index the index of the element to return
* @return the desired element
*/
template <typename T>
T const &
CircularBuffer<T>::get(size_t index) const {
if (index > buffer.size()) {
throw IndexOutOfBounceException("index out of bounce");
}//End if
return buffer[index];
}
/**
* @brief Get the iterator pointing to the beginning of the buffer.
* @return A random access iterator pointing to the first element of the
* buffer. If the buffer is empty it returns an iterator equal to the
* one returned by end().
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::begin() {
return buffer.begin();
}
/**
* @brief Get the const iterator pointing to the beginning of the buffer.
* @return A const random access iterator pointing to the first element of the
* buffer. If the buffer is empty it returns an iterator equal to the
* one returned by end() const.
*/
template<typename T>
typename CircularBuffer<T>::const_iterator_type
CircularBuffer<T>::begin() const {
return buffer.begin();
}
/**
* @brief Get the iterator pointing to the end of the buffer.
* @return A random access iterator pointing to the element "one behind"
* the last element of the buffer. If the buffer is empty it returns an
* iterator equal to the one returned by begin().
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::end() {
return buffer.end();
}
/**
* @brief Get the const iterator pointing to the end of the buffer.
* @return A const random access iterator pointing to the element "one behind"
* the last element of the buffer. If the buffer is empty it returns an
* iterator equal to the one returned by begin() const.
*/
template<typename T>
typename CircularBuffer<T>::const_iterator_type
CircularBuffer<T>::end() const {
return buffer.end();
}
/**
* @brief Remove an element at the specified position. Precondition:
* pos is a valid iterator pointing to the buffer (but not an end()).
* @param pos An iterator pointing at the element to be removed.
* @return Iterator to the first element remaining beyond the removed
* element or end() if no such element exists.
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::erase(iterator_type pos){
return buffer.erase(pos);
}
/**
* @brief Erase the range [first, last). Precondition: Valid range [first, last).
* @param first The beginning of the range to be removed.
* @param last The end of the range to be removed.
* @return Iterator to the first element remaining beyond the removed
* elements or end() if no such element exists.
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::erase(iterator_type first, iterator_type last){
return buffer.erase(first, last);
}
/**
* @brief Remove an element at the specified position. Precondition:
* pos is a valid iterator pointing to the buffer (but not an end()).
* @param pos An iterator pointing at the element to be removed.
* @return Iterator to the first element remaining in front of the
* removed element or begin() if no such element exists.
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::rerase(iterator_type pos){
return buffer.rerase(pos);
}
/**
* @brief Erase the range [first, last). Precondition: Valid range [first, last).
* @param first The beginning of the range to be removed.
* @param last The end of the range to be removed.
* @return Iterator to the first element remaining in front of the
* removed elements or begin() if no such element exists.
*/
template<typename T>
typename CircularBuffer<T>::iterator_type
CircularBuffer<T>::rerase(iterator_type first, iterator_type last){
return buffer.rerase(first, last);
}
}
}
#endif /* CIRCULARBUFFER_H */