#pragma once // A simple ringbuffer holding Size elements of type T template class RingBuffer { protected: T buf_[Size]; uint8_t head_{0}, tail_{0}; public: inline uint8_t nextPosition(uint8_t position) { return (position + 1) % Size; } inline uint8_t prevPosition(uint8_t position) { if (position == 0) { return Size - 1; } return position - 1; } inline bool enqueue(const T &item) { static_assert(Size > 1, "RingBuffer size must be > 1"); uint8_t next = nextPosition(head_); if (next == tail_) { // Full return false; } buf_[head_] = item; head_ = next; return true; } inline bool get(T &dest, bool commit = true) { auto tail = tail_; if (tail == head_) { // No more data return false; } dest = buf_[tail]; tail = nextPosition(tail); if (commit) { tail_ = tail; } return true; } inline bool empty() const { return head_ == tail_; } inline uint8_t size() const { int diff = head_ - tail_; if (diff >= 0) { return diff; } return Size + diff; } inline T& front() { return buf_[tail_]; } inline bool peek(T &item) { return get(item, false); } };