From cfc33fca38d499ac219b39d5041f43ee85cfefbd Mon Sep 17 00:00:00 2001 From: Randy Jordan Date: Tue, 16 Jun 2026 14:53:28 -0500 Subject: [PATCH] Arrays --- include/ci2.h | 1 + include/platform/dsa/ci2_array.h | 79 +++++++++++++++++ src/ci2_array.c | 140 +++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 include/platform/dsa/ci2_array.h create mode 100644 src/ci2_array.c diff --git a/include/ci2.h b/include/ci2.h index daef847..c501ed3 100644 --- a/include/ci2.h +++ b/include/ci2.h @@ -26,6 +26,7 @@ SOFTWARE. #include "./platform/ci2_platform.h" #include "./platform/error/ci2_exception.h" +#include "./platform/dsa/ci2_array.h" #include "./platform/mem/ci2_arena.h" #include "./platform/mem/ci2_mem.h" diff --git a/include/platform/dsa/ci2_array.h b/include/platform/dsa/ci2_array.h new file mode 100644 index 0000000..a6cf804 --- /dev/null +++ b/include/platform/dsa/ci2_array.h @@ -0,0 +1,79 @@ +/* - | Copyright | ------------------------------------------------------------ + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#ifndef CI2_ARRAY_H +#define CI2_ARRAY_H + +#include "../ci2_platform.h" +#include +#include /* size_t */ +#include /* uintptr_t */ + +#define ARRAY_INIT_CAPACITY 4 + +typedef struct Array +{ + void** items; + size_t cap; + size_t len; +} Array; + +/* Initialize an array */ +CI2_DEF void +ci2_array_init(struct Array* v); + +/* Free the array items and set to 0. */ +CI2_DEF void +ci2_array_free(struct Array* v); + +/* Get the current number of items. */ +CI2_DEF size_t +ci2_array_len(const struct Array* v); + +/* Get the current capacity of the array. */ +CI2_DEF size_t +ci2_array_capacity(const struct Array* v); + +CI2_DEF int +ci2_array_shrink_to_fit(Array* v); + +/* Add item to end of array. */ +CI2_DEF int +ci2_array_add(struct Array* v, void* item); + +/* Set the item of an array at the given index */ +CI2_DEF int +ci2_array_set(Array* v, size_t index, void* item); + +/* Get an item of an array at an index. */ +CI2_DEF void* +ci2_array_get(const struct Array* v, size_t index); + +/* Remove element (does not free). Returns 0 on success, -1 out-of-range */ +CI2_DEF int +ci2_array_remove(struct Array* v, size_t index); + +/* Clear all elements; if destructor non-NULL it will be called on each item */ +CI2_DEF void +ci2_array_destroy(struct Array* v, void (*destructor)(void*)); + +#endif // ci2_array.h diff --git a/src/ci2_array.c b/src/ci2_array.c new file mode 100644 index 0000000..33e57a8 --- /dev/null +++ b/src/ci2_array.c @@ -0,0 +1,140 @@ +/* - | Copyright | ------------------------------------------------------------ + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#include "../include/platform/dsa/ci2_array.h" + +#include +#include + +static int +ci2_array_resize_internal(struct Array* v, size_t new_capacity) +{ + if (new_capacity < ARRAY_INIT_CAPACITY) + new_capacity = ARRAY_INIT_CAPACITY; + void** tmp = realloc(v->items, sizeof *v->items * new_capacity); + if (!tmp) + return -1; + v->items = tmp; + v->cap = new_capacity; + return 0; +} + +void +ci2_array_init(struct Array* v) +{ + v->cap = ARRAY_INIT_CAPACITY; + v->len = 0; + v->items = malloc(sizeof *v->items * v->cap); + if (!v->items) { + v->cap = 0; + /* leave len as 0; callers should check ci2_array_add return codes */ + } +} + +void +ci2_array_free(struct Array* v) +{ + free(v->items); + v->items = NULL; + v->cap = 0; + v->len = 0; +} + +size_t +ci2_array_len(const struct Array* v) +{ + return v->len; +} +size_t +ci2_array_capacity(const struct Array* v) +{ + return v->cap; +} + +int +ci2_array_add(struct Array* v, void* item) +{ + if (v->len == v->cap) { + if (ci2_array_resize_internal( + v, v->cap ? v->cap * 2 : ARRAY_INIT_CAPACITY) != 0) + return -1; + } + v->items[v->len++] = item; + return 0; +} + +int +ci2_array_set(struct Array* v, size_t index, void* item) +{ + if (index >= v->len) + return -1; + v->items[index] = item; + return 0; +} + +void* +ci2_array_get(const struct Array* v, size_t index) +{ + if (index >= v->len) + return NULL; + return v->items[index]; +} + +int +ci2_array_delete(struct Array* v, size_t index) +{ + if (index >= v->len) + return -1; + if (index < v->len - 1) + memmove(&v->items[index], + &v->items[index + 1], + (v->len - index - 1) * sizeof *v->items); + v->len--; + v->items[v->len] = NULL; + if (v->len > 0 && v->len == v->cap / 4) + ci2_array_resize_internal(v, v->cap / 2); + return 0; +} + +void +ci2_array_destroy(struct Array* v, void (*destructor)(void*)) +{ + if (destructor) { + for (size_t i = 0; i < v->len; ++i) + if (v->items[i]) + destructor(v->items[i]); + } + v->len = 0; + if (v->cap > ARRAY_INIT_CAPACITY) { + ci2_array_resize_internal(v, ARRAY_INIT_CAPACITY); + } + /* keep items array allocated at least at initial capacity */ +} + +int +ci2_array_shrink_to_fit(struct Array* v) +{ + if (v->cap == v->len) + return 0; + size_t target = v->len ? v->len : ARRAY_INIT_CAPACITY; + return ci2_array_resize_internal(v, target); +}