summaryrefslogtreecommitdiffstats
path: root/nserver
diff options
context:
space:
mode:
authorrsiddharth <s@ricketyspace.net>2019-09-16 19:33:33 -0400
committerrsiddharth <s@ricketyspace.net>2020-04-17 20:56:34 -0400
commit97a4879bc88861b718a5a45b4515303a81923db0 (patch)
tree0c2b48cfdd9c33e67c6d14f39e813a5acb9226d3 /nserver
parent5b2da93ad7f12da9810aec90101b6ade12d7a99e (diff)
nserver: Add ringbuffer.h
Diffstat (limited to 'nserver')
-rw-r--r--nserver/src/ringbuffer.c85
-rw-r--r--nserver/src/ringbuffer.h61
2 files changed, 146 insertions, 0 deletions
diff --git a/nserver/src/ringbuffer.c b/nserver/src/ringbuffer.c
new file mode 100644
index 0000000..a2dc97f
--- /dev/null
+++ b/nserver/src/ringbuffer.c
@@ -0,0 +1,85 @@
+#undef NDEBUG
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dbg.h>
+#include <ringbuffer.h>
+
+RingBuffer *RingBuffer_create(int length)
+{
+ RingBuffer *buffer = calloc(1, sizeof(RingBuffer));
+ buffer->length = length + 1;
+ buffer->start = 0;
+ buffer->end = 0;
+ buffer->buffer = calloc(buffer->length, 1);
+
+ return buffer;
+}
+
+void RingBuffer_destroy(RingBuffer *buffer)
+{
+ if (buffer) {
+ free(buffer->buffer);
+ free(buffer);
+ }
+}
+
+int RingBuffer_write(RingBuffer *buffer, char *data, int length)
+{
+ if (RingBuffer_available_data(buffer) == 0) {
+ buffer->start = buffer->end = 0;
+ }
+
+ check(length <= RingBuffer_available_space(buffer),
+ "Not enough space: %d request, %d available",
+ RingBuffer_available_data(buffer), length);
+
+ void *result = memcpy(RingBuffer_ends_at(buffer), data, length);
+ check(result != NULL, "Failed to write data into buffer");
+
+ RingBuffer_commit_write(buffer, length);
+
+ return length;
+ error:
+ return -1;
+}
+
+int RingBuffer_read(RingBuffer *buffer, char *target, int amount)
+{
+ check_debug(amount <= RingBuffer_available_data(buffer),
+ "Not enough in the buffer: has %d, needs %d",
+ RingBuffer_available_data(buffer), amount);
+
+ void *result = memcpy(target, RingBuffer_starts_at(buffer), amount);
+ check(result != NULL, "Failed to write buffer into data.");
+
+ RingBuffer_commit_read(buffer, amount);
+
+ if (buffer->end == buffer->start) {
+ buffer->start = buffer->end = 0;
+ }
+
+ return amount;
+ error:
+ return -1;
+}
+
+bstring RingBuffer_gets(RingBuffer *buffer, int amount)
+{
+ check(amount > 0, "Need more than 0 for gets, you gave: %d",
+ amount);
+ check_debug(amount <= RingBuffer_available_data(buffer),
+ "Not enough in the buffer");
+
+ bstring result = blk2bstr(RingBuffer_starts_at(buffer), amount);
+ check(result != NULL, "Failed to create gets result.");
+ check(blength(result) == amount, "Wrong result length.");
+
+ RingBuffer_commit_read(buffer, amount);
+ assert(RingBuffer_available_data(buffer) >= 0
+ && "Error in read commit");
+ return result;
+ error:
+ return NULL;
+}
diff --git a/nserver/src/ringbuffer.h b/nserver/src/ringbuffer.h
new file mode 100644
index 0000000..154abc3
--- /dev/null
+++ b/nserver/src/ringbuffer.h
@@ -0,0 +1,61 @@
+#ifndef _RingBuffer_h
+#define _RingBuffer_h
+
+#include <bstrlib.h>
+
+typedef struct {
+ char *buffer;
+ int length;
+ int start;
+ int end;
+} RingBuffer;
+
+RingBuffer *RingBuffer_create(int length);
+
+void RingBuffer_destroy(RingBuffer *buffer);
+
+int RingBuffer_read(RingBuffer *buffer, char *target, int amount);
+
+int RingBuffer_write(RingBuffer *buffer, char *data, int length);
+
+int RingBuffer_empty(RingBuffer *buffer);
+
+int RingBuffer_full(RingBuffer *buffer);
+
+int RingBuffer_available_data(RingBuffer *buffer);
+
+int RingBuffer_available_space(RingBuffer *buffer);
+
+bstring RingBuffer_gets(RingBuffer *buffer, int amount);
+
+#define RingBuffer_available_data(B) (\
+ ((B)->end + 1) % (B)->length - (B)->start - 1)
+
+#define RingBuffer_available_space(B) (\
+ (B)->length - (B)->end - 1)
+
+#define RingBuffer_full(B) (RingBuffer_available_data((B))\
+ - (B)->length == 0)
+
+#define RingBuffer_empty(B) (\
+ RingBuffer_available_data((B)) == 0)
+
+#define RingBuffer_puts(B, D) RingBuffer_write(\
+ (B), bdata((D)), blength((D)))
+
+#define RingBuffer_get_all(B) RingBuffer_gets(\
+ (B), RingBuffer_available_data((B)))
+
+#define RingBuffer_starts_at(B) (\
+ (B)->buffer + (B)->start)
+
+#define RingBuffer_ends_at(B) (\
+ (B)->buffer + (B)->end)
+
+#define RingBuffer_commit_read(B,A) (\
+ (B)->start = ((B)->start + (A)) % (B)->length)
+
+#define RingBuffer_commit_write(B, A) (\
+ (B)->end = ((B)->end + (A)) % (B)->length)
+
+#endif