From 9f25faad5fe732e498942818dc45de78ce7f3766 Mon Sep 17 00:00:00 2001 From: Olivier Gayot Date: Tue, 17 Dec 2013 21:03:39 +0100 Subject: rb: add a first version of the library first working version of the library. the binary stuff is included. we can write to and read from a ring buffer. --- Makefile | 34 +++++++++++++++++++ rb.h | 49 ++++++++++++++++++++++++++++ src/rb.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 Makefile create mode 100644 rb.h create mode 100644 src/rb.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..62eefa6 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +CC ?= gcc +CFLAGS += -W -Wall -std=c99 -Wextra +CFLAGS += -I./ +CFLAGS += -D _GNU_SOURCE +NAME = librb.a +SRC = src/rb.c + +AR = ar rc + +all: depend $(NAME) + +depend: .depend + +.depend: $(SRC) + @$(RM) .depend + @$(CC) $(CFLAGS) -MM $^ > .depend + +include .depend + +OBJ = $(SRC:.c=.o) + +$(NAME): $(OBJ) + $(AR) $(NAME) $(OBJ) + ranlib $(NAME) + +clean: + $(RM) $(OBJ) + +fclean: clean + $(RM) $(NAME) + +re: fclean all + +.PHONY: all depend clean fclean all re diff --git a/rb.h b/rb.h new file mode 100644 index 0000000..f66dba8 --- /dev/null +++ b/rb.h @@ -0,0 +1,49 @@ +#ifndef RING_BUFFER_H +#define RING_BUFFER_H + +#include +#include + +typedef struct t_ring_buffer { + char buffer[8192]; + + uint16_t off_r; + uint16_t off_w; + + size_t size_filled; +} t_ring_buffer; + +typedef t_ring_buffer t_rb; + +static inline size_t rb_get_size(const t_rb *rb) +{ + return sizeof(rb->buffer); +} + +/* + * initializes rb with default values. + * returns 0 on success + */ +int rb_init(t_rb *rb); + +/* returns an initialized newly allocated ring buffer */ +__attribute((malloc)) t_rb *rb_new(void); + +void rb_delete(t_rb **); + +/* put n bytes of src into the ring buffer pointed by rb */ +t_rb *rb_put(t_rb *rb, const void *src, size_t n); + +/* + * take at most n bytes from the ring buffer pointed by rb and + * put them into dest + */ +size_t rb_get(t_rb *rb, void *dest, size_t n); + +/* + * like rb_get but does not modify the ring_buffer (the bytes are kept + * in the ring_buffer) + */ +size_t rb_peek(const t_rb *ring_buffer, void *dest, size_t size); + +#endif /* RING_BUFFER_H */ diff --git a/src/rb.c b/src/rb.c new file mode 100644 index 0000000..505c373 --- /dev/null +++ b/src/rb.c @@ -0,0 +1,112 @@ +#include +#include + +#include "rb.h" + +#define MAX(_x1, _x2) (((_x1) > (_x2)) ? (_x1) : (_x2)) +#define MIN(_x1, _x2) (((_x1) < (_x2)) ? (_x1) : (_x2)) + +int rb_init(t_rb *rb) +{ + rb->off_r = 0; + rb->off_w = 0; + rb->size_filled = 0; + + return 0; +} + +t_rb *rb_new(void) +{ + t_rb *rb; + + if ((rb = malloc(sizeof(t_rb))) == NULL) { + return NULL; + } + + rb_init(rb); + + return rb; +} + +void rb_delete(t_rb **rb) +{ + free(*rb); + *rb = NULL; +} + +t_rb *rb_put(t_rb *rb, const void *src, size_t n) +{ + size_t size; + + /* loop until n bytes of src have been written */ + while (n != 0) { + size = MIN(n, rb_get_size(rb) - rb->off_w); + + memcpy(&rb->buffer[rb->off_w], src, size); + + /* if we overrided the data to read, we need to move off_r */ + if (rb->off_w < rb->off_r && rb->off_w + size > rb->off_r) { + rb->off_r = (rb->off_w + size) % rb_get_size(rb); + } else if (rb->off_r == rb->off_w + && rb->size_filled == rb_get_size(rb)) + { + rb->off_r = (rb->off_w + size) % rb_get_size(rb); + } + + /* this will put the offset back to 0 if we reached the end */ + rb->off_w = (rb->off_w + size) % rb_get_size(rb); + + n -= size; + src += size; + + rb->size_filled += size; + rb->size_filled = MIN(rb->size_filled, rb_get_size(rb)); + } + + return rb; +} + +size_t rb_get(t_rb *rb, void *dest, size_t n) +{ + size_t size = rb_peek(rb, dest, n); + + rb->size_filled -= size; + rb->off_r = (rb->off_r + size) % rb_get_size(rb); + + if (rb->size_filled == 0) { + /* optimize space */ + rb->off_w = rb->off_r = 0; + } + + return size; +} + +size_t rb_peek(const t_rb *rb, void *dest, size_t n) +{ + uint16_t offset; + size_t size; + size_t size2; + + if (rb->size_filled == 0 || n == 0) { + return 0; + } + + size = 0; + if (rb->off_r >= rb->off_w) { + /* do not try to retrieve too much data */ + size = MIN(n, rb_get_size(rb) - rb->off_r); + + memcpy(dest, &rb->buffer[rb->off_r], size); + + dest += size; + n -= size; + } + + offset = (rb->off_r + size) % rb_get_size(rb); + + size2 = MIN(n, (size_t)(rb->off_w - offset)); + + memcpy(dest, &rb->buffer[offset], size2); + + return size + size2; +} -- cgit v1.2.3