cvector/src/vector.c

120 lines
3.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "vector.h"
static Result vec_warn_error(Result error)
{
PERR("%s", error.result.message);
return error;
}
Result vec_new(Destructor destructor)
{
Vector *self = NULL;
self = (Vector *)malloc(sizeof(Vector));
if (!self) { /* Error handling */
return vec_warn_error((Result){
.error = true,
.result = {.message = "Could not allocate memory for Vector structure"}});
}
(*self).length = 0;
(*self).capacity = INITIAL_CAPACITY;
*(size_t *)&self->offset = sizeof(void *); /* weird syntax due to constness */
(*self).elements = (void *)malloc(self->offset * INITIAL_CAPACITY);
if (!self->elements) { /* Error handling */
free(self);
return vec_warn_error((Result){
.error = true,
.result = {.message = "Could not allocate memory for Vectors array"}});
}
(*self).destroy = destructor;
return (Result){.error = false, .result.value = self};
}
Result vec_with_capacity(Destructor const t_destructor, size_t const t_capacity)
{
Result vec = vec_new(t_destructor);
if (vec.error) { /* Error handling */
return vec;
}
Vector *self = vec.result.value;
free((*self).elements);
(*self).elements = (void **)malloc(self->offset * t_capacity);
if (!self->elements) { /* Error handling */
free(self);
return vec_warn_error((Result){
.error = true,
.result = {.message = "Could not allocate memory for Vectors array"}});
}
(*self).capacity = t_capacity;
vec.result.value = self;
return vec;
}
void *vec_safe_at(Vector const *const self, size_t const t_index)
{
return (t_index >= vec_length(self)) ? NULL : vec_at(self, t_index);
}
static void vec_maybe_destroy_element(Vector const *self, size_t const t_index)
{
void *element = vec_at(self, t_index);
if (self->destroy) {
self->destroy(element);
}
}
static Result vec_realloc(Vector *const self)
{
self->capacity *= 2;
self->elements = realloc(self->elements, sizeof(void *) * vec_capacity(self));
if (!self->elements) {
return (Result){
.error = true,
.result = {.message = "Could not reallocate Vectors array"}};
}
return (Result){.error = false, .result = {.value = NULL}};
}
Result vec_push(Vector *const self, void *const t_element)
{
if (vec_length(self) >= vec_capacity(self)) {
Result res_realloc = vec_realloc(self);
if (res_realloc.error) {
return res_realloc;
}
}
self->elements[(*self).length++] = t_element;
return (Result){.error = false, .result = {.value = NULL}};
}
void vec_pop(Vector *const self)
{
if (vec_length(self) <= 0) {
return;
}
vec_maybe_destroy_element(self, vec_length(self) - 1);
--(*self).length;
}
Result vec_shrink_to_fit(Vector *const self)
{
self->capacity = self->length;
self->elements = realloc(self->elements, sizeof(void *) * vec_capacity(self));
if (!self->elements) {
return (Result){
.error = true,
.result = {.message = "Could not reallocate Vectors memory"}};
}
return (Result){.error = false, .result = {.value = NULL}};
}
void vec_delete(Vector *const self)
{
if (self->destroy) {
for (size_t i = 0; i < vec_length(self); ++i) {
self->destroy(self->elements[i]);
}
}
free(self->elements);
free(self);
}