Skip to content

Instantly share code, notes, and snippets.

@caiodanielnunessantos
Created December 7, 2020 18:12
Show Gist options
  • Save caiodanielnunessantos/1b0015c0991b1c36d5c027b2a83b8e28 to your computer and use it in GitHub Desktop.
Save caiodanielnunessantos/1b0015c0991b1c36d5c027b2a83b8e28 to your computer and use it in GitHub Desktop.
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