project_files/frontlib/util/buffer.c
changeset 7234 613998625a3c
parent 7224 5143861c83bd
child 7271 5608ac657362
equal deleted inserted replaced
7230:240620f46dd7 7234:613998625a3c
    35 		free(vec->data);
    35 		free(vec->data);
    36 		free(vec);
    36 		free(vec);
    37 	}
    37 	}
    38 }
    38 }
    39 
    39 
    40 static void try_realloc(flib_vector *vec, size_t newCapacity) {
    40 static int setCapacity(flib_vector *vec, size_t newCapacity) {
       
    41 	if(newCapacity == vec->capacity) {
       
    42 		return 0;
       
    43 	}
    41 	void *newData = realloc(vec->data, newCapacity);
    44 	void *newData = realloc(vec->data, newCapacity);
    42 	if(newData) {
    45 	if(newData) {
    43 		vec->data = newData;
    46 		vec->data = newData;
    44 		vec->capacity = newCapacity;
    47 		vec->capacity = newCapacity;
       
    48 		return 0;
       
    49 	} else {
       
    50 		return -1;
    45 	}
    51 	}
    46 }
    52 }
    47 
    53 
    48 static size_t getFreeCapacity(flib_vector *vec) {
    54 static int allocateExtraCapacity(flib_vector *vec, size_t extraCapacity) {
    49 	return vec->capacity - vec->size;
    55 	if(extraCapacity <= SIZE_MAX - vec->capacity) {
       
    56 		return setCapacity(vec, vec->capacity + extraCapacity);
       
    57 	} else {
       
    58 		return -1;
       
    59 	}
       
    60 }
       
    61 
       
    62 int flib_vector_resize(flib_vector *vec, size_t newSize) {
       
    63 	if(!vec) {
       
    64 		flib_log_e("null parameter in flib_vector_resize");
       
    65 		return -1;
       
    66 	}
       
    67 
       
    68 	if(vec->capacity < newSize) {
       
    69 		// Resize exponentially for constant amortized time,
       
    70 		// But at least by as much as we need of course,
       
    71 		// and be extra careful with integer overflows...
       
    72 		size_t extraCapacity = (vec->capacity)/2;
       
    73 		size_t minExtraCapacity = newSize - vec->capacity;
       
    74 		if(extraCapacity < minExtraCapacity) {
       
    75 			extraCapacity = minExtraCapacity;
       
    76 		}
       
    77 
       
    78 		if(allocateExtraCapacity(vec, extraCapacity)) {
       
    79 			allocateExtraCapacity(vec, minExtraCapacity);
       
    80 		}
       
    81 	} else if(vec->capacity/2 > newSize) {
       
    82 		size_t newCapacity = newSize+newSize/4;
       
    83 		if(newCapacity < MIN_VECTOR_CAPACITY) {
       
    84 			newCapacity = MIN_VECTOR_CAPACITY;
       
    85 		}
       
    86 		setCapacity(vec, newCapacity);
       
    87 	}
       
    88 
       
    89 	if(vec->capacity >= newSize) {
       
    90 		vec->size = newSize;
       
    91 		return 0;
       
    92 	} else {
       
    93 		return -1;
       
    94 	}
    50 }
    95 }
    51 
    96 
    52 int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
    97 int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
    53 	if(!vec) {
    98 	if(!vec) {
    54 		flib_log_e("null parameter in flib_vector_append");
    99 		flib_log_e("null parameter in flib_vector_append");
    55 		return 0;
   100 		return 0;
    56 	}
   101 	}
    57 
   102 
    58 	if(getFreeCapacity(vec) < len) {
   103 	if(len > SIZE_MAX-vec->size) {
    59 		// Resize exponentially for constant amortized time,
   104 		return 0;
    60 		// But at least by as much as we need of course,
       
    61 		// and be extra careful with integer overflows...
       
    62 		size_t extraCapacity = (vec->capacity)/2;
       
    63 
       
    64 		size_t minExtraCapacity = len - getFreeCapacity(vec);
       
    65 		if(extraCapacity < minExtraCapacity) {
       
    66 			extraCapacity = minExtraCapacity;
       
    67 		}
       
    68 
       
    69 		if(extraCapacity <= SIZE_MAX - vec->capacity) {
       
    70 			try_realloc(vec, vec->capacity+extraCapacity);
       
    71 		}
       
    72 
       
    73 		// Check if we were able to resize.
       
    74 		// If not, try to allocate at least what we need.
       
    75 		if(getFreeCapacity(vec) < len) {
       
    76 			try_realloc(vec, vec->capacity+minExtraCapacity);
       
    77 
       
    78 			// Still not working? Then we fail.
       
    79 			if(getFreeCapacity(vec) < len) {
       
    80 				return 0;
       
    81 			}
       
    82 		}
       
    83 	}
   105 	}
    84 
   106 
    85 	memmove(((uint8_t*)vec->data) + vec->size, data, len);
   107 	size_t oldSize = vec->size;
    86 	vec->size += len;
   108 	if(flib_vector_resize(vec, vec->size+len)) {
       
   109 		return 0;
       
   110 	}
       
   111 
       
   112 	memmove(((uint8_t*)vec->data) + oldSize, data, len);
    87 	return len;
   113 	return len;
    88 }
   114 }
    89 
   115 
    90 flib_buffer flib_vector_as_buffer(flib_vector *vec) {
   116 flib_buffer flib_vector_as_buffer(flib_vector *vec) {
    91 	if(!vec) {
   117 	if(!vec) {