diff options
author | rsiddharth <s@ricketyspace.net> | 2019-09-16 19:33:33 -0400 |
---|---|---|
committer | rsiddharth <s@ricketyspace.net> | 2020-04-17 20:56:34 -0400 |
commit | 97a4879bc88861b718a5a45b4515303a81923db0 (patch) | |
tree | 0c2b48cfdd9c33e67c6d14f39e813a5acb9226d3 /nserver | |
parent | 5b2da93ad7f12da9810aec90101b6ade12d7a99e (diff) |
nserver: Add ringbuffer.h
Diffstat (limited to 'nserver')
-rw-r--r-- | nserver/src/ringbuffer.c | 85 | ||||
-rw-r--r-- | nserver/src/ringbuffer.h | 61 |
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 |