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:
M | jrk.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)
{