project_files/frontlib/util/buffer.c
changeset 7179 f84805e6df03
parent 7162 fe76d24a25d7
child 7224 5143861c83bd
equal deleted inserted replaced
7177:bf6cf4dd847a 7179:f84805e6df03
       
     1 #include "buffer.h"
       
     2 #include "logging.h"
       
     3 
       
     4 #include <stdlib.h>
       
     5 #include <limits.h>
       
     6 #include <string.h>
       
     7 
       
     8 typedef struct _flib_vector {
       
     9 	void *data;
       
    10 	size_t size;
       
    11 	size_t capacity;
       
    12 } _flib_vector;
       
    13 
       
    14 flib_vector flib_vector_create() {
       
    15 	flib_vector result = malloc(sizeof(_flib_vector));
       
    16 	if(result == NULL) {
       
    17 		return NULL;
       
    18 	}
       
    19 	result->data = malloc(16);
       
    20 	if(result->data == NULL) {
       
    21 		free(result);
       
    22 		return NULL;
       
    23 	}
       
    24 	result->size = 0;
       
    25 	result->capacity = 16;
       
    26 	return result;
       
    27 }
       
    28 
       
    29 void flib_vector_destroy(flib_vector *vec) {
       
    30 	if(vec && *vec) {
       
    31 		free((*vec)->data);
       
    32 		free(*vec);
       
    33 		*vec = NULL;
       
    34 	}
       
    35 }
       
    36 
       
    37 static void try_realloc(flib_vector vec, size_t newCapacity) {
       
    38 	void *newData = realloc(vec->data, newCapacity);
       
    39 	if(newData) {
       
    40 		vec->data = newData;
       
    41 		vec->capacity = newCapacity;
       
    42 	}
       
    43 }
       
    44 
       
    45 static size_t getFreeCapacity(flib_vector vec) {
       
    46 	return vec->capacity - vec->size;
       
    47 }
       
    48 
       
    49 int flib_vector_append(flib_vector vec, const void *data, size_t len) {
       
    50 	if(getFreeCapacity(vec) < len) {
       
    51 		// Resize exponentially for constant amortized time,
       
    52 		// But at least by as much as we need of course,
       
    53 		// and be extra careful with integer overflows...
       
    54 		size_t extraCapacity = (vec->capacity)/2;
       
    55 
       
    56 		size_t minExtraCapacity = len - getFreeCapacity(vec);
       
    57 		if(extraCapacity < minExtraCapacity) {
       
    58 			extraCapacity = minExtraCapacity;
       
    59 		}
       
    60 
       
    61 		if(extraCapacity <= SIZE_MAX - vec->capacity) {
       
    62 			try_realloc(vec, vec->capacity+extraCapacity);
       
    63 		}
       
    64 
       
    65 		// Check if we were able to resize.
       
    66 		// If not, try to allocate at least what we need...
       
    67 		if(getFreeCapacity(vec) < len) {
       
    68 			try_realloc(vec, vec->capacity+minExtraCapacity);
       
    69 
       
    70 			// Still not working? Then we fail.
       
    71 			if(getFreeCapacity(vec) < len) {
       
    72 				return 0;
       
    73 			}
       
    74 		}
       
    75 	}
       
    76 
       
    77 	memmove(vec->data + vec->size, data, len);
       
    78 	vec->size += len;
       
    79 	return len;
       
    80 }
       
    81 
       
    82 flib_buffer flib_vector_as_buffer(flib_vector vec) {
       
    83 	flib_buffer result = {vec->data, vec->size};
       
    84 	return result;
       
    85 }
       
    86 
       
    87 flib_constbuffer flib_vector_as_constbuffer(flib_vector vec) {
       
    88 	flib_constbuffer result = {vec->data, vec->size};
       
    89 	return result;
       
    90 }