Apostolos Fanakis
6 years ago
3 changed files with 173 additions and 3 deletions
@ -0,0 +1,126 @@ |
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <stddef.h> |
|||
#include <assert.h> |
|||
#include <string.h> |
|||
|
|||
#include "circ_buff.h" |
|||
|
|||
// Defines the circular buffer structure
|
|||
struct circ_buf_t { |
|||
char** buffer; |
|||
size_t head; |
|||
size_t tail; |
|||
size_t max; // of the buffer
|
|||
bool full; |
|||
}; |
|||
|
|||
// Private Functions
|
|||
|
|||
static void advance_pointer(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
if(cbuf->full) { |
|||
cbuf->tail = (cbuf->tail + 1) % cbuf->max; |
|||
} |
|||
|
|||
cbuf->head = (cbuf->head + 1) % cbuf->max; |
|||
|
|||
// We mark full because we will advance tail on the next time around
|
|||
cbuf->full = (cbuf->head == cbuf->tail); |
|||
} |
|||
|
|||
static void retreat_pointer(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
cbuf->full = false; |
|||
cbuf->tail = (cbuf->tail + 1) % cbuf->max; |
|||
} |
|||
|
|||
// APIs
|
|||
|
|||
cbuf_handle_t circ_buf_init(char** buffer, size_t size) { |
|||
assert(buffer && size); |
|||
|
|||
cbuf_handle_t cbuf = malloc(sizeof(circ_buf_t)); |
|||
assert(cbuf); |
|||
|
|||
cbuf->buffer = buffer; |
|||
cbuf->max = size; |
|||
circ_buf_reset(cbuf); |
|||
|
|||
assert(circ_buf_empty(cbuf)); |
|||
|
|||
return cbuf; |
|||
} |
|||
|
|||
void circ_buf_free(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
free(cbuf); |
|||
} |
|||
|
|||
void circ_buf_reset(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
cbuf->head = 0; |
|||
cbuf->tail = 0; |
|||
cbuf->full = false; |
|||
} |
|||
|
|||
size_t circ_buf_size(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
size_t size = cbuf->max; |
|||
|
|||
if(!cbuf->full) { |
|||
if(cbuf->head >= cbuf->tail) { |
|||
size = (cbuf->head - cbuf->tail); |
|||
} |
|||
else { |
|||
size = (cbuf->max + cbuf->head - cbuf->tail); |
|||
} |
|||
} |
|||
|
|||
return size; |
|||
} |
|||
|
|||
size_t circ_buf_capacity(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return cbuf->max; |
|||
} |
|||
|
|||
void circ_buf_put(cbuf_handle_t cbuf, char data) { |
|||
assert(cbuf && cbuf->buffer); |
|||
|
|||
strcpy(cbuf->buffer[cbuf->head], data); |
|||
|
|||
advance_pointer(cbuf); |
|||
} |
|||
|
|||
int circ_buf_get(cbuf_handle_t cbuf, char* data) { |
|||
assert(cbuf && data && cbuf->buffer); |
|||
|
|||
int r = -1; |
|||
|
|||
if(!circ_buf_empty(cbuf)) { |
|||
strcpy(data, cbuf->buffer[cbuf->tail]); |
|||
retreat_pointer(cbuf); |
|||
|
|||
r = 0; |
|||
} |
|||
|
|||
return r; |
|||
} |
|||
|
|||
bool circ_buf_empty(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return (!cbuf->full && (cbuf->head == cbuf->tail)); |
|||
} |
|||
|
|||
bool circ_buf_full(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return cbuf->full; |
|||
} |
@ -0,0 +1,44 @@ |
|||
/*
|
|||
* Implementation of a simple circular buffer data structure. |
|||
* Based on the example and guide found here: |
|||
* https://embeddedartistry.com/blog/2017/4/6/circular-buffers-in-cc
|
|||
*/ |
|||
#ifndef CIRC_BUFF_H_ |
|||
#define CIRC_BUFF_H_ |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
// Circular buffer structure
|
|||
typedef struct circ_buf_t circ_buf_t; |
|||
// and handle type
|
|||
typedef circ_buf_t* cbuf_handle_t; |
|||
|
|||
// Initializes a circular buffer structure and returns the circular buffer handle.
|
|||
// Pass in a storage buffer and size.
|
|||
cbuf_handle_t circ_buf_init(char** buffer, size_t size); |
|||
|
|||
// Frees a circular buffer structure. Does not free data buffer!
|
|||
void circ_buf_free(cbuf_handle_t cbuf); |
|||
|
|||
// Resets the circular buffer to empty, head == tail. Data not cleared!
|
|||
void circ_buf_reset(cbuf_handle_t cbuf); |
|||
|
|||
// Adds data, even if the buffer is full. Old data is overwritten.
|
|||
void circ_buf_put(cbuf_handle_t cbuf, char data); |
|||
|
|||
// Retrieves a value from the buffer.
|
|||
int circ_buf_get(cbuf_handle_t cbuf, char* data); |
|||
|
|||
// Checks if the buffer is empty.
|
|||
bool circ_buf_empty(cbuf_handle_t cbuf); |
|||
|
|||
// Checks if the buffer is full.
|
|||
bool circ_buf_full(cbuf_handle_t cbuf); |
|||
|
|||
// Checks the capacity of the buffer.
|
|||
size_t circ_buf_capacity(cbuf_handle_t cbuf); |
|||
|
|||
// Checks the number of elements stored in the buffer.
|
|||
size_t circ_buf_size(cbuf_handle_t cbuf); |
|||
|
|||
#endif //CIRC_BUFF_H_
|
Loading…
Reference in new issue