commit
0fb32781c9
@ -0,0 +1,33 @@ |
||||
Circular byte buffer |
||||
==================== |
||||
|
||||
This is a circular buffer implementation, useful for embedded systems (buffer for UART RX queue etc). |
||||
|
||||
|
||||
Usage |
||||
----- |
||||
|
||||
```c |
||||
#include <stdint.h> |
||||
|
||||
uint8_t buffer[32]; // array backing the buffer |
||||
|
||||
CircularByteBuffer cb; // buffer instance |
||||
|
||||
void main() |
||||
{ |
||||
cbuf_init(&cb, buffer, 32); // init the buffer |
||||
|
||||
// now it's ready for use! |
||||
} |
||||
``` |
||||
|
||||
Many function return success flag, so make sure to check the return values. |
||||
|
||||
False is returned on buffer overflow / underflow, attempted read past available data size etc. See the header file for details. |
||||
|
||||
|
||||
License |
||||
------- |
||||
|
||||
Do whatever you want with the code. |
@ -0,0 +1,175 @@ |
||||
#include <stdint.h> |
||||
#include <stdbool.h> |
||||
#include <string.h> |
||||
|
||||
#include "circbuf.h" |
||||
|
||||
|
||||
void cbuf_init(CircularBuffer *inst, uint8_t *buffer, uint16_t length) |
||||
{ |
||||
inst->buffer = buffer; |
||||
inst->capacity = length; |
||||
|
||||
cbuf_clear(inst); |
||||
} |
||||
|
||||
|
||||
bool cbuf_full(CircularBuffer *inst) |
||||
{ |
||||
return inst->data_len == inst->capacity; |
||||
} |
||||
|
||||
|
||||
bool cbuf_empty(CircularBuffer *inst) |
||||
{ |
||||
return inst->data_len == 0; |
||||
} |
||||
|
||||
|
||||
bool cbuf_write(CircularBuffer *inst, uint8_t b) |
||||
{ |
||||
if (cbuf_full(inst)) return false; |
||||
|
||||
inst->buffer[inst->write_pos] = b; |
||||
|
||||
inst->write_pos++; |
||||
inst->data_len++; |
||||
|
||||
// wrap
|
||||
if (inst->write_pos >= inst->capacity) { |
||||
inst->write_pos = 0; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
bool cbuf_read(CircularBuffer *inst, uint8_t *b) |
||||
{ |
||||
if (cbuf_empty(inst)) return false; |
||||
|
||||
*b = inst->buffer[inst->read_pos]; |
||||
|
||||
inst->read_pos++; |
||||
inst->data_len--; |
||||
|
||||
// wrap
|
||||
if (inst->read_pos >= inst->capacity) { |
||||
inst->read_pos = 0; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
bool cbuf_peek(CircularBuffer *inst, uint8_t *b) |
||||
{ |
||||
if (cbuf_empty(inst)) return false; |
||||
|
||||
*b = inst->buffer[inst->read_pos]; |
||||
return true; |
||||
} |
||||
|
||||
|
||||
uint16_t cbuf_data_size(CircularBuffer *inst) |
||||
{ |
||||
return inst->data_len; |
||||
} |
||||
|
||||
|
||||
uint16_t cbuf_free_space(CircularBuffer *inst) |
||||
{ |
||||
return inst->capacity - inst->data_len; |
||||
} |
||||
|
||||
|
||||
void cbuf_clear(CircularBuffer *inst) |
||||
{ |
||||
inst->read_pos = 0; |
||||
inst->write_pos = 0; |
||||
inst->data_len = 0; |
||||
} |
||||
|
||||
|
||||
bool cbuf_write_n(CircularBuffer *inst, const uint8_t *b, uint16_t count) |
||||
{ |
||||
if (cbuf_free_space(inst) < count) return false; |
||||
|
||||
for (uint16_t i = 0; i < count; i++) { |
||||
cbuf_write(inst, *(b + i)); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
bool cbuf_write_string(CircularBuffer *inst, const char *str) |
||||
{ |
||||
return cbuf_write_n(inst, (uint8_t *) str, strlen(str)); |
||||
} |
||||
|
||||
|
||||
bool cbuf_read_n(CircularBuffer *inst, uint8_t *buf, uint16_t len) |
||||
{ |
||||
if (cbuf_data_size(inst) < len) return false; |
||||
|
||||
for (uint16_t i = 0; i < len; i++) { |
||||
cbuf_read(inst, buf + i); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
bool cbuf_read_string(CircularBuffer *inst, char *str, uint16_t len) |
||||
{ |
||||
bool b = cbuf_read_n(inst, (uint8_t *) str, len); |
||||
if (!b) return false; |
||||
|
||||
str[len] = 0; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
uint16_t cbuf_read_upto(CircularBuffer *inst, uint8_t *buf, uint16_t max) |
||||
{ |
||||
uint16_t i; |
||||
for (i = 0; i < max; i++) { |
||||
if (cbuf_empty(inst)) break; |
||||
cbuf_read(inst, buf + i); |
||||
} |
||||
|
||||
return i; |
||||
} |
||||
|
||||
|
||||
uint16_t cbuf_read_string_upto(CircularBuffer *inst, char *str, uint16_t max) |
||||
{ |
||||
uint16_t cnt = cbuf_read_upto(inst, (uint8_t *) str, max); |
||||
str[cnt] = 0; |
||||
return cnt; |
||||
} |
||||
|
||||
|
||||
int32_t cbuf_find(CircularBuffer *inst, uint8_t b) |
||||
{ |
||||
uint16_t cursor = inst->read_pos; |
||||
uint16_t cnt = 0; |
||||
|
||||
while (cursor != inst->write_pos) { |
||||
|
||||
if (inst->buffer[cursor] == b) return cnt; |
||||
|
||||
cursor++; |
||||
cnt++; |
||||
|
||||
// wrap
|
||||
if (cursor >= inst->capacity) { |
||||
cursor = 0; |
||||
} |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
|
@ -0,0 +1,79 @@ |
||||
#pragma once |
||||
#include <stdint.h> |
||||
#include <stdbool.h> |
||||
|
||||
typedef struct { |
||||
uint8_t *buffer; |
||||
uint16_t capacity; |
||||
uint16_t read_pos; |
||||
uint16_t write_pos; |
||||
uint16_t data_len; |
||||
} CircularByteBuffer; |
||||
|
||||
|
||||
/** Init a buffer */ |
||||
void cbuf_init(CircularByteBuffer *inst, uint8_t *buffer, uint16_t length); |
||||
|
||||
|
||||
/** Test for full buffer */ |
||||
bool cbuf_full(CircularByteBuffer *inst); |
||||
|
||||
|
||||
/** Test for empty buffer */ |
||||
bool cbuf_empty(CircularByteBuffer *inst); |
||||
|
||||
|
||||
/** Write a byte to buffer, returns success */ |
||||
bool cbuf_write(CircularByteBuffer *inst, uint8_t b); |
||||
|
||||
|
||||
/** Read a byte from the buffer, return susccess */ |
||||
bool cbuf_read(CircularByteBuffer *inst, uint8_t *b); |
||||
|
||||
|
||||
/** Get byte at the read cursor, without incrementing it. False on empty. */ |
||||
bool cbuf_peek(CircularByteBuffer *inst, uint8_t *b); |
||||
|
||||
|
||||
/** Get data count */ |
||||
uint16_t cbuf_data_size(CircularByteBuffer *inst); |
||||
|
||||
|
||||
/** Get free space in the buffer */ |
||||
uint16_t cbuf_free_space(CircularByteBuffer *inst); |
||||
|
||||
|
||||
/** Remove all data from buffer */ |
||||
void cbuf_clear(CircularByteBuffer *inst); |
||||
|
||||
|
||||
/** Write N bytes. Returns success */ |
||||
bool cbuf_write_n(CircularByteBuffer *inst, const uint8_t *b, uint16_t count); |
||||
|
||||
|
||||
/** Write a string (without \0) */ |
||||
bool cbuf_write_string(CircularByteBuffer *inst, const char *str); |
||||
|
||||
|
||||
/** Read N bytes, if available. Returns success. */ |
||||
bool cbuf_read_n(CircularByteBuffer *inst, uint8_t *buf, uint16_t len); |
||||
|
||||
|
||||
/** Read string of given length, append \0. `str` must be len+1 long */ |
||||
bool cbuf_read_string(CircularByteBuffer *inst, char *str, uint16_t len); |
||||
|
||||
|
||||
/** Read up to N bytes. Returns byte count */ |
||||
uint16_t cbuf_read_upto(CircularByteBuffer *inst, uint8_t *buf, uint16_t max); |
||||
|
||||
|
||||
/** Read string up to N chars long, append \0. `str` must be max+1 long */ |
||||
uint16_t cbuf_read_string_upto(CircularByteBuffer *inst, char *str, uint16_t max); |
||||
|
||||
|
||||
/**
|
||||
* Search buffer and return position of the first occurence |
||||
* of the given byte (position relative to read_pos). |
||||
* Returns -1 if not found. |
||||
*/ |
||||
int32_t cbuf_find(CircularByteBuffer *inst, uint8_t b); |
Loading…
Reference in new issue