commit e4a531530e3516e886dbb723e1aa501dfe348fef Author: Mathieu Maret Date: Wed May 26 00:32:25 2021 +0200 Add Ring Buffer implementation diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..131b6e4 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# Preproc options +# -MMD is used to generate .d files for user header dependencies (use -MD for system and user header instead) +CPPFLAGS = -MMD +# main compilation +CFLAGS ?= -Werror -Wall #$(shell pkg-config --cflags sdl) +# C++ flags +CXXFLAGS = +#Linker flags +LDFLAGS = +#Linker path +LDLIBS = #$(shell pkg-config --libs sdl) + +ifneq ($(CROSS_COMPILE),) + CC :=$(CROSS_COMPILE)$(CC) + CXX :=$(CROSS_COMPILE)$(CXX) + LD :=$(CROSS_COMPILE)$(LD) +endif + +bin = main +lib = libringbuffer.so + +#Will be compiled with -fpic +lib_src = ringbuffer.c +lib_obj = $(lib_src:%.c=%.o) +lib_dep = $(lib_src:%.c=%.d) + +sources = $(filter-out $(lib_src), $(wildcard *.c)) +objects = $(sources:%.c=%.o) +depends = $(sources:%.c=%.d) + +all: $(bin) $(lib) + +$(bin): $(objects) $(lib) + + +$(lib): CFLAGS += -fpic +$(lib): $(lib_obj) + +%.so: + $(LINK.c) -shared $^ $(LDLIBS) -o $@ + +.PHONY: clean +clean: + $(RM) $(bin) $(objects) $(depends) $(lib) $(lib_obj) $(lib_dep) + +ifneq ($(MAKECMDGOALS),clean) +-include $(depends) +-include $(lib_dep) +endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..3ef9858 --- /dev/null +++ b/main.c @@ -0,0 +1,45 @@ +#include "ringbuffer.h" +#include +#include + +int main(int argc, char *argv[]) +{ + ringbuffer_t inst = ringbuffer_create(4); + ringbuffer_debug(inst); + uint8_t item; + assert(ringbuffer_enqueue(inst, 1)); + ringbuffer_debug(inst); + assert(ringbuffer_enqueue(inst, 2)); + ringbuffer_debug(inst); + assert(ringbuffer_enqueue(inst, 3)); + ringbuffer_debug(inst); + assert(ringbuffer_enqueue(inst, 4)); + ringbuffer_debug(inst); + assert(ringbuffer_enqueue(inst, 5) == false); + ringbuffer_debug(inst); + assert(ringbuffer_dequeue(inst, &item)); + assert(item == 1); + ringbuffer_debug(inst); + assert(ringbuffer_enqueue(inst, 5)); + ringbuffer_debug(inst); + + assert(ringbuffer_dequeue(inst, &item)); + assert(item == 2); + ringbuffer_debug(inst); + + assert(ringbuffer_dequeue(inst, &item)); + assert(item == 3); + ringbuffer_debug(inst); + + assert(ringbuffer_dequeue(inst, &item)); + assert(item == 4); + ringbuffer_debug(inst); + + assert(ringbuffer_dequeue(inst, &item)); + assert(item == 5); + ringbuffer_debug(inst); + + assert(ringbuffer_dequeue(inst, &item) == false); + ringbuffer_debug(inst); + return 0; +} diff --git a/ringbuffer.c b/ringbuffer.c new file mode 100644 index 0000000..bd6a253 --- /dev/null +++ b/ringbuffer.c @@ -0,0 +1,87 @@ +#include "ringbuffer.h" +#include +#include + +struct ringbuffer_instance_t { + int32_t wr_pos; + int32_t rd_pos; + uint8_t *data; + uint32_t capacity; + bool full; +}; + +ringbuffer_t ringbuffer_create(uint32_t capacity) +{ + ringbuffer_t inst = calloc(1, sizeof(struct ringbuffer_instance_t)); + inst->data = calloc(capacity, sizeof(uint8_t)); + inst->capacity = capacity; + inst->wr_pos = 0; + inst->rd_pos = 0; + inst->full = capacity == 0; + + return inst; +} + +uint32_t ringbuffer_capacity(ringbuffer_t instance) +{ + return instance->capacity; +} + +uint32_t ringbuffer_used(ringbuffer_t instance) +{ + if (instance->full) + return instance->capacity; + + return (instance->wr_pos - instance->rd_pos) % instance->capacity; +} + +bool ringbuffer_empty(ringbuffer_t instance) +{ + return (!instance->full && (instance->wr_pos == instance->rd_pos)); +} + +bool ringbuffer_full(ringbuffer_t instance) +{ + return instance->full; +} + +bool ringbuffer_enqueue(ringbuffer_t instance, uint8_t item) +{ + if (ringbuffer_full(instance)) + return false; + + instance->data[instance->wr_pos] = item; + instance->wr_pos = (instance->wr_pos + 1) % instance->capacity; + if (instance->rd_pos == instance->wr_pos) + instance->full = true; + + return true; +} + +bool ringbuffer_dequeue(ringbuffer_t instance, uint8_t *item) +{ + if (ringbuffer_empty(instance)) + return false; + + instance->full = false; + *item = instance->data[instance->rd_pos]; + instance->rd_pos = (instance->rd_pos + 1) % instance->capacity; + + return true; +} + +void ringbuffer_destroy(ringbuffer_t instance) +{ + if (instance) { + if (instance->data) { + free(instance->data); + } + free(instance); + } +} + +void ringbuffer_debug(ringbuffer_t instance) +{ + printf("%d/%d %d %d %s\n", ringbuffer_used(instance), ringbuffer_capacity(instance), + instance->wr_pos, instance->rd_pos, instance->full ? "(full)" : ""); +} diff --git a/ringbuffer.h b/ringbuffer.h new file mode 100644 index 0000000..4b67631 --- /dev/null +++ b/ringbuffer.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +typedef struct ringbuffer_instance_t* ringbuffer_t; + +ringbuffer_t ringbuffer_create(uint32_t capacity); +uint32_t ringbuffer_capacity(ringbuffer_t instance); +uint32_t ringbuffer_used(ringbuffer_t instance); +bool ringbuffer_enqueue(ringbuffer_t instance, uint8_t item); +bool ringbuffer_dequeue(ringbuffer_t instance, uint8_t* item); +void ringbuffer_destroy(ringbuffer_t instance); +void ringbuffer_debug(ringbuffer_t instance); +bool ringbuffer_empty(ringbuffer_t instance); +bool ringbuffer_full(ringbuffer_t instance);