ringbuffer.h
#ifndef __RINGBUFFER_H__
#define __RINGBUFFER_H__
#if defined(__cplusplus)
extern "C" {
#endif
#define BUFFER_OVERFLOW (-1)
typedef struct {
unsigned char *buffer;
unsigned int size;
unsigned int fill;
unsigned char *read;
unsigned char *write;
} RINGBUFFER_T;
int ringbuffer_empty(RINGBUFFER_T *rb);
int ringbuffer_full(RINGBUFFER_T *rb);
int ringbuffer_read(RINGBUFFER_T *rb, unsigned char* buf, unsigned int len);
int ringbuffer_write(RINGBUFFER_T *rb, unsigned char* buf, unsigned int len);
void ringbuffer_release(RINGBUFFER_T *rb);
int ringbuffer_init(RINGBUFFER_T **rb, unsigned ringbuffer_size);
unsigned int ringbuffer_get_fillsize(RINGBUFFER_T *rb);
#if defined(__cplusplus)
}
#endif
#endif
ringbuffer.c
/* Ring buffer implementation */
#include "ringbuffer.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
int ringbuffer_empty(RINGBUFFER_T *rb)
{
/* It's empty when the read and write pointers are the same. */
if (0 == rb->fill) {
return 1;
}else {
return 0;
}
}
int ringbuffer_full(RINGBUFFER_T *rb)
{
/* It's full when the write ponter is 1 element before the read pointer*/
if (rb->size == rb->fill) {
return 1;
}else {
return 0;
}
}
int ringbuffer_read(RINGBUFFER_T *rb, unsigned char* buf, unsigned int len)
{
assert(len>0);
if (rb->fill >= len) {
// in one direction, there is enough data for retrieving
if (rb->write > rb->read) {
memcpy(buf, rb->read, len);
rb->read += len;
}else if (rb->write < rb->read) {
int len1 = rb->buffer + rb->size - 1 - rb->read + 1;
if (len1 >= len) {
memcpy(buf, rb->read, len);
rb->read += len;
} else {
int len2 = len - len1;
memcpy(buf, rb->read, len1);
memcpy(buf + len1, rb->buffer, len2);
rb->read = rb->buffer + len2; // Wrap around
}
}
rb-> fill -= len;
return len;
} else {
return 0;
}
}
int ringbuffer_write(RINGBUFFER_T *rb, unsigned char* buf, unsigned int len)
{
assert(len > 0);
if (rb->size - rb->fill < len) {
return 0;
}
else {
if (rb->write >= rb->read) {
int len1 = rb->buffer + rb->size - rb->write;
if (len1 >= len) {
memcpy(rb->write, buf, len);
rb->write += len;
} else {
int len2 = len - len1;
memcpy(rb->write, buf, len1);
memcpy(rb->buffer, buf+len1, len2);
rb->write = rb->buffer + len2; // Wrap around
}
} else {
memcpy(rb->write, buf, len);
rb->write += len;
}
rb->fill += len;
return len;
}
}
unsigned int ringbuffer_get_fillsize(RINGBUFFER_T *rb)
{
return rb->fill;
}
void ringbuffer_release(RINGBUFFER_T *rb)
{
if ( NULL != rb )
{
if ( NULL != rb->buffer )
{
free(rb->buffer);
}
free(rb);
}
}
int ringbuffer_init(RINGBUFFER_T **rb, unsigned ringbuffer_size)
{
*rb = (RINGBUFFER_T *)malloc(sizeof(RINGBUFFER_T));
if ( NULL == *rb )
{
return -1;
}
memset(*rb, 0, sizeof(RINGBUFFER_T));
(*rb)->buffer = (unsigned char *)malloc(ringbuffer_size);
if ( NULL == (*rb)->buffer )
{
free(*rb);
return -1;
}
memset((*rb)->buffer, 0, ringbuffer_size);
(*rb)->size = ringbuffer_size;
(*rb)->fill = 0;
(*rb)->read = (*rb)->buffer;
(*rb)->write = (*rb)->buffer;
return 0;
}