/*
* Ring_buffer: utilizes a fixed-size buffer as if it were connected end-to-end (as if the buffer was circular in shape).
* The ring buffer is a FIFO type of buffer
*
*@ Author: Amjad Yousef Majid
*@ Date: 12/March/2017
*/
#include
#include // needed for the uint8_t data type
#include // needed for the size_t and malloc
#include // needed for the printf
/** variables declations and definitions*/
/* Declare a data type that holds the charactristics of a ring buffer */
typedef struct {
uint8_t *buffer; // a pointer to hold the address to the ring buffer
size_t size; // `size_t` is used here to represent buffer
// object size in byte. `malloc` expects this data type
size_t data_len; // capture the length of the valid
size_t head; // the start index of the valid data
size_t tail; // the end index of the valid data
}rbuf_t;
/*-----------------------------------------------------------------------------*/
/** functions prototyping */
void _advance_idx(size_t *idx, size_t *size);
bool rbuf_empty(rbuf_t* rbuf);
bool rbuf_full(rbuf_t *rbuf);
void rbuf_put( rbuf_t *rbuf, uint8_t data);
/*------------------------------------------------------------------------------*/
/** _advance_idx:
* It is a helper function that advances an index of a ring buffer and set it to
* zero when it is equal the buffer size
*
* @param *idx *idx pointer to the head/tail ring buffer indices
* @param *size *size pointer to the size of the buffer
*/
void _advance_idx(size_t *idx, size_t *size)
{
if(++(*idx) == *size)
{
*idx= 0;
}
}
/** rbuf_empty:
* check if the ring buffer is empty
*
* @param *rbuf pointer to a ring buffer
* @return `true value` if the ring buffer is empty
*/
bool rbuf_empty(rbuf_t* rbuf)
{
return (rbuf->data_len == 0);
}
/** rbuf_full:
* check if the ring buffer is full
*
* @param *rbuf pointer to a ring buffer
* @return `true value` if the ring buffer is full
*/
bool rbuf_full(rbuf_t *rbuf)
{
return ( rbuf->data_len == rbuf->size);
}
/** rbuf_put:
* insert a value into the buffer
*
* @param *rbuf pointer to a ring buffer
* @param data a byte to be inserted in to the buffer
*/
void rbuf_put( rbuf_t *rbuf, uint8_t data)
{
// insert the data
rbuf->buffer[rbuf->head] = data;
// check if old data is overwritten
if(rbuf_full(rbuf))
{
// advances the tail index to point to the old data
// buffer size equals (max index + 1)
_advance_idx(&rbuf->tail, &rbuf->size);
}
else
{
// increase the length of the data if you do not overwrite old data
rbuf->data_len++;
}
// if the head index equals the buffer size set it back to zero
_advance_idx(&rbuf->head, &rbuf->size);
}
/** rbuf_get:
* get a data from the buffer if it is not empty and advance tail pointer
*
* @param *rbuf pointer to a ring buffer
* @param *data pointer to a variable to get the data from the buffer
* @param `true value` if the buffer is not empty
*/
bool rbuf_get(rbuf_t * rbuf, uint8_t *data)
{
if(rbuf_empty(rbuf))
{
return (false);
}
// get the data
*data = rbuf->buffer[rbuf->tail] ;
// decrease the valid length
rbuf->data_len--;
_advance_idx(&rbuf->tail, &rbuf->size);
return true;
}
/** rbuf_search:
* search a buffer for a certain word
*
* @param *rbuf pointer to a ring buffer
* @param word a byte of data
* @return bool "true" if the word is found, else "false"
*/
bool rbuf_search( rbuf_t *rbuf, uint8_t word)
{
uint16_t cntr = 0;
while( cntr < rbuf->data_len)
{
if ( word == rbuf->buffer[(rbuf->tail) + cntr])
{
return true;
}
cntr++;
}
return false;
}
/** rbuf_write:
* write many bytes to the buffer
*
* @param *rbuf pointer to a ring buffer
* @param numBytes the number of bytes to be inseted
* @param data a pointer to byte of data to be inserted
*/
void rbuf_write( rbuf_t *rbuf, uint8_t numBytes, uint8_t *data)
{
while(numBytes--)
{
rbuf_put(rbuf, *data);
data++;
}
}
/** rbuf_read:
* read many bytes to the buffer
*
* @param *rbuf pointer to a ring buffer
* @param data a byte to be read from the buffer
*/
void rbuf_read( rbuf_t *rbuf, uint8_t numBytes, uint8_t *data)
{
while( (numBytes--) && rbuf_get(rbuf, data))
{
data++;
}
}
rbuf_t *rbuf = NULL;
int main()
{
rbuf = malloc(sizeof(rbuf_t));
rbuf->data_len=0;
rbuf->head = 0;
rbuf->tail = 0;
rbuf->size = 10;
rbuf->buffer = malloc(rbuf->size);
printf(" insert data\n");
for(uint8_t i = 0; i < 7 ; i++)
{
printf("->%d\n", i);
rbuf_put(rbuf, i);
}
printf("---------------\n");
printf("data_len: %lu \n", rbuf->data_len);
printf("tail %lu \n", rbuf->tail);
printf("head %lu \n", rbuf->head);
printf("size : %lu \n", rbuf->size);
printf("----------------\n");
uint8_t data;
for(uint8_t i = 0; i < 9; i++)
{
if( rbuf_get(rbuf, &data))
{
printf("%d \n", data);
}
}
printf("----------------\n");
printf("data_len: %lu \n", rbuf->data_len);
printf("tail %lu \n", rbuf->tail);
printf("head %lu \n", rbuf->head);
printf("size : %lu \n", rbuf->size);
printf("----------------\n");
printf(" insert data\n");
for(uint8_t i = 0; i < 6; i++)
{
printf("->%d\n", i);
rbuf_put(rbuf, i);
}
printf("----------------\n");
printf("data_len: %lu \n", rbuf->data_len);
printf("tail %lu \n", rbuf->tail);
printf("head %lu \n", rbuf->head);
printf("size : %lu \n", rbuf->size);
printf("----------------\n");
for(uint8_t i = 0; i < 3; i++)
{
if(!rbuf_get(rbuf, &data))
{
break;
}
printf("%d \n", data);
}
printf("----------------\n");
uint8_t data_arr[] = {0,1,2,3,4,5,6,7,8};
for(uint8_t i = 0; i < 9; i++)
{
if(rbuf_search(rbuf, data_arr[i]))
{
printf("found\n");
}
else
{
printf("not found\n");
}
}
return 0;
}