Created
December 7, 2013 23:10
-
-
Save tkafka/7851091 to your computer and use it in GitHub Desktop.
OMG, ringbuffer in C macros :)
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 <stdlib.h> | |
#include <memory.h> | |
#include <malloc.h> | |
#ifndef _ringbuffer_h | |
#define _ringbuffer_h | |
// semantics: buffer goes from start to end-1, start == end -> empty or full, see 'full' flag | |
#define ringBuffer_typedef(T, NAME) \ | |
typedef struct { \ | |
int count; \ | |
int size; \ | |
int start; \ | |
int end; \ | |
bool full; \ | |
T* elems; \ | |
} NAME | |
#define ringBufferInit(BUF_PTR, BUF_LENGTH, BUF_ENTRY_TYPE, BUF_TYPE) \ | |
assert(BUF_LENGTH > 0); \ | |
BUF_TYPE t; \ | |
BUF_PTR = &t; \ | |
BUF_PTR->size = BUF_LENGTH; \ | |
BUF_PTR->count = 0; \ | |
BUF_PTR->start = 0; \ | |
BUF_PTR->end = 0; \ | |
BUF_PTR->full = false; \ | |
BUF_PTR->elems = (BUF_ENTRY_TYPE*)malloc(BUF_PTR->size * sizeof(BUF_ENTRY_TYPE)); \ | |
memset(BUF_PTR->elems, 0, BUF_PTR->size * sizeof(BUF_ENTRY_TYPE)) | |
#define ringBufferDestroy(BUF) free(BUF->elems) | |
#define ringBufferNextStartIndex(BUF) ((BUF->start + 1) % BUF->size) | |
#define ringBufferNextEndIndex(BUF) ((BUF->end + 1) % BUF->size) | |
#define ringBufferIsEmpty(BUF) (BUF->end == BUF->start && !BUF->full) | |
#define ringBufferIsFull(BUF) (BUF->full) | |
#define ringBufferReset(BUF, ELEM) \ | |
BUF->count = 0; \ | |
BUF->start = 0; \ | |
BUF->end = 0; \ | |
BUF->full = false | |
#define ringBufferWrite(BUF, ELEM) \ | |
BUF->elems[BUF->end] = ELEM; \ | |
BUF->end = ringBufferNextEndIndex(BUF); \ | |
if (!BUF->full) { \ | |
BUF->count++; \ | |
if (BUF->end == BUF->start) { \ | |
BUF->full = true; \ | |
} \ | |
} else { \ | |
BUF->start = ringBufferNextStartIndex(BUF); \ | |
} | |
#define ringBufferRead(BUF, I, ELEM) \ | |
assert(I < BUF->count); \ | |
ELEM = BUF->elems[(BUF->start + I) % BUF->size] | |
#define ringBufferForEach(BUF, item) \ | |
for(int keep = 1, \ | |
count = 0, \ | |
i = BUF->start;\ | |
keep && ((BUF->full) ? (count==0 || i != BUF->end) : i != BUF->end); \ | |
keep = !keep, i = (i + 1) % BUF->size, count++) \ | |
for(item = BUF->elems[i]; keep; keep = !keep) | |
#define ringBufferForEachRaw(BUF, item) \ | |
for(int keep = 1, \ | |
i = 0;\ | |
keep && i < BUF->size; \ | |
keep = !keep, i++) \ | |
for(item = BUF->elems[i]; keep; keep = !keep) | |
#endif | |
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 <SDKDDKVer.h> | |
#include <stdio.h> | |
#include <tchar.h> | |
#include <assert.h> | |
#include "lib/c-generic-ring-buffer/ringbuffer.h" | |
ringBuffer_typedef(int, IntBuffer); | |
void printIntBufferRaw(IntBuffer* buffer, char* message) { | |
int item; | |
printf("%s: (raw)[", message); | |
ringBufferForEachRaw(buffer, item) { | |
printf("%d ", item); | |
} | |
printf("]\n"); | |
} | |
void printIntBufferNice(IntBuffer* buffer, char* message) { | |
int item; | |
printf("%s: [", message); | |
ringBufferForEach(buffer, item) { | |
printf("%d ", item); | |
} | |
printf("]\n"); | |
} | |
void printIntBuffer(IntBuffer* buffer, char* message) { | |
printIntBufferNice(buffer, message); | |
printIntBufferRaw(buffer, message); | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
// Declare vars. | |
IntBuffer* myBuffer; | |
ringBufferInit(myBuffer, 4, int, IntBuffer); | |
printIntBuffer(myBuffer, "after init"); | |
ringBufferWrite(myBuffer, 1); | |
printIntBuffer(myBuffer, "after 1 item"); | |
ringBufferWrite(myBuffer, 2); | |
printIntBuffer(myBuffer, "after 2 items"); | |
ringBufferWrite(myBuffer, 3); | |
printIntBuffer(myBuffer, "after 3 items"); | |
ringBufferWrite(myBuffer, 4); | |
printIntBuffer(myBuffer, "after 4 items"); | |
int item; | |
ringBufferRead(myBuffer, 0, item); | |
printf("1st: %d\n", item); | |
assert(item == 1); | |
ringBufferRead(myBuffer, 1, item); | |
printf("2nd: %d\n", item); | |
assert(item == 2); | |
ringBufferRead(myBuffer, 2, item); | |
printf("3rd: %d\n", item); | |
assert(item == 3); | |
ringBufferRead(myBuffer, 3, item); | |
printf("4th: %d\n", item); | |
assert(item == 4); | |
ringBufferWrite(myBuffer, 5); | |
printIntBuffer(myBuffer, "after 5 items:"); | |
ringBufferWrite(myBuffer, 6); | |
printIntBuffer(myBuffer, "after 6 items:"); | |
ringBufferRead(myBuffer, 2, item); | |
assert(item == 5); | |
ringBufferRead(myBuffer, 3, item); | |
assert(item == 6); | |
ringBufferDestroy(myBuffer); | |
printf("All tests passed.\n"); | |
return 0; | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment