summaryrefslogtreecommitdiff
path: root/src/rb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rb.c')
-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;
+}