blob: 551f48902e9dca4654ffae23e086ac606b2c09d7 [file]
/*******************************************************************************
* Copyright (c) 2016 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* CONTRIBUTORS:
* Jan Belle (initial contribution)
*
*******************************************************************************/
#ifndef SRC_COMMON_CONTAINERS_StaticDeque_H_
#define SRC_COMMON_CONTAINERS_StaticDeque_H_
#include <stdint.h>
/**
* Implementation of a double ended queue with a circular buffer
* The type T must implement the copy constructor
*/
template<class T, int maxSize>
class StaticDeque {
public:
StaticDeque(void) : m_first(0), m_size(0) {}
StaticDeque(const StaticDeque<T, maxSize>& copy) : m_first(0), m_size(0) {
operator=(copy);
}
~StaticDeque(void) {
reset();
}
StaticDeque<T, maxSize>& operator=(const StaticDeque<T, maxSize>& copy) {
reset();
for(int i = 0; i < copy.m_size; ++i) {
push_back(copy[i]);
}
return *this;
}
// Returns the number of objects
int size(void) const { return m_size; }
bool empty(void) const { return !m_size; }
// Returns a reference to an arbitrary object at the specified position
T& operator[] (int position) const {
// TODO JB: Handle position out of bounds exception
return (T&) m_memory[(m_first + position * sizeof(T)) % (sizeof(T) * maxSize)];
}
// Copies the object and stores it at the front
void push_front(const T& object) {
// TODO JB: Handle out of memory exception
if(m_size < maxSize) {
++m_size;
m_first = (m_first + (maxSize - 1) * sizeof(T)) % (sizeof(T) * maxSize);
new (&operator[](0)) T(object);
}
}
// Copies the object and stores it at the end
void push_back(const T& object) {
// TODO JB: Handle out of memory exception
if(m_size < maxSize) {
++m_size;
new (&operator[](m_size - 1)) T(object);
}
}
// Removes the first object
void pop_front(void) {
// TODO JB: Handle deque empty exception
if(m_size > 0) {
operator[](0).~T();
m_first = (m_first + sizeof(T)) % (sizeof(T) * maxSize);
--m_size;
}
}
// Removes the last element
void pop_back(void) {
// TODO JB: Handle deque empty exception
if(m_size > 0) {
operator[](m_size - 1).~T();
--m_size;
}
}
// Returns a reference to the first object
T& front(void) const {
return operator[](0);
}
// Returns a reference to the last object
T& back(void) const {
return operator[](m_size - 1);
}
private:
uint8_t m_memory[sizeof(T) * maxSize]; // array for the objects
int m_first; // index of the first object
int m_size; // current size of the queue
void reset(void) {
while(m_size > 0) {
pop_back();
}
}
};
#endif /* SRC_COMMON_CONTAINERS_StaticDeque_H_ */