From f4364f38d12c731e2ef491871d68fdf6eb5f1699 Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Mon, 17 Nov 2025 00:30:46 +0000 Subject: [PATCH] vec -> prick_darr.h --- prick_darr.h | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ vec.h | 111 ------------------------------------------- 2 files changed, 130 insertions(+), 111 deletions(-) create mode 100644 prick_darr.h delete mode 100644 vec.h diff --git a/prick_darr.h b/prick_darr.h new file mode 100644 index 0000000..8ea6aa0 --- /dev/null +++ b/prick_darr.h @@ -0,0 +1,130 @@ +/* prick_darr.h: A dynamically sized array, all on the heap. + * Created: 2024-10-01 + * Author: Aryadev Chavali + * License: see end of file + * Commentary: + + To utilise this library, please put: + #define PRICK_DARR_IMPL + #include "prick_darr.h" + in one of your code units. + + This library defines a dynamic array purely on the heap. We split the one + dynamic array allocation into two parts: the metadata, and the actual data. + Consumers of the library will only ever need to deal with the latter component + i.e. they'll only ever have access to the data they require. + + Unfortuntely this does mean that the underlying data pointer is _not_ stable + during capacity reallocation, as we're allocating a whole new pointer with the + correct size. Therefore, if you're expecting the array to grow during the + runtime of your program, you should ensure any pointers to components of it are + updated as they will otherwise be dangling. + */ + +#ifndef PRICK_DARR_H +#define PRICK_DARR_H + +#include + +typedef struct +{ + uint32_t size, capacity; + uint8_t bytes[]; +} darr_t; + +#define DARR_GET(P) (((darr_t *)(P)) - 1) +#define DARR_SIZE(P) (DARR_GET(P)->size) +#define DARR_CAP(P) (DARR_GET(P)->capacity) + +void darr_make(void **ptr, uint32_t size); +void darr_free(void **ptr); +void darr_append_byte(void **ptr, uint8_t byte); +void darr_append(void **ptr, void *data, uint32_t size); +void darr_clone(void **dest, void **src); +void darr_ensure_remaining(void **ptr, uint32_t space); + +#ifdef PRICK_DARR_IMPL + +#include +#include + +#ifndef DARR_MULT +#define DARR_MULT 2 +#endif + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +void darr_make(void **ptr, uint32_t size) +{ + if (!ptr) + return; + darr_t *darrtor = calloc(1, sizeof(*darrtor) + size); + darrtor->size = 0; + darrtor->capacity = size; + *ptr = (darrtor + 1); +} + +void darr_free(void **data) +{ + if (!data || !*data) + return; + free(DARR_GET(*data)); + *data = NULL; +} + +void darr_ensure_remaining(void **ptr, uint32_t space) +{ + if (!ptr || !*ptr) + return; + darr_t *darr = DARR_GET(*ptr); + if (darr->capacity - darr->size < space) + { + void *new_darr = NULL; + darr_make(&new_darr, MAX(darr->capacity * DARR_MULT, darr->size + space)); + DARR_SIZE(new_darr) = darr->size; + memcpy(new_darr, *ptr, darr->size); + darr_free(ptr); + *ptr = new_darr; + } +} + +void darr_append_byte(void **ptr, uint8_t byte) +{ + darr_ensure_remaining(ptr, 1); + darr_t *darr = DARR_GET(*ptr); + darr->bytes[darr->size++] = byte; +} + +void darr_append(void **ptr, void *data, uint32_t size) +{ + darr_ensure_remaining(ptr, size); + darr_t *darr = DARR_GET(*ptr); + memcpy(*ptr + darr->size, data, size); + darr->size += size; +} + +void darr_clone(void **dest, void **src) +{ + if (!dest || !src || !*src) + return; + darr_make(dest, DARR_SIZE(*src)); + memcpy(*dest, *src, DARR_SIZE(*src)); + DARR_SIZE(*dest) = DARR_SIZE(*src); +} + +#endif + +#endif + +/* Copyright (C) 2024 Aryadev Chavali + * 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 Unlicense + * for details. + + * You may distribute and modify this code under the terms of the + * Unlicense, which you should have received a copy of along with this + * program. If not, please go to . + + */ diff --git a/vec.h b/vec.h deleted file mode 100644 index a87c851..0000000 --- a/vec.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2024 Aryadev Chavali - - * 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 Unlicense - * for details. - - * You may distribute and modify this code under the terms of the - * Unlicense, which you should have received a copy of along with this - * program. If not, please go to . - - * Created: 2024-10-01 - * Author: Aryadev Chavali - * Description: A dynamically sized container. - */ - -#ifndef VEC_H -#define VEC_H - -#include - -typedef struct -{ - uint32_t size, capacity; - uint8_t bytes[]; -} vec_t; - -#define VEC_GET(P) (((vec_t *)(P)) - 1) -#define VEC_SIZE(P) (VEC_GET(P)->size) -#define VEC_CAP(P) (VEC_GET(P)->capacity) - -void vec_make(void **ptr, uint32_t size); -void vec_free(void **ptr); -void vec_append_byte(void **ptr, uint8_t byte); -void vec_append(void **ptr, void *data, uint32_t size); -void vec_clone(void **dest, void **src); -void vec_ensure_remaining(void **ptr, uint32_t space); - -#ifdef VEC_IMPL - -#include -#include - -#ifndef VEC_MULT -#define VEC_MULT 2 -#endif - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) - -void vec_make(void **ptr, uint32_t size) -{ - if (!ptr) - return; - vec_t *vector = calloc(1, sizeof(*vector) + size); - vector->size = 0; - vector->capacity = size; - *ptr = (vector + 1); -} - -void vec_free(void **data) -{ - if (!data || !*data) - return; - free(VEC_GET(*data)); - *data = NULL; -} - -void vec_ensure_remaining(void **ptr, uint32_t space) -{ - if (!ptr || !*ptr) - return; - vec_t *vec = VEC_GET(*ptr); - if (vec->capacity - vec->size < space) - { - void *new_vec = NULL; - vec_make(&new_vec, MAX(vec->capacity * VEC_MULT, vec->size + space)); - VEC_SIZE(new_vec) = vec->size; - memcpy(new_vec, *ptr, vec->size); - vec_free(ptr); - *ptr = new_vec; - } -} - -void vec_append_byte(void **ptr, uint8_t byte) -{ - vec_ensure_remaining(ptr, 1); - vec_t *vec = VEC_GET(*ptr); - vec->bytes[vec->size++] = byte; -} - -void vec_append(void **ptr, void *data, uint32_t size) -{ - vec_ensure_remaining(ptr, size); - vec_t *vec = VEC_GET(*ptr); - memcpy(*ptr + vec->size, data, size); - vec->size += size; -} - -void vec_clone(void **dest, void **src) -{ - if (!dest || !src || !*src) - return; - vec_make(dest, VEC_SIZE(*src)); - memcpy(*dest, *src, VEC_SIZE(*src)); - VEC_SIZE(*dest) = VEC_SIZE(*src); -} - -#endif - -#endif