#ifndef GLTB_RINGBUFFER_H #define GLTB_RINGBUFFER_H #include #include "GLTB/referencedobject.h" namespace gltb { template class RingBuffer : public ReferencedObject { public: RingBuffer(size_t size); ~RingBuffer(); void append(const T *data, size_t length); void append(const std::vector data); void append(const T &element); size_t size() const { return bufferSize; } size_t validElemens() const { return numValidElements; } T &operator[] (size_t index); void clear(); private: T *buffer; size_t bufferSize; size_t offset; size_t numValidElements; }; template RingBuffer::RingBuffer(size_t size) { buffer = new T[size]; } template RingBuffer::~RingBuffer() { delete[] buffer; } template void RingBuffer::append(const T *data, size_t length) { // handle length > bufferSize by copying only the bufferSize latest elements if(length >= bufferSize) { offset = 0; data += (length - bufferSize); for(size_t i = 0; i < bufferSize; i++) { buffer[i] = data[i]; } return; } // copy data into ring buffer (split if required) for(size_t i = 0; i < length; i++) { buffer[(offset + i) % bufferSize] = data[i]; } offset = (offset + length) % bufferSize; numValidElements = std::min(bufferSize, numValidElements + length); } template void RingBuffer::append(std::vector data) { append(data.data(), data.size()); } template void RingBuffer::append(const T &element) { append(std::addressof(element), 1); } template T &RingBuffer::operator[] (size_t index) { return buffer[(offset + index) % bufferSize]; } template void RingBuffer::clear() { offset = 0; numValidElements = 0; } } #endif