Add optional arena to a Noh_String

This commit is contained in:
2026-06-19 16:49:11 +02:00
parent c9f43c152d
commit 6751e92f8a

View File

@@ -187,6 +187,17 @@ do {
(da)->elems[(da)->count++] = (elem); \ (da)->elems[(da)->count++] = (elem); \
} while(0) } while(0)
// The same as noh_da_append, but uses an arena to allocate more data. No data is freed.
#define noh_da_append_arena(arena, da, elem) \
do { \
if ((da)->count >= (da)->capacity) { \
(da)->capacity = (da)->capacity == 0 ? NOH_DA_INIT_CAP : (da)->capacity * 2; \
(da)->elems = noh_arena_alloc((arena), (da)->capacity * sizeof(*(da)->elems)); \
} \
\
(da)->elems[(da)->count++] = (elem); \
} while(0)
// Appends multiple elements to a dynamic array. Allocates more memory and moves all elements to newly allocated memory // Appends multiple elements to a dynamic array. Allocates more memory and moves all elements to newly allocated memory
// if needed. // if needed.
#define noh_da_append_multiple(da, new_elems, new_elems_count) \ #define noh_da_append_multiple(da, new_elems, new_elems_count) \
@@ -201,6 +212,19 @@ do {
(da)->count += new_elems_count; \ (da)->count += new_elems_count; \
} while (0) } while (0)
// The same as noh_da_append_multiple, but uses an arena to allocate more data. No data is freed.
#define noh_da_append_multiple_arena(arena, da, new_elems, new_elems_count) \
do { \
if ((da)->count + new_elems_count > (da)->capacity) { \
if ((da)->capacity == 0) (da)->capacity = NOH_DA_INIT_CAP; \
while ((da)->count + new_elems_count > (da)->capacity) (da)->capacity *= 2; \
(da)->elems = noh_arena_alloc((arena), (da)->capacity * sizeof(*(da)->elems)); \
} \
\
memcpy((da)->elems + (da)->count, new_elems, new_elems_count * sizeof(*(da)->elems)); \
(da)->count += new_elems_count; \
} while (0)
// Removes the element at the specified location. // Removes the element at the specified location.
#define noh_da_remove_at(da, index) \ #define noh_da_remove_at(da, index) \
do { \ do { \
@@ -335,6 +359,9 @@ typedef struct {
char *elems; char *elems;
size_t count; size_t count;
size_t capacity; size_t capacity;
// If set, memory will be allocated in this arena when adding to the string.
// if set or unset halfway through using a string, this will cause undefined behaviour.
Noh_Arena *arena;
} Noh_String; } Noh_String;
// Copies a Noh_String to the arena, and frees the Noh_String // Copies a Noh_String to the arena, and frees the Noh_String
@@ -343,6 +370,10 @@ char *noh_arena_consume_string(Noh_Arena *arena, Noh_String *string);
// Creates a Noh_String from a c-string. // Creates a Noh_String from a c-string.
Noh_String noh_string_from_cstr(const char *cstr); Noh_String noh_string_from_cstr(const char *cstr);
// Creates a Noh_String from a c-string.
// Provide a Noh_Arena to allocate the string's data in.
Noh_String noh_string_from_cstr_arena(Noh_Arena *arena, const char *cstr);
// Appends a null-terminated string into a Noh_String. // Appends a null-terminated string into a Noh_String.
void noh_string_append_cstr(Noh_String *string, const char *cstr); void noh_string_append_cstr(Noh_String *string, const char *cstr);
@@ -353,7 +384,10 @@ void noh_string_append_null(Noh_String *string);
void noh_string_replace(Noh_String *string, const char from, const char to); void noh_string_replace(Noh_String *string, const char from, const char to);
// Frees a Noh_String, freeing the memory used and settings the count and capacity to 0. // Frees a Noh_String, freeing the memory used and settings the count and capacity to 0.
#define noh_string_free(string) noh_da_free(string) #define noh_string_free(string) do { \
noh_assert(!(string)->arena && "A string with an arena cannot be freed."); \
noh_da_free(string); \
} while(0)
// Resets a Noh_String, setting the count to 0. // Resets a Noh_String, setting the count to 0.
#define noh_string_reset(string) noh_da_reset(string) #define noh_string_reset(string) noh_da_reset(string)
@@ -857,31 +891,54 @@ char *noh_arena_consume_string(Noh_Arena *arena, Noh_String *string) {
} }
Noh_String noh_string_from_cstr(const char *cstr) { Noh_String noh_string_from_cstr(const char *cstr) {
return noh_string_from_cstr_arena(cstr, NULL);
}
Noh_String noh_string_from_cstr_arena(Noh_Arena *arena, const char *cstr) {
Noh_String str = {0}; Noh_String str = {0};
if (arena) str.arena = arena;
noh_string_append_cstr(&str, cstr); noh_string_append_cstr(&str, cstr);
return str; return str;
} }
void noh_string_append_cstr(Noh_String *string, const char *cstr) { void noh_string_append_cstr(Noh_String *string, const char *cstr) {
size_t len = strlen(cstr); size_t len = strlen(cstr);
noh_da_append_multiple(string, cstr, len);
if (string->arena) {
noh_da_append_multiple_arena(string->arena, string, cstr, len);
} else {
noh_da_append_multiple(string, cstr, len);
}
} }
void noh_string_append_null(Noh_String *string) { void noh_string_append_null(Noh_String *string) {
noh_da_append(string, '\0'); if (string->arena) {
noh_da_append_arena(string->arena, string, '\0');
} else {
noh_da_append(string, '\0');
}
} }
void noh_string_replace(Noh_String *string, const char from, const char to) { void noh_string_replace(Noh_String *string, const char from, const char to) {
Noh_String result = {0}; Noh_String result = {0};
for (size_t i = 0; i < string->count; i++) { for (size_t i = 0; i < string->count; i++) {
if (string->elems[i] == from) { if (result.arena) {
noh_da_append(&result, to); if (string->elems[i] == from) {
noh_da_append_arena(result.arena, &result, to);
} else {
noh_da_append_arena(result.arena, &result, string->elems[i]);
}
} else { } else {
noh_da_append(&result, string->elems[i]); if (string->elems[i] == from) {
noh_da_append(&result, to);
} else {
noh_da_append(&result, string->elems[i]);
}
} }
} }
noh_string_free(string); if (!string->arena) noh_string_free(string);
string->elems = result.elems; string->elems = result.elems;
string->count = result.count; string->count = result.count;
string->capacity = result.capacity; string->capacity = result.capacity;
@@ -906,7 +963,11 @@ bool noh_string_read_file(Noh_String *string, const char *filename) {
size_t n = fread(buf, 1, buf_size, f); size_t n = fread(buf, 1, buf_size, f);
while (n > 0) { while (n > 0) {
noh_da_append_multiple(string, buf, n); if (string->arena) {
noh_da_append_multiple_arena(string->arena, string, buf, n);
} else {
noh_da_append_multiple(string, buf, n);
}
n = fread(buf, 1, buf_size, f); n = fread(buf, 1, buf_size, f);
} }
@@ -951,7 +1012,11 @@ Noh_String_View noh_sv_copy_cstr(Noh_Arena *arena, const char *cstr) {
} }
void noh_string_append_sv(Noh_String *string, Noh_String_View sv) { void noh_string_append_sv(Noh_String *string, Noh_String_View sv) {
noh_da_append_multiple(string, sv.elems, sv.count); if (string->arena) {
noh_da_append_multiple_arena(string->arena, string, sv.elems, sv.count);
} else {
noh_da_append_multiple(string, sv.elems, sv.count);
}
} }
void noh_sv_increase_position(Noh_String_View *sv, size_t distance) { void noh_sv_increase_position(Noh_String_View *sv, size_t distance) {
@@ -1293,9 +1358,15 @@ void noh_quote_if_needed(const char *value, Noh_String *string) {
if (!strchr(value, ' ')) { if (!strchr(value, ' ')) {
noh_string_append_cstr(string, value); noh_string_append_cstr(string, value);
} else { } else {
noh_da_append(string, '\''); if (string->arena) {
noh_string_append_cstr(string, value); noh_da_append_arena(string->arena, string, '\'');
noh_da_append(string, '\''); noh_string_append_cstr(string, value);
noh_da_append_arena(string->arena, string, '\'');
} else {
noh_da_append(string, '\'');
noh_string_append_cstr(string, value);
noh_da_append(string, '\'');
}
} }
} }