aboutsummaryrefslogtreecommitdiff
path: root/src/std/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/std/buffer.c')
-rw-r--r--src/std/buffer.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/std/buffer.c b/src/std/buffer.c
new file mode 100644
index 0000000..f32c515
--- /dev/null
+++ b/src/std/buffer.c
@@ -0,0 +1,62 @@
+#include "../../include/std/buffer.h"
+#include "../../include/std/alloc.h"
+#include "../../include/std/mem.h"
+#include "../../include/std/scoped_allocator.h"
+#include <assert.h>
+
+int buffer_init(Buffer *self, struct ScopedAllocator *allocator) {
+ self->data = NULL;
+ self->size = 0;
+ self->capacity = 0;
+ if(allocator)
+ return scoped_allocator_add_buffer(allocator, self);
+ return 0;
+}
+
+static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity) {
+ usize capacity;
+ void *new_mem;
+ int alloc_result;
+
+ if(self->capacity >= new_capacity)
+ return BUFFER_OK;
+
+ capacity = self->capacity;
+ if(capacity == 0) {
+ capacity = new_capacity;
+ } else {
+ while(capacity < new_capacity) {
+ capacity *= 1.5;
+ }
+ }
+
+ alloc_result = am_realloc(self->data, capacity, &new_mem);
+ if(alloc_result != ALLOC_OK)
+ return BUFFER_ALLOC_FAIL;
+
+ self->data = new_mem;
+ self->capacity = capacity;
+ return BUFFER_OK;
+}
+
+int buffer_append(Buffer *self, void *data, usize size) {
+ return_if_error(buffer_ensure_capacity(self, self->size + size));
+ am_memcpy(self->data + self->size, data, size);
+ self->size += size;
+ return BUFFER_OK;
+}
+
+void* buffer_get(Buffer *self, usize index, usize type_size) {
+ usize real_index;
+ real_index = index * type_size;
+ assert(real_index < self->size);
+ return &self->data[real_index];
+}
+
+int buffer_pop(Buffer *self, void *data, usize size) {
+ if(size > self->size)
+ return -1;
+ am_memcpy(data, &self->data[self->size - size], size);
+ self->size -= size;
+ return 0;
+} \ No newline at end of file