#ifndef RINGBUFFER_C #define RINGBUFFER_C #include "ringbuffer.h" #include "../memory.c" #define ERROR(msg) \ do { \ /* TODO Do something error-ish */ \ } while(0) #define ASSERT_NONNULL_ARG(argument) { \ if (argument == NULL) { \ ERROR(__func__ " got NULL for argument '" #argument "'"); \ } \ } struct ringbuffer* rbfr_create(const int capacity, void (*const destroy_element)(void*)) { ASSERT_NONNULL_ARG(destroy_element); struct ringbuffer* const this = alloc(sizeof (struct ringbuffer)); this->buffer = alloc(capacity * sizeof (void*)); this->buffer_n = capacity; this->size = 0; this->head = 0; this->destroy_element = destroy_element; return this; } void rbfr_destroy(struct ringbuffer* const this) { ASSERT_NONNULL_ARG(this); rbfr_clear(this); free(this->buffer); this->buffer = NULL; free(this); } int rbfr_size(const struct ringbuffer* const this) { ASSERT_NONNULL_ARG(this); return this->size; } int rbfr_capacity(const struct ringbuffer* this) { ASSERT_NONNULL_ARG(this); return this->buffer_n; } void rbfr_enqueue(struct ringbuffer* this, void* const element) { ASSERT_NONNULL_ARG(this); if (this->buffer_n == 0) { return; } int index = this->head + this->size; if (index >= this->buffer_n) { index -= this->buffer_n; } this->buffer[index] = element; if (this->size < this->buffer_n) { this->size++; } else { this->head++; } return; } bool rbfr_peek(const struct ringbuffer *const this, void** element) { ASSERT_NONNULL_ARG(this); ASSERT_NONNULL_ARG(element); if (this->size == 0) { return false; } *element = this->buffer[this->head]; return true; } bool rbfr_dequeue(struct ringbuffer *const this, void** element) { ASSERT_NONNULL_ARG(this); ASSERT_NONNULL_ARG(element); if (!rbfr_peek(this, element)) { return false; } this->size--; this->head++; if (this->head >= this->buffer_n) { this->head = 0; } return true; } void rbfr_clear(struct ringbuffer* this) { ASSERT_NONNULL_ARG(this); void* element; while (rbfr_dequeue(this, &element)) { this->destroy_element(element); } } #endif // RINGBUFFER_C