123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- #ifndef CORE_RINGBUFFER_HPP
- #define CORE_RINGBUFFER_HPP
- #include "utils/AlignedData.hpp"
- #include "utils/ArrayString.hpp"
- namespace Core {
- template<typename T, int N>
- class RingBuffer final {
- static_assert(N > 0, "RingBuffer size must be positive");
- AlignedType<T> data[static_cast<unsigned int>(N)];
- int writeIndex;
- int readIndex;
- int values;
- public:
- RingBuffer() : writeIndex(0), readIndex(0), values(0) {
- }
- RingBuffer(const RingBuffer& other) : RingBuffer() {
- copy(other);
- }
- RingBuffer(RingBuffer&& other) : RingBuffer() {
- 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<typename... Args>
- check_return Error put(T*& t, Args&&... args) {
- if(getLength() >= N) {
- return Error::CAPACITY_REACHED;
- }
- t = new(data + writeIndex) T(Core::forward<Args>(args)...);
- writeIndex = (writeIndex + 1) % N;
- values++;
- return Error::NONE;
- }
- template<typename... Args>
- check_return Error add(Args&&... args) {
- T* t = nullptr;
- return put(t, Core::forward<Args>(args)...);
- }
- T& operator[](int index) {
- return reinterpret_cast<T*>(data)[(index + readIndex) % N];
- }
- const T& operator[](int index) const {
- return reinterpret_cast<const T*>(data)[(index + readIndex) % N];
- }
- int getLength() const {
- return values;
- }
- bool canRemove() const {
- return getLength() > 0;
- }
- void clear() {
- for(int i = 0; i < getLength(); i++) {
- (*this)[i].~T();
- }
- writeIndex = 0;
- readIndex = 0;
- values = 0;
- }
- check_return Error remove() {
- if(!canRemove()) {
- return Error::INVALID_STATE;
- }
- values--;
- (*this)[0].~T();
- readIndex = (readIndex + 1) % N;
- return Error::NONE;
- }
- template<typename String>
- check_return Error toString(String& s) const {
- CORE_RETURN_ERROR(s.append("["));
- for(int i = 0; i < getLength() - 1; i++) {
- CORE_RETURN_ERROR(s.append((*this)[i]));
- CORE_RETURN_ERROR(s.append(", "));
- }
- if(getLength() > 0) {
- CORE_RETURN_ERROR(s.append((*this)[getLength() - 1]));
- }
- return s.append("]");
- }
- private:
- void copy(const RingBuffer& other) {
- for(int i = 0; i < other.getLength(); i++) {
- (void)add(other[i]);
- }
- }
- void move(RingBuffer&& other) {
- for(int i = 0; i < other.getLength(); i++) {
- (void)add(Core::move(other[i]));
- }
- }
- };
- }
- #endif
|