diff options
author | Olivier Gayot <duskcoder@gmail.com> | 2013-12-17 21:03:39 +0100 |
---|---|---|
committer | Olivier Gayot <duskcoder@gmail.com> | 2014-01-18 13:43:46 +0100 |
commit | 9f25faad5fe732e498942818dc45de78ce7f3766 (patch) | |
tree | ab8a1c13ed05c02a732601d13b1f95b5f2c4e791 /src | |
parent | 6d88b62a73c7c4985d07317e3fe00f84743c4700 (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/rb.c | 112 |
1 files changed, 112 insertions, 0 deletions
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 <stdlib.h> +#include <string.h> + +#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; +} |