should be reliable now with producent and consumer threads. Removed length variable. Also removed useless "bonus" funcs.

threadsafe
Ondřej Hruška 9 years ago
parent 89e9249b92
commit 46e243dd2c
  1. 164
      circbuf.c
  2. 88
      circbuf.h

@ -1,39 +1,54 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <malloc.h>
#include "circbuf.h" #include "circbuf.h"
void cbuf_init(CircularBuffer *inst, uint8_t *buffer, uint16_t length) void cbuf_init(circbuf_t *inst, uint16_t length)
{ {
inst->buffer = buffer; inst->buffer = malloc(length);
inst->capacity = length; inst->capacity = length;
cbuf_clear(inst); cbuf_clear(inst);
} }
bool cbuf_full(CircularBuffer *inst) void cbuf_deinit(circbuf_t *inst)
{ {
return inst->data_len == inst->capacity; if (inst->buffer != NULL) {
free(inst->buffer);
}
} }
bool cbuf_empty(CircularBuffer *inst) bool cbuf_full(circbuf_t *inst)
{ {
return inst->data_len == 0; if (inst->read_pos == 0) {
return inst->write_pos == inst->capacity - 1;
} else {
return inst->write_pos == inst->read_pos;
}
} }
bool cbuf_write(CircularBuffer *inst, uint8_t b) bool cbuf_empty(circbuf_t *inst)
{
if (inst->write_pos == 0) {
return inst->read_pos == inst->capacity - 1;
} else {
return inst->read_pos == inst->write_pos - 1;
}
}
bool cbuf_write(circbuf_t *inst, uint8_t b)
{ {
if (cbuf_full(inst)) return false; if (cbuf_full(inst)) return false;
inst->buffer[inst->write_pos] = b; inst->buffer[inst->write_pos] = b;
inst->write_pos++; inst->write_pos++;
inst->data_len++;
// wrap // wrap
if (inst->write_pos >= inst->capacity) { if (inst->write_pos >= inst->capacity) {
@ -44,150 +59,37 @@ bool cbuf_write(CircularBuffer *inst, uint8_t b)
} }
bool cbuf_read(CircularBuffer *inst, uint8_t *b) bool cbuf_read(circbuf_t *inst, uint8_t *b)
{ {
if (cbuf_empty(inst)) return false; if (cbuf_empty(inst)) return false;
*b = inst->buffer[inst->read_pos];
inst->read_pos++; inst->read_pos++;
inst->data_len--;
// wrap // wrap
if (inst->read_pos >= inst->capacity) { if (inst->read_pos >= inst->capacity) {
inst->read_pos = 0; 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]; *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;
}
// zero out the read byte (for debug)
uint16_t cbuf_write_partial(CircularBuffer *inst, const uint8_t *b, uint16_t max) //inst->buffer[inst->read_pos] = 0;
{
uint16_t i;
for (i = 0; i < max; i++) {
if (cbuf_full(inst)) break;
cbuf_write(inst, *(b + i));
}
return i;
}
bool cbuf_write_string(CircularBuffer *inst, const char *str)
{
return cbuf_write_n(inst, (uint8_t *) str, strlen(str));
}
uint16_t cbuf_write_string_partial(CircularBuffer *inst, const char *str)
{
return cbuf_write_partial(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; return true;
} }
bool cbuf_read_string(CircularBuffer *inst, char *str, uint16_t len) bool cbuf_peek(circbuf_t *inst, uint8_t *b)
{ {
bool b = cbuf_read_n(inst, (uint8_t *) str, len); if (cbuf_empty(inst)) return false;
if (!b) return false;
str[len] = 0;
*b = inst->buffer[inst->read_pos];
return true; return true;
} }
uint16_t cbuf_read_partial(CircularBuffer *inst, uint8_t *buf, uint16_t max) void cbuf_clear(circbuf_t *inst)
{ {
uint16_t i; inst->read_pos = inst->capacity - 1;
for (i = 0; i < max; i++) { inst->write_pos = 0;
if (cbuf_empty(inst)) break;
cbuf_read(inst, buf + i);
}
return i;
}
uint16_t cbuf_read_string_partial(CircularBuffer *inst, char *str, uint16_t max)
{
uint16_t cnt = cbuf_read_partial(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;
} }

@ -2,99 +2,49 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
typedef struct { // Circular Character Buffer implementation
typedef struct CircularBuffer_struct {
uint8_t *buffer; uint8_t *buffer;
uint16_t capacity; uint16_t capacity;
uint16_t read_pos; uint16_t read_pos;
uint16_t write_pos; uint16_t write_pos;
uint16_t data_len; } circbuf_t;
} CircularBuffer;
/** Init a buffer */ /** Init a buffer */
void cbuf_init(CircularBuffer *inst, uint8_t *buffer, uint16_t length); void cbuf_init(circbuf_t *inst, uint16_t length);
/** Deinit a buffer (free the memory) */
void cbuf_deinit(circbuf_t *inst);
/** Test for full buffer */ /** Test for full buffer */
bool cbuf_full(CircularBuffer *inst); bool cbuf_full(circbuf_t *inst);
/** Test for empty buffer */ /** Test for empty buffer */
bool cbuf_empty(CircularBuffer *inst); bool cbuf_empty(circbuf_t *inst);
/** Write a byte to buffer, returns success */ /** Write a byte to buffer, returns success */
bool cbuf_write(CircularBuffer *inst, uint8_t b); bool cbuf_write(circbuf_t *inst, uint8_t b);
/** Read a byte from the buffer, return susccess */ /**
bool cbuf_read(CircularBuffer *inst, uint8_t *b); * Read a byte from the buffer, return susccess.
* If `b` is NULL, the read byte is discarded.
*/
bool cbuf_read(circbuf_t *inst, uint8_t *b);
/** /**
* Get byte at the read cursor, without incrementing it. * Get byte at the read cursor, without incrementing it.
* False on empty. * False on empty.
*/ */
bool cbuf_peek(CircularBuffer *inst, uint8_t *b); bool cbuf_peek(circbuf_t *inst, uint8_t *b);
/** Get data count */
uint16_t cbuf_data_size(CircularBuffer *inst);
/** Get free space in the buffer */
uint16_t cbuf_free_space(CircularBuffer *inst);
/** Remove all data from buffer */ /** Remove all data from buffer */
void cbuf_clear(CircularBuffer *inst); void cbuf_clear(circbuf_t *inst);
/** Write N bytes, or none. Returns success */
bool cbuf_write_n(CircularBuffer *inst, const uint8_t *b, uint16_t count);
/** Try to write N bytes. Returns actual number of bytes written. */
uint16_t cbuf_write_partial(CircularBuffer *inst, const uint8_t *b, uint16_t max);
/** Write a string (excluding \0) - or nothing. */
bool cbuf_write_string(CircularBuffer *inst, const char *str);
/**
* Try to write string (excluding \0).
* Returns actual number of chars written.
*/
uint16_t cbuf_write_string_partial(CircularBuffer *inst, const char *str);
/** Read N bytes, or none. Returns success. */
bool cbuf_read_n(CircularBuffer *inst, uint8_t *buf, uint16_t len);
/** Read up to N bytes. Returns byte count */
uint16_t cbuf_read_partial(CircularBuffer *inst, uint8_t *buf, uint16_t max);
/** Read string of given length, append \0. `str` must be len+1 long */
bool cbuf_read_string(CircularBuffer *inst, char *str, uint16_t len);
/**
* Read string up to N chars long, append \0.
* `str` must be max+1 long
*/
uint16_t cbuf_read_string_partial(CircularBuffer *inst, char *str, uint16_t max);
/**
* Search buffer and return position of the first occurence
* of the given byte (position relative to read_pos).
*
* The returned value is zero-based, add 1 to get string
* length including the delimiter.
*
* Returns -1 if not found.
*/
int32_t cbuf_find(CircularBuffer *inst, uint8_t b);

Loading…
Cancel
Save