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