diff --git a/src/vector.c b/src/vector.c index 9c84f8f..aa2e89b 100644 --- a/src/vector.c +++ b/src/vector.c @@ -1,28 +1,52 @@ #include "vector.h" -Vector vec_new(Destructor destructor) +static Result vec_warn_error(Result error) { - 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; + PERR("%s", error.result.message); + return error; } -Vector vec_with_capacity(Destructor const t_destructor, size_t const t_capacity) +Result vec_new(Destructor destructor) { - Vector self = vec_new(t_destructor); - free(self.elements); - self.elements = (void **)malloc(self.offset * t_capacity); - self.capacity = t_capacity; - return self; + 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 Vector’s array"}}); + } + (*self).destroy = destructor; + return (Result){.error = false, .result.value = self}; } -void *vec_at(Vector const *const self, size_t const t_index) +Result vec_with_capacity(Destructor const t_destructor, size_t const t_capacity) { - return self->elements[t_index]; + 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 Vector’s array"}}); + } + (*self).capacity = t_capacity; + vec.result.value = self; + return vec; } void *vec_safe_at(Vector const *const self, size_t const t_index) @@ -38,37 +62,28 @@ static void vec_maybe_destroy_element(Vector const *self, size_t const t_index) } } -void *vec_last(Vector const *const self) -{ - return vec_at(self, vec_length(self) - 1); -} - -size_t vec_length(Vector const *const self) -{ - return self->length; -} - -size_t vec_capacity(Vector const *const self) -{ - return self->capacity; -} - -static void vec_realloc(Vector *const self) +static Result vec_realloc(Vector *const self) { 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); + return (Result){ + .error = true, + .result = {.message = "Could not reallocate Vector’s array"}}; } + return (Result){.error = false, .result = {.value = NULL}}; } -void vec_push(Vector *const self, void const *const t_element) +Result vec_push(Vector *const self, void *const t_element) { if (vec_length(self) >= vec_capacity(self)) { - vec_realloc(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) @@ -80,14 +95,16 @@ void vec_pop(Vector *const self) --(*self).length; } -void vec_shrink_to_fit(Vector *const self) +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) { - PDEB("Could not reallocate Vector’s memory, aborting...", NULL); - exit(ERR_MEM_ALLOC); + return (Result){ + .error = true, + .result = {.message = "Could not reallocate Vector’s memory"}}; } + return (Result){.error = false, .result = {.value = NULL}}; } void vec_delete(Vector *const self) @@ -98,4 +115,5 @@ void vec_delete(Vector *const self) } } free(self->elements); + free(self); } diff --git a/src/vector.h b/src/vector.h index bacae7c..09d6f30 100644 --- a/src/vector.h +++ b/src/vector.h @@ -1,6 +1,7 @@ #ifndef VECTOR_H #define VECTOR_H +#include #include #include #include @@ -20,37 +21,62 @@ #define UNINPLEMENTED printf("%s:%d: Not yet implemented", __FILE__, __LINE__) #define INITIAL_CAPACITY 4 -#define PDEB(format, ...) \ - if (DEBUG) { \ - fprintf(stderr, \ - GREEN "%s:%d\t" NO_COLOR format "\n", \ - __FILE__, \ - __LINE__, \ - __VA_ARGS__); \ - } +#define PCOMMON(color, format, ...) \ + fprintf(stderr, \ + "%s%s:%d%s\t" format "\n", \ + color, \ + __FILE__, \ + __LINE__, \ + NO_COLOR, \ + __VA_ARGS__) +#define PDEB(format, ...) PCOMMON(GREEN, format, __VA_ARGS__) +#define PERR(format, ...) PCOMMON(RED, format, __VA_ARGS__) /* Destructor typedef */ typedef void (*Destructor)(void *element); typedef struct Vector_s { - size_t length; - size_t capacity; - size_t offset; - void ** elements; - Destructor destroy; + size_t length; + size_t capacity; + const size_t offset; + void ** elements; + Destructor destroy; } Vector; -Vector vec_new(Destructor destructor); -Vector vec_with_capacity(Destructor const destructor, size_t const capacity); +typedef struct Result_s { + union { + const char *message; + void * value; + } result; + bool error; +} Result; -void * vec_at(Vector const *const self, size_t const index); +Result vec_new(Destructor destructor); +Result vec_with_capacity(Destructor const destructor, size_t const capacity); +Result vec_push(Vector *const self, void *const element); +Result vec_shrink_to_fit(Vector *const self); void * vec_safe_at(Vector const *const self, size_t const index); -void * vec_last(Vector const *const self); -size_t vec_length(Vector const *const self); -size_t vec_capacity(Vector const *const self); -void vec_push(Vector *const self, void const *const element); void vec_pop(Vector *const self); -void vec_shrink_to_fit(Vector *const self); void vec_delete(Vector *const self); +inline size_t vec_length(Vector const *const self) +{ + return self->length; +} + +inline size_t vec_capacity(Vector const *const self) +{ + return self->capacity; +} + +inline void *vec_at(Vector const *const self, size_t const index) +{ + return self->elements[index]; +} + +inline void *vec_last(Vector const *const self) +{ + return vec_at(self, vec_length(self) - 1); +} + #endif /* VECTOR_H */