Created
January 28, 2016 08:14
-
-
Save temoto/cb0cef313bfa03b4df3f to your computer and use it in GitHub Desktop.
Ring buffer in C, push to tail, pop from head, single size define <=256
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> // bool, required | |
#include <stdio.h> // printf, only for debug | |
#include <stdlib.h> // uint8_t, required | |
#include <string.h> // memset, required | |
#define RING_BUFFER_SIZE 4 | |
#if RING_BUFFER_SIZE > 256 | |
#error "RING_BUFFER_SIZE must be <=256" | |
#endif | |
typedef struct { | |
uint8_t data[RING_BUFFER_SIZE]; | |
uint8_t head; | |
uint8_t tail; | |
bool over; | |
} RingBuffer_t; | |
void Ring_Init(RingBuffer_t* const b) { | |
memset(b->data, 0, RING_BUFFER_SIZE); | |
b->head = 0; | |
b->tail = 0; | |
b->over = false; | |
} | |
bool Ring_PushTail(RingBuffer_t* const b, uint8_t value) { | |
if (b->over && (b->tail == b->head)) { | |
printf("ring push(%c) ERR over\n", value); | |
return false; | |
} | |
uint8_t next = (b->tail + 1) % RING_BUFFER_SIZE; | |
if (next == b->head) { | |
b->over = true; | |
} | |
b->data[b->tail] = value; | |
b->tail = next; | |
printf("ring push(%c) head=%d tail=%d next=%d over=%d\n", value, b->head, | |
b->tail, next, b->over); | |
return true; | |
} | |
bool Ring_PopHead(RingBuffer_t* const b, uint8_t* const out) { | |
if (!b->over && (b->tail == b->head)) { | |
printf("ring pop ERR empty head=%d tail=%d over=%d\n", b->head, b->tail, | |
b->over); | |
return false; | |
} | |
uint8_t next = (b->head + 1) % RING_BUFFER_SIZE; | |
*out = b->data[b->head]; | |
// b->data[b->head] = 0; | |
b->head = next; | |
b->over = false; | |
printf("ring pop out=%c head=%d tail=%d over=%d\n", *out, b->head, | |
b->tail, b->over); | |
return true; | |
} | |
void Ring_Debug(RingBuffer_t const* const b) { | |
printf("ring debug data=[%c%c%c%c] head=%d tail=%d over=%d content=[", | |
b->data[0]!=0?b->data[0]:'.', | |
b->data[1]!=0?b->data[1]:'.', | |
b->data[2]!=0?b->data[2]:'.', | |
b->data[3]!=0?b->data[3]:'.', | |
b->head, b->tail, b->over); | |
uint8_t h = b->head, t = b->tail, n = t - h; | |
if (b->over && (h == t)) { | |
n = RING_BUFFER_SIZE; | |
} else if (h > t) { | |
n = RING_BUFFER_SIZE - h + t; | |
} | |
for (uint8_t i = 0; i < n; i++) { | |
uint8_t j = (h + i) % RING_BUFFER_SIZE; | |
printf("%c", b->data[j]); | |
} | |
printf("]\n"); | |
} | |
int main() { | |
RingBuffer_t rb; | |
uint8_t v; | |
Ring_Init(&rb); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, '1'); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, '2'); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, 't'); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, '3'); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, '4'); | |
Ring_Debug(&rb); | |
Ring_PushTail(&rb, 'e'); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
Ring_PopHead(&rb, &v); | |
Ring_Debug(&rb); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment