cvector/vector.c

145 lines
3.6 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 void vec_maybe_destroy_element(Vector const *self,
size_t const t_index) NONNULL;
static Result vec_realloc(Vector *const self) NONNULL;
static Result vec_warn_error(Result error);
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);
}
void vec_maybe_destroy_element(Vector const *self, size_t const t_index)
{
if (self->destroy) {
void *element = vec_at(self, t_index);
self->destroy(element);
}
}
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);
}
size_t vec_length(Vector const *const self)
{
return self->length;
}
size_t vec_capacity(Vector const *const self)
{
return self->capacity;
}
void *vec_at(Vector const *const self, size_t const index)
{
return self->elements[index];
}
void *vec_last(Vector const *const self)
{
return vec_at(self, vec_length(self) - 1);
}