#ifndef CORE_RINGBUFFER_HPP #define CORE_RINGBUFFER_HPP #include #include "core/utils/AlignedData.hpp" #include "core/utils/ArrayString.hpp" namespace Core { template class RingBuffer final { AlignedType data[N]; size_t writeIndex = 0; size_t readIndex = 0; size_t values = 0; public: RingBuffer() = default; RingBuffer(const RingBuffer& other) { copy(other); } RingBuffer(RingBuffer&& other) { move(Core::move(other)); other.clear(); } ~RingBuffer() { clear(); } RingBuffer& operator=(const RingBuffer& other) { if(&other != this) { clear(); copy(other); } return *this; } RingBuffer& operator=(RingBuffer&& other) { if(&other != this) { clear(); move(Core::move(other)); other.clear(); } return *this; } template T* put(Args&&... args) { if(getLength() >= N) { return nullptr; } T* t = new(data + writeIndex) T(Core::forward(args)...); writeIndex = (writeIndex + 1) % N; values++; return t; } template RingBuffer& add(Args&&... args) { put(Core::forward(args)...); return *this; } T& operator[](size_t index) { return reinterpret_cast(data)[(index + readIndex) % N]; } const T& operator[](size_t index) const { return reinterpret_cast(data)[(index + readIndex) % N]; } size_t getLength() const { return values; } bool canRemove() const { return getLength() > 0; } void clear() { for(size_t i = 0; i < getLength(); i++) { (*this)[i].~T(); } writeIndex = 0; readIndex = 0; values = 0; } void remove() { assert(canRemove()); values--; (*this)[0].~T(); readIndex = (readIndex + 1) % N; } void toString(BufferString& s) const { s.append("["); size_t end = getLength(); if(end > 0) { end--; for(size_t i = 0; i < end; i++) { s.append((*this)[i]).append(", "); } s.append((*this)[end]); } s.append("]"); } private: void copy(const RingBuffer& other) { for(size_t i = 0; i < other.getLength(); i++) { add(other[i]); } } void move(RingBuffer&& other) { for(size_t i = 0; i < other.getLength(); i++) { add(Core::move(other[i])); } } }; } #endif