feat: add dyn-arr

This commit is contained in:
2026-03-23 00:26:37 +01:00
commit 4b80c8aea5
9 changed files with 338 additions and 0 deletions

106
include/c-libs/dyn-arr.h Normal file
View File

@@ -0,0 +1,106 @@
#ifndef CLIBS_DYN_ARR_H
#define CLIBS_DYN_ARR_H
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
size_t cap;
size_t size;
} DArrHeader;
/// Initialize a dynamic array
/// @param darr a pointer, which will be overwritten to point to the dynamic
/// array's data part
/// @param capacity the initial capacity allocated
#define darr_init(darr, capacity) \
do { \
size_t c = (capacity); \
DArrHeader *header = malloc(sizeof(DArrHeader) + c * sizeof(*(darr))); \
header->cap = c; \
header->size = 0; \
(darr) = (typeof(darr))(header + 1); \
} while (0)
/// Grow an danamic array by an amount
/// @param darr a pointer initialized with darr_init, will be changed to point
/// to the new data location
/// @param extra_cap the extra capacity to add
#define darr_grow(darr, extra_cap) \
do { \
DArrHeader *header = ((DArrHeader *)(darr)) - 1; \
header->cap += (extra_cap); \
\
header = \
realloc(header, header->cap * sizeof(*(darr)) + sizeof(DArrHeader)); \
(darr) = (typeof((darr)))(header + 1); \
} while (0)
/// Append an element to a dynamic array.
/// @param darr a pointer initialized with darr_init, may be overwritten if
/// memory changes
/// @param x the element to insert at darr[darr_size(darr)]
#define darr_push(darr, x) \
do { \
DArrHeader *header = ((DArrHeader *)(darr)) - 1; \
\
if (header->size == header->cap) { \
size_t inc = header->cap / 2; \
darr_grow(darr, inc ? inc : 1); \
} \
\
header = ((DArrHeader *)(darr)) - 1; \
darr[header->size++] = (x); \
} while (0)
/// Clone an dynamic array
/// @param darr a pointer initialized with darr_init
/// Returns a fresh pointer to the cloned data
#define darr_clone(darr) (typeof(darr))darr_clone_impl((darr), sizeof(*(darr)))
/// Clone an untyped dynamic array
/// @param arr any pointer initialized with darr_init
/// @param elem_size the byte-size of the contained elements
/// Returns a fresh pointer to the cloned data, must be freed with darr_free
void *darr_clone_impl(void *arr, size_t elem_size);
/// Get the number of elements in the dynamic array
/// @param arr a pointer initialized with darr_init
size_t darr_size(void *arr);
/// Get the capacity of the dynamic array
/// @param arr a pointer initialized with darr_init
size_t darr_cap(void *arr);
/// Free a dynamic array
/// @param arr a pointer initialized with darr_init or returned from darr_clone
void darr_free(void *arr);
#endif
#ifdef CLIBS_DYN_ARR_IMPL
size_t darr_size(void *arr) {
DArrHeader *header = ((DArrHeader *)arr) - 1;
return header->size;
}
size_t darr_cap(void *arr) {
DArrHeader *header = ((DArrHeader *)arr) - 1;
return header->cap;
}
void *darr_clone_impl(void *arr, size_t elem_size) {
DArrHeader *header = ((DArrHeader *)arr) - 1;
size_t size = sizeof(DArrHeader) + elem_size * header->cap;
DArrHeader *tgt = malloc(size);
memcpy(tgt, header, size);
return (void *)(tgt + 1);
}
void darr_free(void *arr) {
DArrHeader *header = ((DArrHeader *)arr) - 1;
free(header);
}
#endif