#include "../../include/std/buffer.h" #include "../../include/std/alloc.h" #include "../../include/std/mem.h" #include "../../include/std/arena_allocator.h" #include int buffer_init(Buffer *self, struct ArenaAllocator *allocator) { self->data = NULL; self->size = 0; self->capacity = 0; self->allocator = allocator; if(allocator) { return arena_allocator_add_mem(allocator, &self->allocator_index); } else { self->allocator_index = ~(usize)0; return 0; } } void buffer_deinit(Buffer *self) { assert(!self->allocator && "Can't deinit buffer if it has an allocator"); am_free(self->data); self->data = NULL; self->size = 0; self->capacity = 0; } static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity) { usize capacity; void *new_mem; if(self->capacity >= new_capacity) return BUFFER_OK; capacity = self->capacity; if(capacity == 0) capacity = 8; while(capacity < new_capacity) { capacity += (capacity >> 1); } if(am_realloc(self->data, capacity, &new_mem) != ALLOC_OK) return BUFFER_ALLOC_FAIL; self->data = new_mem; self->capacity = capacity; /* Update list of buffers in the allocator with the new address of the buffer data */ if(self->allocator) am_memcpy(self->allocator->mems.data + self->allocator_index, &self->data, sizeof(void*)); return BUFFER_OK; } int buffer_append(Buffer *self, const void *data, usize size) { assert(data); return_if_error(buffer_ensure_capacity(self, self->size + size)); am_memcpy(self->data + self->size, data, size); self->size += size; return BUFFER_OK; } int buffer_append_empty(Buffer *self, usize size) { return_if_error(buffer_ensure_capacity(self, self->size + size)); self->size += size; return BUFFER_OK; } int buffer_expand(Buffer *self, usize size) { return buffer_ensure_capacity(self, self->size + size); } 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; } void buffer_clear(Buffer *self) { self->size = 0; } int buffer_set_capacity(Buffer *self, usize new_capacity) { if(am_realloc(self->data, new_capacity, (void**)&self->data) != ALLOC_OK) return BUFFER_ALLOC_FAIL; self->capacity = new_capacity; if(self->size < self->capacity) self->size = self->capacity; /* Update list of buffers in the allocator with the new address of the buffer data */ if(self->allocator) am_memcpy(self->allocator->mems.data + self->allocator_index, &self->data, sizeof(void*)); return BUFFER_OK; } void* buffer_begin(Buffer *self) { return self->data; } void *buffer_end(Buffer *self) { return self->data + self->size; } usize __buffer_get_size(Buffer *self, usize type_size) { assert(type_size != 0); return self->size / type_size; }