diff -r 240620f46dd7 -r 613998625a3c project_files/frontlib/util/buffer.c --- a/project_files/frontlib/util/buffer.c Fri Jun 15 19:57:25 2012 +0200 +++ b/project_files/frontlib/util/buffer.c Tue Jun 19 21:17:05 2012 +0200 @@ -37,16 +37,61 @@ } } -static void try_realloc(flib_vector *vec, size_t newCapacity) { +static int setCapacity(flib_vector *vec, size_t newCapacity) { + if(newCapacity == vec->capacity) { + return 0; + } void *newData = realloc(vec->data, newCapacity); if(newData) { vec->data = newData; vec->capacity = newCapacity; + return 0; + } else { + return -1; + } +} + +static int allocateExtraCapacity(flib_vector *vec, size_t extraCapacity) { + if(extraCapacity <= SIZE_MAX - vec->capacity) { + return setCapacity(vec, vec->capacity + extraCapacity); + } else { + return -1; } } -static size_t getFreeCapacity(flib_vector *vec) { - return vec->capacity - vec->size; +int flib_vector_resize(flib_vector *vec, size_t newSize) { + if(!vec) { + flib_log_e("null parameter in flib_vector_resize"); + return -1; + } + + if(vec->capacity < newSize) { + // 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 = newSize - vec->capacity; + if(extraCapacity < minExtraCapacity) { + extraCapacity = minExtraCapacity; + } + + if(allocateExtraCapacity(vec, extraCapacity)) { + allocateExtraCapacity(vec, minExtraCapacity); + } + } else if(vec->capacity/2 > newSize) { + size_t newCapacity = newSize+newSize/4; + if(newCapacity < MIN_VECTOR_CAPACITY) { + newCapacity = MIN_VECTOR_CAPACITY; + } + setCapacity(vec, newCapacity); + } + + if(vec->capacity >= newSize) { + vec->size = newSize; + return 0; + } else { + return -1; + } } int flib_vector_append(flib_vector *vec, const void *data, size_t len) { @@ -55,35 +100,16 @@ return 0; } - 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; - } - } + if(len > SIZE_MAX-vec->size) { + return 0; } - memmove(((uint8_t*)vec->data) + vec->size, data, len); - vec->size += len; + size_t oldSize = vec->size; + if(flib_vector_resize(vec, vec->size+len)) { + return 0; + } + + memmove(((uint8_t*)vec->data) + oldSize, data, len); return len; }