commit f8e38ad61126db546feffb16dce3fb4c7781ffba
parent 28dfbe162b48059c1b3ad99b0c56fb2d9100e8cf
Author: Jake Koroman <jake@jakekoroman.com>
Date: Fri, 12 Sep 2025 10:06:11 -0400
overhaul of jrk_Arena.
Diffstat:
M | jrk.h | | | 336 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 file changed, 242 insertions(+), 94 deletions(-)
diff --git a/jrk.h b/jrk.h
@@ -34,15 +34,17 @@ typedef double f64;
do { result = value; goto defer; } while(0)
#define JRK_KILOBYTES(x) ((u64)x*1024)
-#define JRK_MEGABYTES(x) (JRK_KILOBYTES((u64)x*1024))
-#define JRK_GIGABYTES(x) (JRK_MEGABYTES((u64)x*1024))
+#define JRK_MEGABYTES(x) ((u64)JRK_KILOBYTES((u64)x*1024))
+#define JRK_GIGABYTES(x) ((u64)JRK_MEGABYTES((u64)x*1024))
+#define JRK_TERABYTES(x) ((u64)JRK_GIGABYTES((u64)x*1024))
#define JRK_TMPSTRINGS_ARR_CAPACITY 4
#define JRK_TMPSTRINGS_STR_CAPACITY JRK_KILOBYTES(1)
typedef struct {
u8 *data;
- u64 count;
+ u64 offset;
+ u64 prev_offset;
u64 capacity;
} jrk_Arena;
@@ -60,8 +62,13 @@ typedef struct {
void *jrk_ecalloc(u64, u64);
void *jrk_erealloc(void*, u64);
-jrk_Arena jrk_arena_create(u64);
-void *jrk__arena_push(jrk_Arena*, u64);
+jrk_Arena jrk_arena_create(u8*, u64);
+void *jrk_arena_push(jrk_Arena*, u64);
+void jrk_arena_reset(jrk_Arena*);
+void *jrk_arena_resize(jrk_Arena*, void*, u64, u64);
+
+i32 jrk_arena_sb_appendf(jrk_Arena*, jrk_StringBuilder*, const char*, ...);
+void jrk_arena_sb_append_buf_at(jrk_Arena*, jrk_StringBuilder*, char *, u64, u64);
i32 jrk_rand_num(i32);
i32 jrk_rand_num_range(i32, i32);
@@ -102,10 +109,6 @@ char *jrk_tmpstrings_pushf(char *, ...);
#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)
-#define jrk_arena_push_struct(arena, type) (type *) jrk__arena_push(arena, sizeof(type))
-
#define jrk_sb_to_sv(sb) jrk_sv_from_parts((sb).items, (sb).count)
#define JRK_DA_DEFAULT_INIT_CAPACITY 16
@@ -122,6 +125,35 @@ char *jrk_tmpstrings_pushf(char *, ...);
} \
} while (0)
+#define jrk_arena_da_reserve(arena, da, expected_capacity) \
+ do { \
+ if ((da)->capacity == 0) { \
+ (da)->capacity = JRK_DA_DEFAULT_INIT_CAPACITY; \
+ (da)->items = jrk_arena_push(arena, (da)->capacity); \
+ break; \
+ } \
+ if ((expected_capacity) > (da)->capacity) { \
+ u64 old_cap = (da)->capacity; \
+ while ((expected_capacity) > (da)->capacity) { \
+ (da)->capacity *= 2; \
+ } \
+ (da)->items = jrk_arena_resize((arena), (da)->items, old_cap, (da)->capacity); \
+ } \
+ } while (0)
+
+#define jrk_arena_da_append(arena, da, item) \
+ do { \
+ jrk_arena_da_reserve((arena), (da), (da)->count + 1); \
+ (da)->items[(da)->count++] = (item); \
+ } while (0)
+
+#define jrk_arena_da_append_many(arena, da, new_items, new_items_count) \
+ do { \
+ jrk_arena_da_reserve((arena), (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_append(da, item) \
do { \
jrk_da_reserve((da), (da)->count + 1); \
@@ -151,79 +183,102 @@ char *jrk_tmpstrings_pushf(char *, ...);
#define jrk_da_foreach(type,it,da) for (type *it = (da)->items; it < (da)->items + (da)->count; ++it)
-#define jrk_sb_append_null(sb) jrk_da_append(sb, '\0')
-#define jrk_sb_free(sb) jrk_da_free(sb)
+#define jrk_sb_append_null(sb) jrk_da_append((sb), '\0')
+#define jrk_sb_free(sb) jrk_da_free((sb))
+
+#define jrk_arena_sb_append_null(arena, sb) jrk_arena_da_append((arena), (sb), '\0')
+
+#define jrk_arena_sb_append_cstr(arena, sb, cstr) \
+ do { \
+ const char *s = (cstr); \
+ i64 n = strlen((cstr)); \
+ jrk_arena_da_append_many((arena), (sb), s, n); \
+ } while (0)
-#define jrk_sb_append_cstr(sb, cstr) \
- do { \
- const char *s = (cstr); \
- i64 n = strlen(cstr); \
- jrk_da_append_many(sb, s, n); \
+#define jrk_sb_append_cstr(sb, cstr) \
+ do { \
+ const char *s = (cstr); \
+ i64 n = strlen((cstr)); \
+ jrk_da_append_many((sb), s, n); \
} while (0)
-#define jrk_sb_append_buf(sb, buf, size) jrk_da_append_many(sb, buf, size)
+
+#define jrk_arena_sb_append_buf(arena, sb, buf, size) jrk_arena_da_append_many((arena), (sb), (buf), (size))
+
+#define jrk_sb_append_buf(sb, buf, size) jrk_da_append_many((sb), (buf), (size))
#ifdef JRK_SHORTNAMES
- #define UNUSED JRK_UNUSED
- #define ARRSIZE JRK_ARRSIZE
- #define KILOBYTES JRK_KILOBYTES
- #define MEGABYTES JRK_MEGABYTES
- #define GIGABYTES JRK_GIGABYTES
-
- #define return_defer jrk_return_defer
-
- #define Arena jrk_Arena
- #define StringBuilder jrk_StringBuilder
- #define StringView jrk_StringView
-
- #define tmpstrings_push jrk_tmpstrings_push
- #define tmpstrings_pushf jrk_tmpstrings_pushf
-
- #define sb_appendf jrk_sb_appendf
- #define sb_append_null jrk_sb_append_null
- #define sb_append_buf jrk_sb_append_buf
- #define sb_append_buf_at jrk_sb_append_buf_at
- #define sb_append_cstr jrk_sb_append_cstr
- #define sb_free jrk_sb_free
- #define sb_fd_read_all jrk_sb_fd_read_all
- #define sb_fd_write_all jrk_sb_fd_write_all
- #define sb_to_sv jrk_sb_to_sv
- #define sb_write_file jrk_sb_write_file
- #define sb_read_entire_file jrk_sb_read_entire_file
-
- #define sv_trim_left jrk_sv_trim_left
- #define sv_trim_right jrk_sv_trim_right
- #define sv_trim jrk_sv_trim
- #define sv_from_cstr jrk_sv_from_cstr
- #define sv_from_parts jrk_sv_from_parts
- #define sv_chop_delim jrk_sv_chop_delim
-
- #define ecalloc jrk_ecalloc
- #define erealloc jrk_erealloc
- #define emalloc jrk_emalloc
-
- #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
- #define arena_push_struct jrk_arena_push_struct
- #define arena_push_array jrk_arena_push_array
-
- #define rand_num jrk_rand_num
- #define rand_num_range jrk_rand_num_range
-
- #define fd_close jrk_fd_close
- #define fd_open_read jrk_fd_open_read
- #define fd_open_write jrk_fd_open_write
- #define fd_open_write_append jrk_fd_open_write_append
-
- #define shift jrk_shift
- #define shift_loop jrk_shift_loop
+ #define UNUSED JRK_UNUSED
+ #define ARRSIZE JRK_ARRSIZE
+ #define KILOBYTES JRK_KILOBYTES
+ #define MEGABYTES JRK_MEGABYTES
+ #define GIGABYTES JRK_GIGABYTES
+ #define TERABYTES JRK_TERABYTES
+
+ #define return_defer jrk_return_defer
+
+ #define Arena jrk_Arena
+ #define StringBuilder jrk_StringBuilder
+ #define StringView jrk_StringView
+
+ #define tmpstrings_push jrk_tmpstrings_push
+ #define tmpstrings_pushf jrk_tmpstrings_pushf
+
+ #define sb_appendf jrk_sb_appendf
+ #define sb_append_null jrk_sb_append_null
+ #define sb_append_buf jrk_sb_append_buf
+ #define sb_append_buf_at jrk_sb_append_buf_at
+ #define sb_append_cstr jrk_sb_append_cstr
+ #define sb_free jrk_sb_free
+ #define sb_fd_read_all jrk_sb_fd_read_all
+ #define sb_fd_write_all jrk_sb_fd_write_all
+ #define sb_to_sv jrk_sb_to_sv
+ #define sb_write_file jrk_sb_write_file
+ #define sb_read_entire_file jrk_sb_read_entire_file
+
+ #define sv_trim_left jrk_sv_trim_left
+ #define sv_trim_right jrk_sv_trim_right
+ #define sv_trim jrk_sv_trim
+ #define sv_from_cstr jrk_sv_from_cstr
+ #define sv_from_parts jrk_sv_from_parts
+ #define sv_chop_delim jrk_sv_chop_delim
+
+ #define ecalloc jrk_ecalloc
+ #define erealloc jrk_erealloc
+ #define emalloc jrk_emalloc
+
+ #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_push jrk_arena_push
+ #define arena_resize jrk_arena_resize
+ #define arena_reset jrk_arena_reset
+
+ #define arena_da_reserve jrk_arena_da_reserve
+ #define arena_da_append jrk_arena_da_append
+ #define arena_da_append_many jrk_arena_da_append_many
+
+ #define arena_sb_appendf jrk_arena_sb_appendf
+ #define arena_sb_append_buf_at jrk_arena_sb_append_buf_at
+ #define arena_sb_append_buf jrk_arena_sb_append_buf
+ #define arena_sb_append_cstr jrk_arena_sb_append_cstr
+ #define arena_sb_append_null jrk_arena_sb_append_null
+
+ #define rand_num jrk_rand_num
+ #define rand_num_range jrk_rand_num_range
+
+ #define fd_close jrk_fd_close
+ #define fd_open_read jrk_fd_open_read
+ #define fd_open_write jrk_fd_open_write
+ #define fd_open_write_append jrk_fd_open_write_append
+
+ #define shift jrk_shift
+ #define shift_loop jrk_shift_loop
#endif // JRK_SHORTNAMES
#ifdef JRK_IMPLEMENTATION
@@ -308,43 +363,136 @@ jrk_tmpstrings_pushf(char *fmt, ...)
}
jrk_Arena
-jrk_arena_create(u64 n)
+jrk_arena_create(u8 *buffer, u64 buffer_count)
+{
+ jrk_Arena result = {0};
+ result.data = buffer;
+ result.capacity = buffer_count;
+ result.offset = 0;
+ result.prev_offset = 0;
+ return result;
+}
+
+void *
+jrk_arena_push(jrk_Arena *arena, u64 n)
{
- jrk_Arena result;
- result.count = 0;
- result.capacity = n;
- result.data = jrk_ecalloc(result.capacity, 1);
+ jrk_assertv(arena->offset + n <= arena->capacity,
+ "jrk_arena_push(%p, %ld): arena push requires %ld bytes but has a capacity of %ld bytes",
+ arena, n, arena->offset + n, arena->capacity);
+
+ void *result = &arena->data[arena->offset];
+ arena->prev_offset = arena->offset;
+ arena->offset += n;
+ memset(result, 0, n);
return result;
}
void *
-jrk__arena_push(jrk_Arena *arena, u64 n)
+jrk_arena_resize(jrk_Arena *arena, void *old, u64 old_size, u64 new_size)
+{
+ jrk_assertv(new_size > old_size,
+ "jrk_arena_resize(%p, %p, %ld, %ld): new_size is smaller than the old_size",
+ arena, old, old_size, new_size);
+
+ jrk_assertv(arena->offset + (new_size - old_size) <= arena->capacity,
+ "jrk_arena_resize(%p, %p, %ld, %ld): arena resize requires %ld bytes but has a capacity of %ld bytes",
+ arena, old, old_size, new_size, arena->offset + (new_size - old_size), arena->capacity);
+
+ void *result = NULL;
+
+ if (old == &arena->data[arena->prev_offset]) {
+ result = old;
+ arena->offset = new_size;
+ } else {
+ result = &arena->data[arena->offset];
+ arena->prev_offset = arena->offset;
+ arena->offset += new_size;
+ memset(result, 0, new_size);
+ memmove(result, old, old_size);
+ }
+
+ return result;
+}
+
+void
+jrk_arena_reset(jrk_Arena *arena)
+{
+ arena->offset = 0;
+ arena->prev_offset = 0;
+ memset(arena->data, 0, arena->capacity);
+}
+
+i32
+jrk_arena_sb_appendf(jrk_Arena *arena, jrk_StringBuilder *sb, const char *fmt, ...)
{
- jrk_assertv(arena->count + n <= arena->capacity,
- "jrk__arena_push(%p, %ld): arena push requires %ld bytes but has a capacity of %ld bytes",
- arena, n, arena->count + n, arena->capacity
- );
+ i32 result = -1;
+
+ va_list args;
+ va_start(args, fmt);
+ result = vsnprintf(NULL, 0, fmt, args);
+ va_end(args);
+
+ jrk_arena_da_reserve(arena, sb, sb->count + result + 1);
+
+ va_start(args, fmt);
+ vsnprintf(sb->items + sb->count, result + 1, fmt, args);
+ va_end(args);
+ sb->count += result;
- void *result = &arena->data[arena->count];
- arena->count += n;
return result;
}
i32
jrk_sb_appendf(jrk_StringBuilder *sb, const char *fmt, ...)
{
+ i32 result = -1;
+
va_list args;
va_start(args, fmt);
- i32 n = vsnprintf(NULL, 0, fmt, args);
+ result = vsnprintf(NULL, 0, fmt, args);
va_end(args);
- jrk_da_reserve(sb, sb->count + n + 1);
+ jrk_da_reserve(sb, sb->count + result + 1);
+
va_start(args, fmt);
- vsnprintf(sb->items + sb->count, n + 1, fmt, args);
+ vsnprintf(sb->items + sb->count, result + 1, fmt, args);
va_end(args);
- sb->count += n;
+ sb->count += result;
+
+ return result;
+}
+
- return n;
+void
+jrk_arena_sb_append_buf_at(jrk_Arena *arena, jrk_StringBuilder *sb, char *buf, u64 size, u64 idx)
+{
+ jrk_assertv(idx < sb->count, "jrk_arena_sb_append_buf_at(%p, %p, %p, %ld, %ld): idx is greater than sb->count",
+ arena, sb, buf, size, idx);
+
+ u64 new_size = sb->count + size;
+ char *old_items = sb->items;
+
+ jrk_arena_da_reserve(arena, sb, new_size);
+
+ if (old_items == sb->items) { // didn't move
+ jrk_StringBuilder temp_builder = {0};
+ temp_builder.items = jrk_emalloc(sb->capacity);
+ temp_builder.count = sb->count;
+ temp_builder.capacity = sb->capacity;
+ memcpy(temp_builder.items, sb->items, sb->count);
+
+ memcpy(sb->items, temp_builder.items, idx);
+ memcpy(sb->items + idx, buf, size);
+ memcpy(sb->items + idx + size, temp_builder.items + idx, temp_builder.count - idx);
+
+ jrk_sb_free(temp_builder);
+ } else { // did move
+ memcpy(sb->items, old_items, idx);
+ memcpy(sb->items + idx, buf, size);
+ memcpy(sb->items + idx + size, old_items + idx, sb->count - idx);
+ }
+
+ sb->count = new_size;
}
void