From 4ea062fd6004adebd49b40e19f2cfba204a63af0 Mon Sep 17 00:00:00 2001 From: laentropia Date: Tue, 14 Apr 2026 20:30:02 -0600 Subject: [PATCH] addition/refactor: Made ADT design and added grow/shrink So, added private functions made to grow and shrink the array in a multiple of 2, 2 as a factro is fine, at least that is Rust does it that way. Also changed the design to ADT, forgot i liked that, probably will be changing that to apply also to my Arena implementation, i will see if fits --probably--. --- include/arraylist.h | 27 ++++----------- src/arraylist.c | 82 ++++++++++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/include/arraylist.h b/include/arraylist.h index 087c47c..50e4f7c 100644 --- a/include/arraylist.h +++ b/include/arraylist.h @@ -5,15 +5,10 @@ #include #include -typedef struct { - void *data; - size_t capacity; - size_t len; - size_t elem_size; -} ArrayList; +typedef struct ArrayList ArrayList; typedef struct { - ArrayList array; + ArrayList *array; size_t offset; } ArrayListSlice; @@ -27,21 +22,13 @@ typedef enum { ARRLIST_INVALID_ELEM_SIZE, } ArrayListErr; -typedef struct { - bool is_valid; - union { - ArrayListErr err; - ArrayList array; - }; -} ArrayListResult; - -ArrayListResult arraylist_init(size_t capacity, size_t elem_size); +ArrayList *arraylist_init(size_t capacity, size_t elem_size); ArrayListErr arraylist_destroy(ArrayList *arr); ArrayListErr arraylist_clear(ArrayList *arr); -size_t arraylist_size(ArrayList *arr); -size_t arraylist_capacity(ArrayList *arr); -bool arraylist_is_empty(ArrayList *arr); +size_t arraylist_size(const ArrayList *arr); +size_t arraylist_capacity(const ArrayList *arr); +bool arraylist_is_empty(const ArrayList *arr); ArrayListErr arraylist_push_back(ArrayList *arr, void *data); ArrayListErr arraylist_insert(ArrayList*arr, size_t index, void *data); @@ -52,7 +39,7 @@ ArrayListErr arraylist_pop_back(ArrayList *arr, void *out); ArrayListErr arraylist_remove_at(ArrayList *arr, size_t index, void *out); ArrayListErr arraylist_pop_front(ArrayList *arr, void *out); -ArrayListErr arraylist_get(ArrayList *arr, size_t index, void *out); +ArrayListErr arraylist_get(const ArrayList *arr, size_t index, void *out); ArrayListErr arraylist_set(ArrayList *arr, size_t index, void *data); ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity); diff --git a/src/arraylist.c b/src/arraylist.c index 05732aa..3e8cf12 100644 --- a/src/arraylist.c +++ b/src/arraylist.c @@ -1,37 +1,45 @@ #include "arraylist.h" +#include #include #include #include -ArrayListResult arraylist_init(size_t capacity, size_t elem_size) { +struct ArrayList{ + void *data; + size_t capacity; + size_t len; + size_t elem_size; +}; + +// Grow and shrink factor is 2, 1.5 might give different results i guess +// but i'm basing myself in that Rust implementation of array does use +// 2 as the factor so i guess is good :) +static ArrayListErr arraylist_grow(ArrayList *arr); +static ArrayListErr arraylist_shrink(ArrayList *arr); + +ArrayList *arraylist_init(size_t capacity, size_t elem_size) { if (capacity == 0) { - return (ArrayListResult) { - .is_valid = false, - .err = ARRLIST_INVALID_CAPACITY}; + return NULL; } if (elem_size == 0) { - return (ArrayListResult) { - .is_valid = false, - .err = ARRLIST_INVALID_ELEM_SIZE, - }; + return NULL; } - ArrayList arr = { - .data = malloc(capacity * elem_size), - .capacity = capacity, - .elem_size = elem_size, - .len = 0 - }; - - if (arr.data == NULL) { - return (ArrayListResult) { - .is_valid = false, - .err = ARRLIST_BAD_ALLOC, - }; + ArrayList *arr = malloc(sizeof(ArrayList)); + if (arr == NULL) { + return NULL; + } + arr->capacity = capacity; + arr->elem_size = elem_size; + arr->len = 0; + arr->data = malloc(capacity * elem_size); + if (arr->data == NULL) { + free(arr); + return NULL; } - return (ArrayListResult) {.is_valid = true, .array = arr}; + return arr; } ArrayListErr arraylist_destroy(ArrayList *arr) { @@ -44,6 +52,7 @@ ArrayListErr arraylist_destroy(ArrayList *arr) { arr->len = 0; free(arr->data); arr->data = NULL; + free(arr); return ARRLIST_OK; } @@ -59,23 +68,48 @@ ArrayListErr arraylist_clear(ArrayList *arr) { return ARRLIST_OK; } -size_t arraylist_size(ArrayList *arr) { +size_t arraylist_size(const ArrayList *arr) { if (arr == NULL) { return 0; } return arr->len; } -size_t arraylist_capacity(ArrayList *arr) { +size_t arraylist_capacity(const ArrayList *arr) { if (arr == NULL) { return 0; } return arr->capacity; } -bool arraylist_is_empty(ArrayList *arr) { +bool arraylist_is_empty(const ArrayList *arr) { if (arr == NULL) { return true; } return arr->capacity == 0; } + +static ArrayListErr arraylist_grow(ArrayList *arr) { + // We can asume is not null because is internal + // and only used by funtions that already verified + // arr is not null, same with shrink. + size_t new_capacity = arr->capacity * 2; + void *tmp = realloc(arr->data, new_capacity * arr->elem_size); + if (tmp == NULL) { + return ARRLIST_BAD_ALLOC; + } + arr->capacity = new_capacity; + arr->data = tmp; + return ARRLIST_OK; +} + +static ArrayListErr arraylist_shrink(ArrayList *arr) { + size_t new_capacity = arr->capacity / 2; + void *tmp = realloc(arr->data, new_capacity *arr->elem_size); + if (tmp == NULL) { + return ARRLIST_BAD_ALLOC; + } + arr->capacity = new_capacity; + arr->data = tmp; + return ARRLIST_OK; +}