feat: add dyn-arr
This commit is contained in:
106
include/c-libs/dyn-arr.h
Normal file
106
include/c-libs/dyn-arr.h
Normal 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
|
||||
Reference in New Issue
Block a user