diff -r bf6cf4dd847a -r f84805e6df03 project_files/frontlib/util/buffer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/frontlib/util/buffer.c Sat Jun 09 03:28:38 2012 +0200 @@ -0,0 +1,90 @@ +#include "buffer.h" +#include "logging.h" + +#include +#include +#include + +typedef struct _flib_vector { + void *data; + size_t size; + size_t capacity; +} _flib_vector; + +flib_vector flib_vector_create() { + flib_vector result = malloc(sizeof(_flib_vector)); + if(result == NULL) { + return NULL; + } + result->data = malloc(16); + if(result->data == NULL) { + free(result); + return NULL; + } + result->size = 0; + result->capacity = 16; + return result; +} + +void flib_vector_destroy(flib_vector *vec) { + if(vec && *vec) { + free((*vec)->data); + free(*vec); + *vec = NULL; + } +} + +static void try_realloc(flib_vector vec, size_t newCapacity) { + void *newData = realloc(vec->data, newCapacity); + if(newData) { + vec->data = newData; + vec->capacity = newCapacity; + } +} + +static size_t getFreeCapacity(flib_vector vec) { + return vec->capacity - vec->size; +} + +int flib_vector_append(flib_vector vec, const void *data, size_t len) { + if(getFreeCapacity(vec) < len) { + // Resize exponentially for constant amortized time, + // But at least by as much as we need of course, + // and be extra careful with integer overflows... + size_t extraCapacity = (vec->capacity)/2; + + size_t minExtraCapacity = len - getFreeCapacity(vec); + if(extraCapacity < minExtraCapacity) { + extraCapacity = minExtraCapacity; + } + + if(extraCapacity <= SIZE_MAX - vec->capacity) { + try_realloc(vec, vec->capacity+extraCapacity); + } + + // Check if we were able to resize. + // If not, try to allocate at least what we need... + if(getFreeCapacity(vec) < len) { + try_realloc(vec, vec->capacity+minExtraCapacity); + + // Still not working? Then we fail. + if(getFreeCapacity(vec) < len) { + return 0; + } + } + } + + memmove(vec->data + vec->size, data, len); + vec->size += len; + return len; +} + +flib_buffer flib_vector_as_buffer(flib_vector vec) { + flib_buffer result = {vec->data, vec->size}; + return result; +} + +flib_constbuffer flib_vector_as_constbuffer(flib_vector vec) { + flib_constbuffer result = {vec->data, vec->size}; + return result; +}