Created
December 7, 2020 18:12
-
-
Save caiodanielnunessantos/1b0015c0991b1c36d5c027b2a83b8e28 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size_t PowerOfTwoGuard(size_t input) { | |
size_t power_of_two = 1; | |
while (input > power_of_two) | |
power_of_two *= 2; | |
return power_of_two; | |
} | |
typedef struct { | |
size_t element_type_size; | |
size_t size; | |
size_t capacity; | |
char* elements; | |
} _GenericVector; | |
void* _GenericVectorGetReference(_GenericVector vector, size_t index) { | |
if (index >= vector.size) return (void*)0; | |
return vector.elements + vector.elements_type_size * index; | |
} | |
void _GenericVectorAssignElement(_GenericVector vector, size_t index, void* element_address) { | |
memcpy(_GenericVectorGetReference(vector, index), element_address, vector.elements_type_size); | |
} | |
void _GenericVectorResizeBuffer(_GenericVector vector) { | |
vector.elements = realloc(vector.elements, | |
vector.capacity * vector.elements_type_size); | |
} | |
void _GenericVectorCheckOverflow(_GenericVector vector) { | |
if (vector.size == vector.capacity) { | |
vector.capacity *= 2; | |
_GenericVectorResizeBuffer(vector); | |
} | |
} | |
void _GenericVectorCheckUnderflow(_GenericVector vector) { | |
if (vector.size <= vector.capacity / 2) { | |
vector.capacity /= 2; | |
_GenericVectorResizeBuffer(vector); | |
} | |
} | |
void _GenericVectorPushBack(_GenericVector vector, void* element_address) { | |
_GenericVectorCheckOverflow(vector); | |
vector.size++; | |
_GenericVectorAssignElement(vector, vector.size, element_address); | |
} | |
void* _GenericVectorPopBack(_GenericVector vector) { //UNSAFE!!! FREE IT PLEASE!!! | |
void* buffer = malloc(vector.element_type_size); | |
vector.size--; | |
memcpy(_GenericVectorGetReference(vector, vector.size), buffer, vector.element_type_size); | |
_GenericVectorCheckUndeflow(vector); | |
return buffer; | |
} | |
void _GenericVectorShiftRight(_GenericVector vector, size_t index) { | |
_GenericVectorCheckOverflow(vector); | |
memmove(_GenericVectorGetReference(vector, index), _GenericVectorGetReference(vector, index + 1)); | |
vector.size++; | |
} | |
void _GenericVectorShiftLeft(_GenericVector vector, size_t index) { | |
memmove(_GenericVectorGetReference(vector, index), _GenericVectorGetReference(vector, index - 1)); | |
vector.size--; | |
_GenericVectorCheckUnderflow(vector); | |
} | |
void _GenericVectorInsert(_GenericVector vector, size_t index, void* element_address) { | |
if (index > vector.size) return; | |
_GenericVectorShiftRight(vector, index + 1); | |
_GenericVectorAssign(vector, index, element_address); | |
} | |
void _GenericVectorRemove(_GenericVector vector, size_t index) { | |
if (index >= vector.size) return; | |
_GenericVectorShiftLeft(vector, index + 1); | |
_GenericVectorCheckUnderflow(vector); | |
} | |
void* _GenericVectorRemoveGet(_GenericVector vector, size_t index) { //UNSAFE!!! FREE IT PLEASE | |
if (index >= vector.size) return (void*)0; | |
void* buffer = malloc(vector.element_type_size); | |
memcpy(_GenericVectorGetReference(vector, index), buffer, vector.element_type_size); | |
_GenericVectorShiftLeft(vector, index + 1); | |
_GenericVectorCheckUnderflow(vector); | |
return buffer; | |
} | |
_GenericVector _GenericVectorCreate(size_t elements_type_size, size_t prealloc) { | |
prealloc = PowerOfTwoGuard(prealloc); | |
return (_GenericVector){ elements_type_size, 0, malloc(prealloc) }; | |
} | |
void _GenericVectorDestroy(_GenericVector vector) { | |
free(vector.elements); | |
} | |
void _GenericVectorForEach(_GenericVector vector, void (*function)(void*)) { | |
for (size_t index = 0; index < vector.size; index++) { | |
function(_GenericVectorGetReference(vector, index)); | |
} | |
} | |
void _GenericVectorReduce(_GenericVector vector, void* initial_value, | |
void (*function)(void*, void*)) { | |
for (size_t index = 0; index < vector.size; index++) { | |
function(_GenericVectorGetReference(vector, index), initial_value); | |
} | |
} | |
_GenericVector _GenericVectorMap(_GenericVector vector, size_t return_type_size, void (function)(void*, void*)) { | |
_GenericVector buffer = _GenericVectorCreate(return_type_size, vector.size); | |
void* arg_buffer = malloc(return_type_size); | |
for (size_t index = 0; index < vector.size; index++) { | |
_GenericVectorPushBack(buffer, (function(_GenericVectorGetReference(vector, index), arg_buffer), arg_buffer)); | |
} | |
free(arg_buffer); | |
return buffer; | |
} | |
_GenericVector _GenericVectorFilter(_GenericVector vector, _Bool (*function)(void*)) { | |
_GenericVector buffer = _GenericVectorCreate(vector.element_type_size, 8); | |
for (size_t index = 0; index < vector.size; index++) { | |
void* element = _GenericVectorGetReference(vector, index)); | |
if (function(element)) { | |
_GenericVectorPushBack(buffer, element); | |
} | |
} | |
return buffer; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment