123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- http://tath.eu/code/ring-buffer-in-c/
- Ring buffer is very common and useful data structure, excellent for storing
- asynchronous data from multiple sources in embedded devices.
- ringbuffer.h
- // Simple prove-of-concept ring buffer
- // Author: Adam Orcholski, www.tath.eu
- #pragma once
-
- // types
- typedef struct ring_buffer_s
- {
- unsigned char * data; // pointer to external buffer
- int size; // size of external buffer
- int head; // index of free space in external buffer
- int tail; // index of last item to be read
- int count; // hold number of items stored but not read
- } ring_buffer_t;
-
- // interface
- void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes);
- void RING_Reset(ring_buffer_t * const buff_state); // note: does not clear external buffer
- int RING_IsEmpty(ring_buffer_t * const buff_state); // return non-zero if buffer is empty
- int RING_IsFull(ring_buffer_t * const buff_state); // return non-zero if buffer is full
- int RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item); // return non-zero if buffer is full
- int RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item); // return non-zero if buffer is empty
- ringbuffer.c
- // Simple prove-of-concept ring buffer
- // Author: Adam Orcholski, www.tath.eu
-
- #include <ringbuffer.h>
- #include <assert.h>
-
-
- // function definitions
- void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes)
- {
- assert(0 != buff_state);
- assert(0 != in_buffer);
- assert(buffer_size_in_bytes > 0);
-
- buff_state->data = in_buffer;
- buff_state->size = buffer_size_in_bytes;
- buff_state->head = 0;
- buff_state->tail = 0;
- buff_state->count = 0;
- }
-
- void RING_Reset(ring_buffer_t * const buff_state)
- {
- assert(0 != buff_state);
-
- buff_state->head = 0;
- buff_state->tail = 0;
- buff_state->count = 0;
- }
-
- // return non-zero value if buffer is empty
- int RING_IsEmpty(ring_buffer_t * const buff_state)
- {
- int fBufferIsEmpty = 0;
-
- assert(0 != buff_state);
-
- if (0 == buff_state->count)
- {
- fBufferIsEmpty = 1;
- }
-
- return fBufferIsEmpty;
- }
-
- // return non-zero value if buffer is full
- int RING_IsFull(ring_buffer_t * const buff_state)
- {
- int fBufferIsFull = 0;
-
- assert(0 != buff_state);
-
- if (buff_state->count >= buff_state->size)
- {
- fBufferIsFull = 1;
- }
-
- return fBufferIsFull;
- }
-
- // return non-zero value if buffer is full
- int RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item)
- {
- int fBufferIsFull = 0;
-
- assert(0 != buff_state);
-
- fBufferIsFull = RING_IsFull(buff_state);
-
- if (!fBufferIsFull)
- {
- buff_state->data[buff_state->head] = new_item;
- buff_state->head++;
- buff_state->count++;
-
- if (buff_state->head >= buff_state->size)
- {
- buff_state->head = 0;
- }
- }
-
-
- return fBufferIsFull;
- }
-
- // return non-zero value if buffer is empty
- int RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item)
- {
- int fBufferIsEmpty = 0;
-
- assert(0 != buff_state);
- assert(0 != out_item);
-
- fBufferIsEmpty = RING_IsEmpty(buff_state);
-
- if (!fBufferIsEmpty)
- {
- *out_item = buff_state->data[buff_state->tail];
- buff_state->tail++;
- buff_state->count--;
-
- if (buff_state->tail >= buff_state->size)
- {
- buff_state->tail = 0;
- }
- }
-
- return fBufferIsEmpty;
- }
- and example/test compiled in Microsoft Visual Studio:
- main.c
- // Simple prove-of-concept ring buffer example
- // Author: Adam Orcholski, www.tath.eu
-
- #include <stdio.h>
- #include <ringbuffer.h>
-
- #define BUFF_SIZE 4
- unsigned char bufffeeer[BUFF_SIZE];
-
- ring_buffer_t buff;
-
- int main()
- {
- RING_Init(&buff, bufffeeer, sizeof(bufffeeer));
-
- char c = 0;
-
- while (c != 'q')
- {
- static char write_char = 'a';
- c = getchar();
-
- int ret = 0;
-
- if (c == 'w')
- {
- ret = RING_AddItem(&buff, write_char);
- if (ret)
- {
- printf("buffer full\r\n");
- }
- else
- {
- printf("written char = %c\r\n", write_char);
- }
- write_char++;
- if (write_char == 'z') { write_char = 'a'; }
- }
- else if (c == 's')
- {
- char out;
- ret = RING_GetItem(&buff, &out);
- if (ret)
- {
- printf("buffer empty\r\n");
- }
- else
- {
- printf("read char = %c\r\n", out);
- }
- }
- }
-
- return 0;
- }
- Run example, and press W key to add item to buffer and S key to read last item. Press Q to quit.
|