summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOlivier Gayot <duskcoder@gmail.com>2013-12-17 21:03:39 +0100
committerOlivier Gayot <duskcoder@gmail.com>2014-01-18 13:43:46 +0100
commit9f25faad5fe732e498942818dc45de78ce7f3766 (patch)
treeab8a1c13ed05c02a732601d13b1f95b5f2c4e791 /src
parent6d88b62a73c7c4985d07317e3fe00f84743c4700 (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.c112
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;
+}