141 lines
3.4 KiB
C
141 lines
3.4 KiB
C
#include "libRingbuffer.h"
|
|
|
|
libRingBufferTypedef *libRingBufferNew(int size, int len) {
|
|
libRingBufferTypedef *self = (libRingBufferTypedef *)malloc(sizeof(libRingBufferTypedef));
|
|
|
|
if (!self)
|
|
return NULL;
|
|
|
|
memset(self, 0, sizeof(libRingBufferTypedef));
|
|
|
|
if (libRingBufferInit(self, size, len) < 0) {
|
|
free(self);
|
|
return NULL;
|
|
}
|
|
return self;
|
|
};
|
|
|
|
int libRingBufferInit(libRingBufferTypedef *self, int size, int len) {
|
|
self->buf = (unsigned char *)malloc(size*len);
|
|
if (!self->buf) return -1;
|
|
memset(self->buf, 0, size*len);
|
|
|
|
self->size = size;
|
|
self->len = len;
|
|
self->start = 0;
|
|
self->end = 0;
|
|
self->elements = 0;
|
|
|
|
self->next_end_index = &libRingBufferNextEndIndex;
|
|
self->incr_end_index = &libRingBufferIncrEnd;
|
|
self->incr_start_index = &libRingBufferIncrStart;
|
|
self->isFull = &libRingBufferIsFull;
|
|
self->isEmpty = &libRingBufferIsEmpty;
|
|
self->add = &libRingBufferAdd;
|
|
self->numElements = &libRingBufferNumElements;
|
|
self->peek = &libRingBufferPeek;
|
|
self->pull = &libRingBufferPull;
|
|
return 0;
|
|
};
|
|
|
|
int libRingBufferDelete(libRingBufferTypedef *self) {
|
|
free(self->buf);
|
|
free(self);
|
|
return 0;
|
|
};
|
|
|
|
/////// PRIVATE METHODS //////////
|
|
// get next empty index
|
|
int libRingBufferNextEndIndex(libRingBufferTypedef *self) {
|
|
//buffer is full
|
|
if (self->isFull(self)) return -1;
|
|
//if empty dont incriment
|
|
return (self->end+(unsigned int)!self->isEmpty(self))%self->len;
|
|
};
|
|
|
|
// incriment index of RingBuf struct, only call if safe to do so
|
|
int libRingBufferIncrEnd(libRingBufferTypedef *self) {
|
|
self->end = (self->end+1)%self->len;
|
|
return self->end;
|
|
};
|
|
|
|
|
|
// incriment index of RingBuf struct, only call if safe to do so
|
|
int libRingBufferIncrStart(libRingBufferTypedef *self) {
|
|
self->start = (self->start+1)%self->len;
|
|
return self->start;
|
|
};
|
|
|
|
/////// PUBLIC METHODS //////////
|
|
// Add an object struct to RingBuf
|
|
int libRingBufferAdd(libRingBufferTypedef *self, const void *object) {
|
|
int index;
|
|
// Perform all atomic opertaions
|
|
index = self->next_end_index(self);
|
|
//if not full
|
|
if (index >= 0) {
|
|
memcpy(self->buf + index*self->size, object, self->size);
|
|
if (!self->isEmpty(self)) self->incr_end_index(self);
|
|
self->elements++;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Return pointer to num element, return null on empty or num out of bounds
|
|
void *libRingBufferPeek(libRingBufferTypedef *self, unsigned int num) {
|
|
void *ret = NULL;
|
|
|
|
//empty or out of bounds
|
|
if (self->isEmpty(self) || num > self->elements - 1)
|
|
ret = NULL;
|
|
else
|
|
ret = &self->buf[((self->start + num)%self->len)*self->size];
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Returns and removes first buffer element
|
|
void *libRingBufferPull(libRingBufferTypedef *self, void *object) {
|
|
void *ret = NULL;
|
|
|
|
if (self->isEmpty(self))
|
|
ret = NULL;
|
|
else{
|
|
memcpy(object, self->buf+self->start*self->size, self->size);
|
|
self->elements--;
|
|
// don't incriment start if removing last element
|
|
if (!self->isEmpty(self)) self->incr_start_index(self);
|
|
ret = object;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Returns number of elemnts in buffer
|
|
unsigned int libRingBufferNumElements(libRingBufferTypedef *self) {
|
|
unsigned int elements;
|
|
|
|
elements = self->elements;
|
|
|
|
return elements;
|
|
}
|
|
|
|
// Returns true if buffer is full
|
|
bool libRingBufferIsFull(libRingBufferTypedef *self) {
|
|
bool ret;
|
|
|
|
ret = self->elements == self->len;
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Returns true if buffer is empty
|
|
bool libRingBufferIsEmpty(libRingBufferTypedef *self) {
|
|
bool ret;
|
|
|
|
ret = !self->elements;
|
|
|
|
return ret;
|
|
}
|