generic circular buffer implementation in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
circbuf/circbuf.c

101 lines
1.5 KiB

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include "circbuf.h"
void cbuf_init(circbuf_t *inst, size_t capacity)
{
inst->buf = malloc(capacity);
inst->cap = capacity;
cbuf_clear(inst);
}
void cbuf_deinit(circbuf_t *inst)
{
if (inst->buf != NULL) {
free(inst->buf);
}
}
bool cbuf_full(circbuf_t *inst)
{
return (inst->lr == inst->nw);
}
static bool can_read_at(circbuf_t *inst, size_t i)
{
if (inst->lr < inst->nw) {
return i > inst->lr && i < inst->nw;
} else {
// NW < LR
return (i < inst->cap && i > inst->lr) || i < inst->nw;
}
}
bool cbuf_empty(circbuf_t *inst)
{
return ((inst->lr + 1) % inst->cap) == inst->nw;
}
bool cbuf_write(circbuf_t *inst, uint8_t b)
{
if (cbuf_full(inst)) return false;
inst->buf[inst->nw] = b;
// increment
inst->nw++;
if (inst->nw == inst->cap) inst->nw = 0;
return true;
}
bool cbuf_read(circbuf_t *inst, uint8_t *b)
{
if (cbuf_empty(inst)) return false;
// increment
inst->lr++;
if (inst->lr == inst->cap) inst->lr = 0;
*b = inst->buf[inst->lr];
//zero out the read byte (for debug)
inst->buf[inst->lr] = 0;
return true;
}
bool cbuf_peek(circbuf_t *inst, size_t nth, uint8_t *b)
{
// check if can read there (can't use modulo, could "wrap")
size_t n = inst->lr;
for (size_t i = 0; i <= nth; i++) {
// increment N
n++;
if (n == inst->cap) n = 0;
if (!can_read_at(inst, n)) return false;
}
*b = inst->buf[n];
return true;
}
void cbuf_clear(circbuf_t *inst)
{
inst->lr = inst->cap - 1;
inst->nw = 0;
}