jrk

my own c stdlib to keep myself sane
git clone git://git.jakekoroman.com/jrk
Log | Files | Refs

commit f9d4f4b1d711ded078027e12ebc3141ba66180fb
parent 2e5c2e9b0edc340ac147afb63ad8b417afcfb882
Author: Jake Koroman <jake@jakekoroman.com>
Date:   Mon, 28 Jul 2025 15:24:45 -0400

completely reworked dynamic array api design.

Diffstat:
Mjrk.h | 99++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 50 insertions(+), 49 deletions(-)

diff --git a/jrk.h b/jrk.h @@ -24,11 +24,6 @@ typedef struct { u64 capacity; } jrk_arena; -typedef struct { - u64 capacity; - u64 length; -} jrk_array_header; - /* NOTE(jake): * I could use the existing jrk_array_header approach to strings * but I much prefer just setting the data pointer to strings @@ -43,8 +38,6 @@ typedef struct { void *jrk_ecalloc(u64, u64); void *jrk_erealloc(void*, u64); -void *jrk_arrgrow(void*, u64, u64, u64); - jrk_arena jrk_arena_create(u64); void *jrk__arena_push(jrk_arena*, u64); void jrk_arena_expand(jrk_arena*, u64); @@ -58,17 +51,10 @@ void jrk_strputn(jrk_string, u64); i32 jrk_rand_num(i32); i32 jrk_rand_num_range(i32, i32); -#define jrk_emalloc(n) jrk_ecalloc(1, n) +/* NOTE(jake): no shortname as 'assert' is just too generic */ +#define jrk_assert(c, msg) do { if (!(c)) jrk_die("jrk_assert: "msg); } while(0) -#define jrk_arrsetcap(arr,n) ((arr) = jrk_arrgrow(arr,0,sizeof(typeof(*arr)),n)) -#define jrk_arr_header(arr) ((jrk_array_header *) (arr) - 1) -#define jrk_arrlen(arr) ((arr) ? jrk_arr_header(arr)->length : 0) -#define jrk_arrcap(arr) ((arr) ? jrk_arr_header(arr)->capacity : 0) -#define jrk_arrput(arr,val) (jrk_arrmaybegrow(arr,1), (arr)[jrk_arr_header(arr)->length++] = (val)) -#define jrk_arrmaybegrow(arr,n) ((!(arr) || jrk_arrlen(arr) + (n) > jrk_arrcap(arr)) ? \ - (arr) = jrk_arrgrow(arr, n, sizeof(typeof(*arr)), 0) : 0) -#define jrk_arrfree(arr) (free(jrk_arr_header(arr))) -#define jrk_arrforeach(type,it,arr) for (type *it = (arr); it < (arr) + jrk_arrlen(arr); ++it) +#define jrk_emalloc(n) jrk_ecalloc(1, n) #define jrk_arena_destroy(arena) ((arena.data) ? free(arena.data) : (void) 0) #define jrk_arena_push_array(arena, type, n) (type *) jrk__arena_push(arena, sizeof(type) * n) @@ -78,17 +64,58 @@ i32 jrk_rand_num_range(i32, i32); str + (jrk_str.data - str) + jrk_str.length + 1 : str, \ delim, n) +#define jrk_da_reserve(da, expected_capacity) \ + do { \ + if ((expected_capacity) > (da)->capacity) { \ + if ((da)->capacity == 0) { \ + (da)->capacity = 4; \ + } \ + while ((expected_capacity) > (da)->capacity) { \ + (da)->capacity *= 2; \ + } \ + (da)->items = jrk_erealloc((da)->items, (da)->capacity * sizeof(*(da)->items)); \ + jrk_assert((da)->items, "buy more ram lol"); \ + } \ + } while (0) + +#define jrk_da_append(da, item) \ + do { \ + jrk_da_reserve((da), (da)->count + 1); \ + (da)->items[(da)->count++] = (item); \ + } while (0); + +#define jrk_da_append_many(da, new_items, new_items_count) \ + do { \ + jrk_da_reserve((da), (da)->count + (new_items_count)); \ + memcpy((da)->items + (da)->count, (new_items), (new_items_count)*sizeof(*(da)->items)); \ + (da)->count += (new_items_count); \ + } while (0) + +#define jrk_da_create(name, type) \ + struct name { \ + type *items; \ + u64 count; \ + u64 capacity; \ + }; \ + typedef struct name name + +#define jrk_da_free(da) \ + jrk_assert((da).items, "bad free: jrk_da_free da.items is NULL"); \ + free((da).items) + +#define jrk_da_foreach(type,it,da) for (type *it = (da)->items; it < (da)->items + (da)->count; ++it) + #ifdef JRK_SHORTNAMES #define ecalloc jrk_ecalloc #define erealloc jrk_erealloc #define emalloc jrk_emalloc -#define arrput jrk_arrput -#define arrlen jrk_arrlen -#define arrcap jrk_arrcap -#define arrfree jrk_arrfree -#define arrsetcap jrk_arrsetcap -#define arrforeach jrk_arrforeach +#define da_reserve jrk_da_reserve +#define da_append jrk_da_append +#define da_append_many jrk_da_append_many +#define da_foreach jrk_da_foreach +#define da_create jrk_da_create +#define da_free jrk_da_free #define arena_create jrk_arena_create #define arena_destroy jrk_arena_destroy @@ -141,32 +168,6 @@ jrk_erealloc(void *ptr, u64 size) return p; } -void * -jrk_arrgrow(void *arr, u64 addlen, u64 elemsize, u64 min_cap) -{ - u64 min_len = jrk_arrlen(arr) + addlen; - - if (min_len > min_cap) - min_cap = min_len; - - if (min_cap <= jrk_arrcap(arr)) - return arr; - - if (min_cap < 2 * jrk_arrcap(arr)) - min_cap = 2 * jrk_arrcap(arr); - else if (min_cap < 4) - min_cap = 4; - - void *temp = jrk_erealloc(arr ? jrk_arr_header(arr) : NULL, elemsize * min_cap + sizeof(jrk_array_header)); - temp = (jrk_array_header *) temp + 1; - - if (arr == NULL) - jrk_arr_header(temp)->length = 0; - - jrk_arr_header(temp)->capacity = min_cap; - return temp; -} - jrk_arena jrk_arena_create(u64 n) {