#pragma once #include /** * A simple ring buffer structure */ template struct Ringbuf { Ringbuf() : m_head(0), m_tail(0) {} /** * Clears the buffer's contents */ void clear() { m_head = 0; m_tail = 0; } /** * Returns the value of the next available item, if available */ T peek(int offset) const { const int nextHead = (m_head + offset) % Size; return m_items[nextHead]; } /** * Removes and returns the next available item, if any. * * @return false if no data is available, true otherwise */ bool take(T& dest) { if (m_head == m_tail) { return false; } const int cur = m_head; const int nextHead = (m_head + 1) % Size; m_head = nextHead; dest = m_items[cur]; return true; } /** * Inserts an item into the buffer. If the buffer is full, the oldest item * is overwritten. */ void insert(const T& src) { const int cur = m_tail; const int nextTail = (m_tail + 1) % Size; if (nextTail == m_head) { return; } else { m_tail = nextTail; } m_items[cur] = src; } /** * Consumes the entire buffer and writes it to the given array. */ size_t write(T(&dest)[Size]) { int i = 0; size_t ret = 0; while(take(dest[i])) { i++; ret += sizeof(T); } return ret; } /** * Consumes the entire buffer and writes it to the given output */ size_t write(Print& stream) { T val; size_t ret = 0; while(take(val)) { stream.write(val); } return ret; } /** * Returns how many items are available in the buffer */ size_t size() { if (m_tail > m_head) { return m_tail - m_head; } else if (m_tail == m_head) { return 0; } return m_tail + (Size - m_head); } private: int m_head = 0; int m_tail = 0; std::array m_items; };