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:
@@ -5,15 +5,10 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct ArrayList ArrayList;
|
||||||
void *data;
|
|
||||||
size_t capacity;
|
|
||||||
size_t len;
|
|
||||||
size_t elem_size;
|
|
||||||
} ArrayList;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ArrayList array;
|
ArrayList *array;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
} ArrayListSlice;
|
} ArrayListSlice;
|
||||||
|
|
||||||
@@ -27,21 +22,13 @@ typedef enum {
|
|||||||
ARRLIST_INVALID_ELEM_SIZE,
|
ARRLIST_INVALID_ELEM_SIZE,
|
||||||
} ArrayListErr;
|
} ArrayListErr;
|
||||||
|
|
||||||
typedef struct {
|
ArrayList *arraylist_init(size_t capacity, size_t elem_size);
|
||||||
bool is_valid;
|
|
||||||
union {
|
|
||||||
ArrayListErr err;
|
|
||||||
ArrayList array;
|
|
||||||
};
|
|
||||||
} ArrayListResult;
|
|
||||||
|
|
||||||
ArrayListResult arraylist_init(size_t capacity, size_t elem_size);
|
|
||||||
ArrayListErr arraylist_destroy(ArrayList *arr);
|
ArrayListErr arraylist_destroy(ArrayList *arr);
|
||||||
ArrayListErr arraylist_clear(ArrayList *arr);
|
ArrayListErr arraylist_clear(ArrayList *arr);
|
||||||
|
|
||||||
size_t arraylist_size(ArrayList *arr);
|
size_t arraylist_size(const ArrayList *arr);
|
||||||
size_t arraylist_capacity(ArrayList *arr);
|
size_t arraylist_capacity(const ArrayList *arr);
|
||||||
bool arraylist_is_empty(ArrayList *arr);
|
bool arraylist_is_empty(const ArrayList *arr);
|
||||||
|
|
||||||
ArrayListErr arraylist_push_back(ArrayList *arr, void *data);
|
ArrayListErr arraylist_push_back(ArrayList *arr, void *data);
|
||||||
ArrayListErr arraylist_insert(ArrayList*arr, size_t index, 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_remove_at(ArrayList *arr, size_t index, void *out);
|
||||||
ArrayListErr arraylist_pop_front(ArrayList *arr, 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_set(ArrayList *arr, size_t index, void *data);
|
||||||
|
|
||||||
ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity);
|
ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity);
|
||||||
|
|||||||
@@ -1,37 +1,45 @@
|
|||||||
#include "arraylist.h"
|
#include "arraylist.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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) {
|
if (capacity == 0) {
|
||||||
return (ArrayListResult) {
|
return NULL;
|
||||||
.is_valid = false,
|
|
||||||
.err = ARRLIST_INVALID_CAPACITY};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem_size == 0) {
|
if (elem_size == 0) {
|
||||||
return (ArrayListResult) {
|
return NULL;
|
||||||
.is_valid = false,
|
|
||||||
.err = ARRLIST_INVALID_ELEM_SIZE,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList arr = {
|
ArrayList *arr = malloc(sizeof(ArrayList));
|
||||||
.data = malloc(capacity * elem_size),
|
if (arr == NULL) {
|
||||||
.capacity = capacity,
|
return NULL;
|
||||||
.elem_size = elem_size,
|
}
|
||||||
.len = 0
|
arr->capacity = capacity;
|
||||||
};
|
arr->elem_size = elem_size;
|
||||||
|
arr->len = 0;
|
||||||
if (arr.data == NULL) {
|
arr->data = malloc(capacity * elem_size);
|
||||||
return (ArrayListResult) {
|
if (arr->data == NULL) {
|
||||||
.is_valid = false,
|
free(arr);
|
||||||
.err = ARRLIST_BAD_ALLOC,
|
return NULL;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ArrayListResult) {.is_valid = true, .array = arr};
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayListErr arraylist_destroy(ArrayList *arr) {
|
ArrayListErr arraylist_destroy(ArrayList *arr) {
|
||||||
@@ -44,6 +52,7 @@ ArrayListErr arraylist_destroy(ArrayList *arr) {
|
|||||||
arr->len = 0;
|
arr->len = 0;
|
||||||
free(arr->data);
|
free(arr->data);
|
||||||
arr->data = NULL;
|
arr->data = NULL;
|
||||||
|
free(arr);
|
||||||
return ARRLIST_OK;
|
return ARRLIST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,23 +68,48 @@ ArrayListErr arraylist_clear(ArrayList *arr) {
|
|||||||
return ARRLIST_OK;
|
return ARRLIST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t arraylist_size(ArrayList *arr) {
|
size_t arraylist_size(const ArrayList *arr) {
|
||||||
if (arr == NULL) {
|
if (arr == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return arr->len;
|
return arr->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t arraylist_capacity(ArrayList *arr) {
|
size_t arraylist_capacity(const ArrayList *arr) {
|
||||||
if (arr == NULL) {
|
if (arr == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return arr->capacity;
|
return arr->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arraylist_is_empty(ArrayList *arr) {
|
bool arraylist_is_empty(const ArrayList *arr) {
|
||||||
if (arr == NULL) {
|
if (arr == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return arr->capacity == 0;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user