390 lines
13 KiB
C++
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ä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 */
|
|
|