project_files/frontlib/util/buffer.c
changeset 7224 5143861c83bd
parent 7179 f84805e6df03
child 7234 613998625a3c
equal deleted inserted replaced
7221:8d04e85ca204 7224:5143861c83bd
     1 #include "buffer.h"
     1 #include "buffer.h"
     2 #include "logging.h"
     2 #include "logging.h"
       
     3 #include "util.h"
     3 
     4 
     4 #include <stdlib.h>
     5 #include <stdlib.h>
     5 #include <limits.h>
     6 #include <limits.h>
     6 #include <string.h>
     7 #include <string.h>
       
     8 
       
     9 #define MIN_VECTOR_CAPACITY 16
     7 
    10 
     8 typedef struct _flib_vector {
    11 typedef struct _flib_vector {
     9 	void *data;
    12 	void *data;
    10 	size_t size;
    13 	size_t size;
    11 	size_t capacity;
    14 	size_t capacity;
    12 } _flib_vector;
    15 } _flib_vector;
    13 
    16 
    14 flib_vector flib_vector_create() {
    17 flib_vector *flib_vector_create() {
    15 	flib_vector result = malloc(sizeof(_flib_vector));
    18 	flib_vector *result = NULL;
    16 	if(result == NULL) {
    19 	flib_vector *tmpVector = flib_calloc(1, sizeof(_flib_vector));
    17 		return NULL;
    20 	if(tmpVector) {
       
    21 		tmpVector->data = flib_malloc(MIN_VECTOR_CAPACITY);
       
    22 		if(tmpVector->data) {
       
    23 			tmpVector->size = 0;
       
    24 			tmpVector->capacity = MIN_VECTOR_CAPACITY;
       
    25 			result = tmpVector;
       
    26 			tmpVector = NULL;
       
    27 		}
    18 	}
    28 	}
    19 	result->data = malloc(16);
    29 	flib_vector_destroy(tmpVector);
    20 	if(result->data == NULL) {
       
    21 		free(result);
       
    22 		return NULL;
       
    23 	}
       
    24 	result->size = 0;
       
    25 	result->capacity = 16;
       
    26 	return result;
    30 	return result;
    27 }
    31 }
    28 
    32 
    29 void flib_vector_destroy(flib_vector *vec) {
    33 void flib_vector_destroy(flib_vector *vec) {
    30 	if(vec && *vec) {
    34 	if(vec) {
    31 		free((*vec)->data);
    35 		free(vec->data);
    32 		free(*vec);
    36 		free(vec);
    33 		*vec = NULL;
       
    34 	}
    37 	}
    35 }
    38 }
    36 
    39 
    37 static void try_realloc(flib_vector vec, size_t newCapacity) {
    40 static void try_realloc(flib_vector *vec, size_t newCapacity) {
    38 	void *newData = realloc(vec->data, newCapacity);
    41 	void *newData = realloc(vec->data, newCapacity);
    39 	if(newData) {
    42 	if(newData) {
    40 		vec->data = newData;
    43 		vec->data = newData;
    41 		vec->capacity = newCapacity;
    44 		vec->capacity = newCapacity;
    42 	}
    45 	}
    43 }
    46 }
    44 
    47 
    45 static size_t getFreeCapacity(flib_vector vec) {
    48 static size_t getFreeCapacity(flib_vector *vec) {
    46 	return vec->capacity - vec->size;
    49 	return vec->capacity - vec->size;
    47 }
    50 }
    48 
    51 
    49 int flib_vector_append(flib_vector vec, const void *data, size_t len) {
    52 int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
       
    53 	if(!vec) {
       
    54 		flib_log_e("null parameter in flib_vector_append");
       
    55 		return 0;
       
    56 	}
       
    57 
    50 	if(getFreeCapacity(vec) < len) {
    58 	if(getFreeCapacity(vec) < len) {
    51 		// Resize exponentially for constant amortized time,
    59 		// Resize exponentially for constant amortized time,
    52 		// But at least by as much as we need of course,
    60 		// But at least by as much as we need of course,
    53 		// and be extra careful with integer overflows...
    61 		// and be extra careful with integer overflows...
    54 		size_t extraCapacity = (vec->capacity)/2;
    62 		size_t extraCapacity = (vec->capacity)/2;
    61 		if(extraCapacity <= SIZE_MAX - vec->capacity) {
    69 		if(extraCapacity <= SIZE_MAX - vec->capacity) {
    62 			try_realloc(vec, vec->capacity+extraCapacity);
    70 			try_realloc(vec, vec->capacity+extraCapacity);
    63 		}
    71 		}
    64 
    72 
    65 		// Check if we were able to resize.
    73 		// Check if we were able to resize.
    66 		// If not, try to allocate at least what we need...
    74 		// If not, try to allocate at least what we need.
    67 		if(getFreeCapacity(vec) < len) {
    75 		if(getFreeCapacity(vec) < len) {
    68 			try_realloc(vec, vec->capacity+minExtraCapacity);
    76 			try_realloc(vec, vec->capacity+minExtraCapacity);
    69 
    77 
    70 			// Still not working? Then we fail.
    78 			// Still not working? Then we fail.
    71 			if(getFreeCapacity(vec) < len) {
    79 			if(getFreeCapacity(vec) < len) {
    72 				return 0;
    80 				return 0;
    73 			}
    81 			}
    74 		}
    82 		}
    75 	}
    83 	}
    76 
    84 
    77 	memmove(vec->data + vec->size, data, len);
    85 	memmove(((uint8_t*)vec->data) + vec->size, data, len);
    78 	vec->size += len;
    86 	vec->size += len;
    79 	return len;
    87 	return len;
    80 }
    88 }
    81 
    89 
    82 flib_buffer flib_vector_as_buffer(flib_vector vec) {
    90 flib_buffer flib_vector_as_buffer(flib_vector *vec) {
    83 	flib_buffer result = {vec->data, vec->size};
    91 	if(!vec) {
    84 	return result;
    92 		flib_log_e("null parameter in flib_vector_as_buffer");
       
    93 		flib_buffer result = {NULL, 0};
       
    94 		return result;
       
    95 	} else {
       
    96 		flib_buffer result = {vec->data, vec->size};
       
    97 		return result;
       
    98 	}
    85 }
    99 }
    86 
   100 
    87 flib_constbuffer flib_vector_as_constbuffer(flib_vector vec) {
   101 flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) {
    88 	flib_constbuffer result = {vec->data, vec->size};
   102 	if(!vec) {
    89 	return result;
   103 		flib_log_e("null parameter in flib_vector_as_constbuffer");
       
   104 		flib_constbuffer result = {NULL, 0};
       
   105 		return result;
       
   106 	} else {
       
   107 		flib_constbuffer result = {vec->data, vec->size};
       
   108 		return result;
       
   109 	}
    90 }
   110 }
       
   111 
       
   112 void *flib_vector_data(flib_vector *vec) {
       
   113 	if(!vec) {
       
   114 		flib_log_e("null parameter in flib_vector_data");
       
   115 		return NULL;
       
   116 	} else {
       
   117 		return vec->data;
       
   118 	}
       
   119 }
       
   120 
       
   121 size_t flib_vector_size(flib_vector *vec) {
       
   122 	if(!vec) {
       
   123 		flib_log_e("null parameter in flib_vector_size");
       
   124 		return 0;
       
   125 	} else {
       
   126 		return vec->size;
       
   127 	}
       
   128 }