Files
empty/include/lib/ringbuffer.h
2025-10-26 15:21:48 +01:00

90 lines
2.0 KiB
C

#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
/**
* \brief Ringbuffer Datenstruktur
* \file ringbuffer.h
*
* Diese Datei ist eine Hilfestellung für Aufgabe 2.
* Sie erspart euch den Aufwand, selber einen Ringbuffer zu implementieren.
*/
struct ring_buff {
unsigned int head;
unsigned int tail;
unsigned int size;
unsigned int mask;
char *buffer;
};
/**
* \brief Überprüft ob eine positive Zahl eine Zweierpotenz ist
*
* Beispiel: (0b100 & 0b011) == 0b000.
*/
#define is_power_of_two(val) (((val) & ((val) - 1)) == 0)
/**
* \brief Macro um einen Ringbuffer zu erstellen
* \param name Bezeichnung des Buffers
* \param size Größe des Buffers
*
*/
#define create_ringbuffer(name, size) \
static_assert((size) >= 1, "Size of Ringbuffer has to be at least 1"); \
static_assert(is_power_of_two(size), "Size of Ringbuffer has to be a power of 2"); \
static char _b_##name[size]; \
static struct ring_buff _##name = { 0, 0, (size), (size) - 1, _b_##name }; \
static volatile struct ring_buff *name = &_##name
[[nodiscard]] static bool buff_is_empty(volatile struct ring_buff *b)
{
return b->head == b->tail;
}
[[nodiscard]] static bool buff_is_full(volatile struct ring_buff *b)
{
return ((b->tail & b->mask) == (b->head & b->mask)) && !buff_is_empty(b);
}
static bool buff_putc(volatile struct ring_buff *b, char c)
{
if (buff_is_full(b)) {
return true;
}
b->buffer[b->head & b->mask] = c;
b->head++;
return false;
}
static char buff_getc(volatile struct ring_buff *b)
{
while (buff_is_empty(b)) {
}
char c = b->buffer[b->tail & b->mask];
b->tail++;
return c;
}
[[nodiscard, maybe_unused]] static char buff_peekc(volatile struct ring_buff *b)
{
while (buff_is_empty(b)) {
}
return b->buffer[b->tail & b->mask];
}
[[nodiscard, maybe_unused]] static char buff_peekc_last(volatile struct ring_buff *b)
{
while (buff_is_empty(b)) {
}
return b->buffer[(b->head - 1) & b->mask];
}
#endif