diff options
Diffstat (limited to 'src/array.c')
-rw-r--r-- | src/array.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..8c34469 --- /dev/null +++ b/src/array.c @@ -0,0 +1,100 @@ +/* + ihex + Copyright (C) 2025 Thomas Albers Raviola <thomas@thomaslabs.org> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <array.h> + +#include <stdlib.h> +#include <string.h> + +#if __STDC_VERSION__ < 202311L +#include <assert.h> +#define static_assert _Static_assert +#endif + +#define ARRAY_INITIAL_CAPACITY 8 + +void +init_array(struct array *arr, size_t elem_size) +{ + arr->length = 0; + arr->capacity = ARRAY_INITIAL_CAPACITY; + arr->elem_size = elem_size; + arr->data = malloc(arr->capacity * elem_size); +} + +void +free_array(struct array *arr) +{ + free(arr->data); + memset(arr, 0, sizeof(*arr)); +} + +// Return pointer to last allocated member +void * +array_append(struct array *arr, const void *data) +{ + void *addr = NULL; + + if (arr->length >= arr->capacity) { + arr->capacity = arr->capacity + arr->capacity / 2; + arr->data = realloc(arr->data, arr->elem_size * arr->capacity); + // Reallocation failed + if (!arr->data) + return NULL; + } + + addr = (void *)((char *)arr->data + arr->elem_size * arr->length); + arr->length++; + + if (data) + memcpy(addr, data, arr->elem_size); + + return addr; +} + +void +array_remove(struct array *arr, size_t n, void *dest) +{ + assert(n < arr->length); + + void *addr = array_elt(arr, n); + void *succ; + + if (dest) + memcpy(dest, addr, arr->elem_size); + + if (arr->length == n) { + arr->length--; + } else { + succ = array_elt(arr, n + 1); + memmove(addr, succ, (arr->length - n - 1) * arr->elem_size); + } +} + +void +array_sort(struct array *arr, int (*compar)(const void *, const void *)) +{ + qsort(arr->data, arr->length, arr->elem_size, compar); +} + +void * +array_search(struct array *arr, const void *key, + int (*compar)(const void *, const void *)) +{ + return bsearch(key, arr->data, arr->length, arr->elem_size, compar); +} |