summaryrefslogtreecommitdiff
path: root/src/kitringbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kitringbuffer.c')
-rw-r--r--src/kitringbuffer.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/kitringbuffer.c b/src/kitringbuffer.c
new file mode 100644
index 0000000..7f97441
--- /dev/null
+++ b/src/kitringbuffer.c
@@ -0,0 +1,158 @@
+/*
+ * Ringbuffer
+ *
+ * Copyright (c) 2016, Tuomas Virtanen
+ * license: MIT; see LICENSE for details.
+*/
+
+#include "kitchensink/internal/kitringbuffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+/**
+ * Creates a new ringbuffer with the given size.
+ * @param size Size for the new ringbuffer
+ * @return Ringbuffer handle
+ */
+Kit_RingBuffer* Kit_CreateRingBuffer(unsigned int size) {
+ Kit_RingBuffer *rb = calloc(1, sizeof(Kit_RingBuffer));
+ rb->size = size;
+ rb->data = malloc(size);
+ return rb;
+}
+
+/**
+ * Deletes the given ringbuffer.
+ * @param rb Ringbuffer to be deleted.
+ */
+void Kit_DestroyRingBuffer(Kit_RingBuffer* rb) {
+ assert(rb != NULL);
+ free(rb->data);
+ free(rb);
+}
+
+/**
+ * Writes to the given ringbuffer. If given length is larger than the amount
+ * the ringbuffer can fit, only the data that fits will be written.
+ * @param rb Ringbuffer to write to.
+ * @param data Data to write
+ * @param len Data length
+ * @return Amount of data that was actually written.
+ */
+int Kit_WriteRingBuffer(Kit_RingBuffer *rb, const char* data, int len) {
+ int k;
+ len = (len > (rb->size - rb->len)) ? (rb->size - rb->len) : len;
+ if(rb->len < rb->size) {
+ if(len + rb->wpos > rb->size) {
+ k = (len + rb->wpos) % rb->size;
+ memcpy((rb->data + rb->wpos), data, len - k);
+ memcpy(rb->data, data+(len-k), k);
+ } else {
+ memcpy((rb->data + rb->wpos), data, len);
+ }
+ rb->len += len;
+ rb->wpos += len;
+ if(rb->wpos >= rb->size) {
+ rb->wpos = rb->wpos % rb->size;
+ }
+ return len;
+ }
+ return 0;
+}
+
+/**
+ * Reads data from ringbuffer. If ringbuffer has less data than was requested,
+ * only the available data will be read.
+ * @param rb Ringbuffer to read from.
+ * @param data Buffer to read into.
+ * @param len How much data do we want
+ * @return Amount of data that was actually read.
+ */
+int Kit_ReadRingBuffer(Kit_RingBuffer *rb, char* data, int len) {
+ int k;
+ len = (len > rb->len) ? rb->len : len;
+ if(rb->len > 0) {
+ if(len + rb->rpos > rb->size) {
+ k = (len + rb->rpos) % rb->size;
+ memcpy(data, (rb->data + rb->rpos), len-k);
+ memcpy(data+(len-k), (rb->data), k);
+ } else {
+ memcpy(data, (rb->data + rb->rpos), len);
+ }
+ rb->len -= len;
+ rb->rpos += len;
+ if(rb->rpos >= rb->size) {
+ rb->rpos = rb->rpos % rb->size;
+ }
+ return len;
+ }
+ return 0;
+}
+
+/**
+ * Peeks into the given ringbuffer. Technically same as rb_read, but does not advance
+ * the internal position pointer. In other words, you may peek as many times as you wish,
+ * and will always get the same data.
+ * @param rb Ringbuffer to peek into.
+ * @param data Buffer to read into
+ * @param len How much data do we need
+ * @return Amount of data actually read
+ */
+int Kit_PeekRingBuffer(const Kit_RingBuffer *rb, char* data, int len) {
+ int k;
+ len = (len > rb->len) ? rb->len : len;
+ if(rb->len > 0) {
+ if(len + rb->rpos > rb->size) {
+ k = (len + rb->rpos) % rb->size;
+ memcpy(data, (rb->data + rb->rpos), len-k);
+ memcpy(data+(len-k), (rb->data), k);
+ } else {
+ memcpy(data, (rb->data + rb->rpos), len);
+ }
+ return len;
+ }
+ return 0;
+}
+
+/**
+ * Advances the internal position counter by given amount. Note that counter can only be
+ * advanced by the amount of unreadable data in ringbuffer.
+ * @param rb Ringbuffer to handle
+ * @param len How much should the position counter be increased
+ * @return How much the position counter was actually increased.
+ */
+int Kit_AdvanceRingBuffer(Kit_RingBuffer *rb, int len) {
+ len = (len > rb->len) ? rb->len : len;
+ if(rb->len > 0) {
+ rb->len -= len;
+ rb->rpos += len;
+ if(rb->rpos >= rb->size) {
+ rb->rpos = rb->rpos % rb->size;
+ }
+ return len;
+ }
+ return 0;
+}
+
+/**
+ * Returns the current length of the Ringbuffer. In other words, how much data
+ * the ringbuffer contains
+ * @param rb Ringbuffer to handle
+ * @return Data in ringbuffer (in bytes).
+ */
+int Kit_GetRingBufferLength(const Kit_RingBuffer *rb) {
+ return rb->len;
+}
+
+/**
+ * Returns the size of the ringbuffer. In other words, the maximum amount of data
+ * the ringbuffer can hold.
+ * @param rb Ringbuffer to handle
+ * @return Size of the ringbuffer
+ */
+int Kit_GetRingBufferSize(const Kit_RingBuffer *rb) {
+ return rb->size;
+}