98 lines
2.0 KiB
C++
98 lines
2.0 KiB
C++
#pragma once
|
|
#include <array>
|
|
|
|
/**
|
|
* A simple ring buffer structure
|
|
*/
|
|
template<typename T, int Size>
|
|
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;
|
|
}
|
|
return m_tail + (Size - m_head);
|
|
}
|
|
private:
|
|
int m_head = 0;
|
|
int m_tail = 0;
|
|
std::array<T, Size> m_items;
|
|
};
|
|
|