add circular buffer demo
parent
fbd7635089
commit
2e2a01e5ba
@ -0,0 +1,172 @@
|
||||
/* Circular buffer, using a counter to distinguish full from empty buffer. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#define debug_printf(fmt, ...) \
|
||||
do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
|
||||
|
||||
#define CB_SIZE 42
|
||||
|
||||
/* Types */
|
||||
|
||||
struct elem {
|
||||
int foo;
|
||||
};
|
||||
typedef struct elem elem_t;
|
||||
|
||||
struct cb {
|
||||
int count;
|
||||
int size;
|
||||
int start;
|
||||
int end;
|
||||
|
||||
elem_t * elems;
|
||||
};
|
||||
typedef struct cb cb_t;
|
||||
|
||||
|
||||
/* Helpers */
|
||||
|
||||
void dienomem() {
|
||||
fprintf(stderr, "ERROR: No memory?!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Operations */
|
||||
|
||||
void cb_init(cb_t * cb, int size) {
|
||||
cb->count = 0;
|
||||
cb->size = size;
|
||||
|
||||
cb->start = 0;
|
||||
|
||||
cb->elems = malloc(sizeof(elem_t)*size);
|
||||
if (!cb->elems)
|
||||
dienomem();
|
||||
}
|
||||
|
||||
void cb_free(cb_t * cb) {
|
||||
free(cb->elems);
|
||||
}
|
||||
|
||||
bool cb_is_full(cb_t * cb) {
|
||||
return (cb->count == cb->size);
|
||||
}
|
||||
|
||||
bool cb_is_empty(cb_t * cb) {
|
||||
return (cb->count == 0);
|
||||
}
|
||||
|
||||
int cb_count(cb_t * cb) {
|
||||
return cb->count;
|
||||
}
|
||||
|
||||
void cb_write(cb_t * cb, elem_t * elem) {
|
||||
int end = (cb->start + cb->count) % cb->size;
|
||||
cb->elems[end] = *elem;
|
||||
|
||||
if (cb_is_full(cb))
|
||||
/* We have just overwritten the first element of the buffer,
|
||||
* therefore move the start. */
|
||||
cb->start = (cb->start + 1) % cb->size;
|
||||
else
|
||||
cb->count++;
|
||||
}
|
||||
|
||||
bool cb_read(cb_t * cb, elem_t * elem) {
|
||||
if (!cb_is_empty(cb)) {
|
||||
*elem = cb->elems[cb->start];
|
||||
cb->start = (cb->start + 1) % cb->size;
|
||||
cb->count--;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test it. */
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/* Initialize empty CB_SIZE-element circular buffer. */
|
||||
cb_t *test_cb = malloc(sizeof(cb_t));
|
||||
if (!test_cb)
|
||||
dienomem();
|
||||
cb_init(test_cb, CB_SIZE);
|
||||
|
||||
/* Should be empty. */
|
||||
assert(cb_is_empty(test_cb) == true);
|
||||
assert(cb_is_full(test_cb) == false);
|
||||
|
||||
/* Add one element. */
|
||||
elem_t *one = malloc(sizeof(elem_t));
|
||||
one->foo = 23;
|
||||
cb_write(test_cb, one);
|
||||
free(one);
|
||||
assert(cb_is_empty(test_cb) == false);
|
||||
|
||||
/* Read the one element. */
|
||||
elem_t *oneback = malloc(sizeof(elem_t));
|
||||
cb_read(test_cb, oneback);
|
||||
assert(oneback->foo == 23);
|
||||
free(oneback);
|
||||
assert(cb_is_empty(test_cb) == true);
|
||||
|
||||
/* Fill the buffer. */
|
||||
elem_t *e = malloc(sizeof(elem_t));
|
||||
for (int i = 1; i <= CB_SIZE; i++) {
|
||||
e->foo = i;
|
||||
cb_write(test_cb, e);
|
||||
}
|
||||
assert(cb_is_empty(test_cb) == false);
|
||||
assert(cb_is_full(test_cb) == true);
|
||||
assert(cb_count(test_cb) == CB_SIZE);
|
||||
|
||||
/* Add another element. */
|
||||
e->foo = CB_SIZE + 1;
|
||||
cb_write(test_cb, e);
|
||||
assert(cb_is_empty(test_cb) == false);
|
||||
assert(cb_is_full(test_cb) == true);
|
||||
assert(cb_count(test_cb) == CB_SIZE);
|
||||
|
||||
/* Read all elements and check their values. */
|
||||
for (int i = 2; i <= CB_SIZE + 1; i++) {
|
||||
bool rc = cb_read(test_cb, e);
|
||||
assert(rc == true);
|
||||
debug_printf("e->foo == %d\n", e->foo);
|
||||
assert(e->foo == i);
|
||||
}
|
||||
assert(cb_is_empty(test_cb) == true);
|
||||
|
||||
/* Should not be possible to read a value now. */
|
||||
bool rc = cb_read(test_cb, e);
|
||||
assert(rc == false);
|
||||
assert(cb_is_empty(test_cb) == true);
|
||||
assert(cb_count(test_cb) == 0);
|
||||
|
||||
/* Fill the buffer - twice. */
|
||||
for (int i = 1; i <= CB_SIZE * 2; i++) {
|
||||
e->foo = i;
|
||||
cb_write(test_cb, e);
|
||||
}
|
||||
assert(cb_is_empty(test_cb) == false);
|
||||
assert(cb_is_full(test_cb) == true);
|
||||
assert(cb_count(test_cb) == CB_SIZE);
|
||||
|
||||
/* Read all elements and check their values. */
|
||||
for (int i = CB_SIZE + 1; i <= CB_SIZE * 2; i++) {
|
||||
bool rc = cb_read(test_cb, e);
|
||||
assert(rc == true);
|
||||
assert(e->foo == i);
|
||||
}
|
||||
assert(cb_is_empty(test_cb) == true);
|
||||
|
||||
/* Free buffer etc. */
|
||||
free(e);
|
||||
cb_free(test_cb);
|
||||
free(test_cb);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#include <assert.h>
|
||||
|
||||
struct test {
|
||||
int foo;
|
||||
};
|
||||
typedef struct test test_t;
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
test_t a = { 23 };
|
||||
test_t b = { 42 };
|
||||
|
||||
a = b;
|
||||
assert(a.foo == 42);
|
||||
assert(b.foo == 42);
|
||||
|
||||
a.foo = 69;
|
||||
assert(a.foo == 69);
|
||||
assert(b.foo == 42);
|
||||
}
|
Loading…
Reference in New Issue