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--.
This commit is contained in:
2026-04-14 20:30:02 -06:00
parent cb78e9467b
commit 4ea062fd60
2 changed files with 65 additions and 44 deletions

View File

@@ -5,15 +5,10 @@
#include <stddef.h>
#include <stdbool.h>
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);

View File

@@ -1,37 +1,45 @@
#include "arraylist.h"
#include <stdatomic.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
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;
}