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

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

@ -1,39 +1,54 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.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;
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_full(circbuf_t *inst)
{
if (inst->read_pos == 0) {
return inst->write_pos == inst->capacity - 1;
} else {
return inst->write_pos == inst->read_pos;
}
}
bool cbuf_empty(CircularBuffer *inst)
bool cbuf_empty(circbuf_t *inst)
{
return inst->data_len == 0;
if (inst->write_pos == 0) {
return inst->read_pos == inst->capacity - 1;
} else {
return inst->read_pos == inst->write_pos - 1;
}
}
bool cbuf_write(CircularBuffer *inst, uint8_t b)
bool cbuf_write(circbuf_t *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) {
@ -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;
*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));
}
// zero out the read byte (for debug)
//inst->buffer[inst->read_pos] = 0;
return true;
}
uint16_t cbuf_write_partial(CircularBuffer *inst, const uint8_t *b, uint16_t max)
bool cbuf_peek(circbuf_t *inst, uint8_t *b)
{
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;
}
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;
if (cbuf_empty(inst)) return false;
*b = inst->buffer[inst->read_pos];
return true;
}
uint16_t cbuf_read_partial(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_partial(CircularBuffer *inst, char *str, uint16_t max)
void cbuf_clear(circbuf_t *inst)
{
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;
inst->read_pos = inst->capacity - 1;
inst->write_pos = 0;
}

@ -2,99 +2,49 @@
#include <stdint.h>
#include <stdbool.h>
typedef struct {
// Circular Character Buffer implementation
typedef struct CircularBuffer_struct {
uint8_t *buffer;
uint16_t capacity;
uint16_t read_pos;
uint16_t write_pos;
uint16_t data_len;
} CircularBuffer;
} circbuf_t;
/** 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 */
bool cbuf_full(CircularBuffer *inst);
bool cbuf_full(circbuf_t *inst);
/** Test for empty buffer */
bool cbuf_empty(CircularBuffer *inst);
bool cbuf_empty(circbuf_t *inst);
/** 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.
* False on empty.
*/
bool cbuf_peek(CircularBuffer *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);
bool cbuf_peek(circbuf_t *inst, uint8_t *b);
/** Remove all data from buffer */
void cbuf_clear(CircularBuffer *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);
void cbuf_clear(circbuf_t *inst);

Loading…
Cancel
Save