2020-10-07 15:13:28 +00:00
|
|
|
|
#include "vector.h"
|
|
|
|
|
|
|
|
|
|
Vector vec_new(Destructor destructor)
|
|
|
|
|
{
|
|
|
|
|
Vector self;
|
|
|
|
|
self.length = 0;
|
|
|
|
|
self.capacity = INITIAL_CAPACITY;
|
|
|
|
|
self.offset = sizeof(void *);
|
|
|
|
|
self.elements = (void *)malloc(self.offset * INITIAL_CAPACITY);
|
|
|
|
|
self.destroy = destructor;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
Vector vec_with_capacity(Destructor const t_destructor, size_t const t_capacity)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
Vector self = vec_new(t_destructor);
|
|
|
|
|
free(self.elements);
|
|
|
|
|
self.elements = (void **)malloc(self.offset * t_capacity);
|
|
|
|
|
self.capacity = t_capacity;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void *vec_at(Vector const *const self, size_t const t_index)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
return self->elements[t_index];
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void *vec_safe_at(Vector const *const self, size_t const t_index)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
return (t_index >= vec_length(self)) ? NULL : vec_at(self, t_index);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
static void vec_maybe_destroy_element(Vector const *self, size_t const t_index)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
void *element = vec_at(self, t_index);
|
|
|
|
|
if (self->destroy) {
|
|
|
|
|
self->destroy(element);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void *vec_last(Vector const *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
return vec_at(self, vec_length(self) - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
size_t vec_length(Vector const *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
return self->length;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
size_t vec_capacity(Vector const *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
return self->capacity;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
static void vec_realloc(Vector *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
self->capacity *= 2;
|
|
|
|
|
self->elements = realloc(self->elements, sizeof(void *) * vec_capacity(self));
|
|
|
|
|
if (!self->elements) {
|
|
|
|
|
PDEB("Could not reallocate Vector’s memory, aborting...", NULL);
|
|
|
|
|
exit(ERR_MEM_ALLOC);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void vec_push(Vector *const self, void const *const t_element)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
if (vec_length(self) >= vec_capacity(self)) {
|
|
|
|
|
vec_realloc(self);
|
|
|
|
|
}
|
|
|
|
|
self->elements[(*self).length++] = t_element;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void vec_pop(Vector *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
if (vec_length(self) <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
vec_maybe_destroy_element(self, vec_length(self) - 1);
|
|
|
|
|
--(*self).length;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void vec_shrink_to_fit(Vector *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
self->capacity = self->length;
|
|
|
|
|
self->elements = realloc(self->elements, sizeof(void *) * vec_capacity(self));
|
|
|
|
|
if (!self->elements) {
|
|
|
|
|
PDEB("Could not reallocate Vector’s memory, aborting...", NULL);
|
|
|
|
|
exit(ERR_MEM_ALLOC);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 09:11:28 +00:00
|
|
|
|
void vec_delete(Vector *const self)
|
2020-10-07 15:13:28 +00:00
|
|
|
|
{
|
|
|
|
|
if (self->destroy) {
|
|
|
|
|
for (size_t i = 0; i < vec_length(self); ++i) {
|
|
|
|
|
self->destroy(self->elements[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(self->elements);
|
|
|
|
|
}
|