jrk

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

commit e83b7450edfec4e90e9d8e2443f3bc352c442cf7
parent e217f11c188e9f47031cf4f80d4ac54a93e92671
Author: Jake Koroman <jake@jakekoroman.com>
Date:   Fri, 31 Oct 2025 16:01:51 -0400

complete overhaul of dynamic arrays and no more shortnames.

Dynamic arrays now are created with jrk_array_prototype and
jrk_array_impl macros. The header includes one predefined array of char
for the jrk_StringBuilder api. This new api embeds allocation related
functions in the struct. This allows for easy integration with any
allocator you choose however it comes at the cost of three extra
pointers in the struct. If the pointers are NULL the allocs will call
the default allocators, see JRK_ARRAY_DEFAULT_ALLOC_FN and JRK_ARRAY_DEFAULT_REALLOC_FN
macros.

Also no more shortnames, don't be lazy :).
This change prioritizes code readability.

Diffstat:
Mjrk.h | 643+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 268 insertions(+), 375 deletions(-)

diff --git a/jrk.h b/jrk.h @@ -1,24 +1,17 @@ /* + * NOTES: + * - i think i've finally landed on dynamic array api + * that i like. + * * TODO: * - look at at the jrk_sv_chop_delim_loop stuff. there must * must be a better way of handling things. * - * NOTES: - * - arena function failures will not crash the program but generic sb/da - * functions will. this isn't the most elegant but im ok with assuming - * mallocs will never fail and if they do you have bigger problems. - * however arena allocs can and will fail as they are sized by the user, - * so these shouldn't crash the program. */ #include <stdbool.h> #include <stdint.h> -#ifdef JRK_IMPLEMENTATION_WITH_SHORTNAMES - #define JRK_IMPLEMENTATION - #define JRK_SHORTNAMES -#endif // JRK_IMPLEMENTATION_WITH_SHORTNAMES - typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; @@ -54,44 +47,31 @@ typedef struct { } jrk_Arena; typedef struct { - char *items; - u64 count; - u64 capacity; -} jrk_StringBuilder; - -typedef struct { char *data; - u64 count; + u64 size; } jrk_StringView; void *jrk_ecalloc(u64, u64); void *jrk_erealloc(void*, u64); +void *jrk_array_alloc_function_arena(u64, u64, void*); +void *jrk_array_realloc_function_arena(void*, u64, u64, void*); + jrk_Arena jrk_arena_create(u8*, u64); void *jrk_arena_push(jrk_Arena*, u64); char *jrk_arena_push_strf(jrk_Arena*, char*, ...); void jrk_arena_reset(jrk_Arena*); void *jrk_arena_resize(jrk_Arena*, void*, u64, u64); -bool jrk_arena_sb_appendf(jrk_Arena*, jrk_StringBuilder*, const char*, ...); -bool 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); i32 jrk_fd_open_read(char*); i32 jrk_fd_open_write(char*); i32 jrk_fd_open_write_append(char*); -u64 jrk_fd_size(i32); +bool jrk_fd_size(i32, u64*); void jrk_fd_close(i32); -i32 jrk_sb_appendf(jrk_StringBuilder*, const char*, ...); -bool jrk_sb_fd_read_all(jrk_StringBuilder*, i32); -i64 jrk_sb_fd_write_all(jrk_StringBuilder*, i32); -bool jrk_sb_write_file(jrk_StringBuilder*, char*); -bool jrk_sb_read_entire_file(jrk_StringBuilder*, char*); -void jrk_sb_append_buf_at(jrk_StringBuilder*, char*, u64, u64); - jrk_StringView jrk_sv_from_parts(char*, u64); jrk_StringView jrk_sv_trim_right(jrk_StringView); jrk_StringView jrk_sv_trim_left(jrk_StringView); @@ -104,7 +84,7 @@ char *jrk_tmpstrings_pushf(char*, ...); /* XXX: im not thrilled with this api, the memory can get messy real fast */ #define jrk_sv_chop_delim_loop(sv, it, delim) \ - for (jrk_StringView it = jrk_sv_chop_delim(sv, delim); it.count != 0; it = jrk_sv_chop_delim(sv, delim)) + for (jrk_StringView it = jrk_sv_chop_delim(sv, delim); it.size != 0; it = jrk_sv_chop_delim(sv, delim)) #ifndef jrk_die #define jrk_die(x) \ @@ -169,7 +149,6 @@ char *jrk_tmpstrings_pushf(char*, ...); #define jrk_eerrorv(x, ...) jrk_errorv(x": %s", __VA_ARGS__, strerror(errno)) #endif -/* NOTE: 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_assertv(c, msg, ...) do { if (!(c)) jrk_diev("jrk_assert: "msg, __VA_ARGS__); } while(0) @@ -178,195 +157,117 @@ char *jrk_tmpstrings_pushf(char*, ...); #define jrk_emalloc(n) jrk_ecalloc(1, n) -#define jrk_sb_to_sv(sb) jrk_sv_from_parts((sb).items, (sb).count) - -#define JRK_DA_DEFAULT_INIT_CAPACITY 16 -#define jrk_da_reserve(da, expected_capacity) \ - do { \ - if ((expected_capacity) > (da)->capacity) { \ - if ((da)->capacity == 0) { \ - (da)->capacity = (expected_capacity) ? (expected_capacity) : JRK_DA_DEFAULT_INIT_CAPACITY; \ - } \ - while ((expected_capacity) > (da)->capacity) { \ - (da)->capacity *= 2; \ - } \ - (da)->items = jrk_erealloc((da)->items, (da)->capacity * sizeof(*(da)->items)); \ - } \ - } while (0) - -// NOTE: caller should verify (da)->items is valid -#define jrk_arena_da_reserve(arena, da, expected_capacity) \ - do { \ - if ((da)->capacity == 0) { \ - (da)->capacity = (expected_capacity) ? (expected_capacity) : JRK_DA_DEFAULT_INIT_CAPACITY; \ - (da)->items = jrk_arena_push(arena, (da)->capacity * sizeof(*(da)->items)); \ - break; \ - } \ - if ((expected_capacity) > (da)->capacity) { \ - u64 old_cap = (da)->capacity; \ - while ((expected_capacity) > (da)->capacity) { \ - (da)->capacity *= 2; \ - } \ - u64 old_size = old_cap * sizeof(*(da)->items); \ - u64 new_size = (da)->capacity * sizeof(*(da)->items); \ - (da)->items = jrk_arena_resize((arena), (da)->items, old_size, new_size); \ - } \ - } while (0) - -// NOTE: caller should verify (da)->items is valid -#define jrk_arena_da_append(arena, da, item) \ - do { \ - jrk_arena_da_reserve((arena), (da), (da)->count + 1); \ - if ((da)->items) { \ - (da)->items[(da)->count++] = (item); \ - } \ - } while (0) - -// NOTE: caller should verify (da)->items is valid -#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)); \ - if ((da)->items) { \ - 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); \ - (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) \ - do { \ - if ((da).items) \ - free((da).items); \ - } while (0) - -#define jrk_da_foreach(type,it,da) for (type *it = (da)->items; it < (da)->items + (da)->count; ++it) +#define JRK_ARRAY_DEFAULT_INIT_CAPACITY 16 -#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) +#ifndef JRK_ARRAY_DEFAULT_ALLOC_FN + #define JRK_ARRAY_DEFAULT_ALLOC_FN jrk_ecalloc +#endif -#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) +#ifndef JRK_ARRAY_DEFAULT_REALLOC_FN + #define JRK_ARRAY_DEFAULT_REALLOC_FN jrk_erealloc +#endif +typedef void *(*jrk_array_alloc_function_t) (u64, u64, void*); +typedef void *(*jrk_array_realloc_function_t) (void*, u64, u64, void*); + +#define __jrk_array_alloc(arr, count, size) (arr)->allocfn ? (arr)->allocfn((count), (size), (arr)->allocfn_user) : JRK_ARRAY_DEFAULT_ALLOC_FN((count), (size)) +#define __jrk_array_realloc(arr, _size) (arr)->reallocfn ? (arr)->reallocfn((arr)->items, (arr)->size * sizeof((arr)->items[0]), (_size), (arr)->allocfn_user) : JRK_ARRAY_DEFAULT_REALLOC_FN((arr)->items, (_size)) + +#define jrk_array_prototype(type) \ + typedef struct { \ + type *items; \ + u64 size; \ + u64 capacity; \ + jrk_array_alloc_function_t allocfn; \ + jrk_array_realloc_function_t reallocfn; \ + void *allocfn_user; \ + } jrk_Array_##type; \ + \ + bool jrk_array_##type##_init_ex(jrk_Array_##type*, u64, jrk_array_alloc_function_t, jrk_array_realloc_function_t, void*); \ + bool jrk_array_##type##_init(jrk_Array_##type*, u64); \ + void jrk_array_##type##_deinit(jrk_Array_##type*); \ + bool jrk_array_##type##_setcap(jrk_Array_##type*, u64); \ + bool jrk_array_##type##_push(jrk_Array_##type*, type); \ + bool jrk_array_##type##_pushn(jrk_Array_##type*, type*, u64) + +#define jrk_array_impl(type) \ + bool jrk_array_##type##_init_ex(jrk_Array_##type *arr, u64 capacity, jrk_array_alloc_function_t allocfn, jrk_array_realloc_function_t reallocfn, void *allocfn_user) \ + { \ + (arr)->allocfn = (allocfn) ? (allocfn) : NULL; \ + (arr)->reallocfn = (reallocfn) ? (reallocfn) : NULL; \ + (arr)->allocfn_user = (allocfn_user) ? (allocfn_user) : NULL; \ + (arr)->size = 0; \ + (arr)->capacity = (capacity); \ + (arr)->items = __jrk_array_alloc((arr), (arr)->capacity, sizeof(type)); \ + if (!(arr)->items) return false; \ + memset((arr)->items, 0, (arr)->capacity * sizeof(type)); \ + return true; \ + } \ + \ + bool jrk_array_##type##_init(jrk_Array_##type *arr, u64 capacity) \ + { \ + return jrk_array_##type##_init_ex(arr, capacity, NULL, NULL, NULL); \ + }\ + \ + void jrk_array_##type##_deinit(jrk_Array_##type *arr) \ + { \ + if ((arr)->items && !(arr)->allocfn) \ + free((arr)->items); \ + } \ + \ + bool jrk_array_##type##_setcap(jrk_Array_##type *arr, u64 new_capacity) \ + { \ + if (new_capacity < (arr)->capacity) return false; \ + (arr)->items = __jrk_array_realloc((arr), new_capacity * sizeof(type)); \ + if (!(arr)->items) return false; \ + memset((arr)->items + (arr)->size, 0, (new_capacity * sizeof(type)) - ((arr)->capacity * sizeof(type))); \ + (arr)->capacity = new_capacity; \ + return true; \ + } \ + \ + bool jrk_array_##type##_push(jrk_Array_##type *arr, type val) \ + { \ + if ((arr)->size + 1 > (arr)->capacity) { \ + while ((arr)->size + 1 > ((arr)->capacity)) \ + (arr)->capacity = (arr->capacity) ? (arr)->capacity * 2 : JRK_ARRAY_DEFAULT_INIT_CAPACITY; \ + (arr)->items = __jrk_array_realloc((arr), (arr)->capacity * sizeof(type)); \ + if (!(arr)->items) return false; \ + } \ + (arr)->items[(arr)->size++] = (val); \ + return true; \ + } \ + \ + bool jrk_array_##type##_pushn(jrk_Array_##type *arr, type *vals, u64 count) \ + { \ + if ((arr)->size + count > (arr)->capacity) { \ + while ((arr)->size + count > ((arr)->capacity)) \ + (arr)->capacity = (arr->capacity) ? (arr)->capacity * 2 : JRK_ARRAY_DEFAULT_INIT_CAPACITY; \ + (arr)->items = __jrk_array_realloc((arr), (arr)->capacity * sizeof(type)); \ + if (!(arr)->items) return false; \ + memset((arr)->items + (arr)->size, 0, count * sizeof(type)); \ + }\ + memcpy(&(arr)->items[(arr)->size], (vals), sizeof(type) * (count)); \ + (arr)->size += count; \ + return true; \ + } -#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 ARRLENGTH JRK_ARRLENGTH - #define KILOBYTES JRK_KILOBYTES - #define MEGABYTES JRK_MEGABYTES - #define GIGABYTES JRK_GIGABYTES - #define TERABYTES JRK_TERABYTES - - #define return_defer jrk_return_defer - #define die jrk_die - #define diev jrk_diev - #define edie jrk_edie - #define ediev jrk_ediev - #define log jrk_log - #define logv jrk_logv - #define error jrk_error - #define errorv jrk_errorv - - #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_push_strf jrk_arena_push_strf - #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 +jrk_array_prototype(char); +#define jrk_StringBuilder jrk_Array_char + +#define jrk_sb_append_null(sb) jrk_array_char_push((sb), 0) +#define jrk_sb_append_cstr(sb, str) jrk_sb_appendf((sb), (str)) +#define jrk_sb_append_buf(sb, buf, bufsz) jrk_array_char_pushn((sb), (buf), (bufsz)) +#define jrk_sb_init_ex(sb, size, allocfn, reallocfn, userarg) jrk_array_char_init_ex((sb), (size), (allocfn), (reallocfn), (userarg)) +#define jrk_sb_init_arena(sb, size, arena) jrk_sb_init_ex((sb), (size), jrk_array_alloc_function_arena, jrk_array_realloc_function_arena, (void *)(arena)) +#define jrk_sb_deinit(sb) jrk_array_char_deinit((sb)) +#define jrk_sb_to_sv(sb) jrk_sv_from_parts((sb).items, (sb).size) + +bool jrk_sb_appendf(jrk_StringBuilder*, char*, ...); +bool jrk_sb_append_buf_at(jrk_StringBuilder*, char*, u64, u64); +bool jrk_sb_fd_write(jrk_StringBuilder*, i32); +bool jrk_sb_write_entire_file(jrk_StringBuilder *, char *); +bool jrk_sb_fd_read_all(jrk_StringBuilder*, i32); +bool jrk_sb_read_entire_file(jrk_StringBuilder*, char*); #ifdef JRK_IMPLEMENTATION #include <ctype.h> @@ -379,6 +280,140 @@ char *jrk_tmpstrings_pushf(char*, ...); #include <sys/stat.h> #include <unistd.h> +jrk_array_impl(char) + +void * +jrk_array_alloc_function_arena(u64 size, u64 count, void *user) +{ + void *result = NULL; + jrk_Arena *arena = (jrk_Arena *) user; + result = jrk_arena_push(arena, size * count); + return result; +} + +void * +jrk_array_realloc_function_arena(void *ptr, u64 old_size, u64 new_size, void *user) +{ + void *result = NULL; + jrk_Arena *arena = (jrk_Arena *) user; + result = jrk_arena_resize(arena, ptr, old_size, new_size); + return result; +} + +bool +jrk_sb_appendf(jrk_StringBuilder *sb, char *fmt, ...) +{ + char buf[JRK_KILOBYTES(1)]; + va_list args; + va_start(args, fmt); + + i32 buf_sz = vsnprintf(buf, sizeof(buf), fmt, args); + if (buf_sz < 0) { + jrk_eerrorv("jrk_sb_appendf(%p, %s): failed to create full string from '%s'", (void *) sb, fmt, fmt); + return false; + } + va_end(args); + + i32 actual_sz = 0; + if ((u32) buf_sz > JRK_ARRLENGTH(buf)) { + actual_sz = JRK_ARRLENGTH(buf); + jrk_errorv("jrk_sb_appendf(%p, %s): pushing '%s' into sb caused truncation of %ld bytes", + (void *) sb, fmt, fmt, buf_sz - JRK_ARRLENGTH(buf)); + return false; + } else { + actual_sz = buf_sz; + } + + if (!jrk_array_char_pushn(sb, buf, actual_sz)) { + jrk_errorv("jrk_sb_appendf(%p, %s): failed to push '%s' into sb", (void *) sb, fmt, fmt); + return false; + } + + return true; +} + +bool +jrk_sb_append_buf_at(jrk_StringBuilder *sb, char *buf, u64 buf_sz, u64 idx) +{ + if (idx > sb->size) { + jrk_errorv("jrk_sb_append_buf_at(%p, %s, %ld, %ld): idx is greater than sb.size", + (void *)sb, buf, buf_sz, idx); + return false; + } + + if (sb->size + (buf_sz) > sb->capacity) { + while (sb->size + (buf_sz) > sb->capacity) { + sb->capacity *= 2; + } + sb->items = __jrk_array_realloc(sb, sb->capacity); + if (!sb->items) return false; \ + memset(sb->items + sb->size, 0, sb->capacity - sb->size); + } + + memmove(sb->items + idx + buf_sz, sb->items + idx, sb->size - idx); + memcpy(sb->items + idx, buf, buf_sz); + + sb->size += buf_sz; + return true; +} + +bool +jrk_sb_fd_read_all(jrk_StringBuilder *sb, i32 fd) +{ + bool result = true; + u64 filesize = 0; + if (!jrk_fd_size(fd, &filesize)) jrk_return_defer(false); + char *buf = jrk_emalloc(filesize); + if (read(fd, buf, filesize) < 0) { + jrk_eerrorv("jrk_sb_fd_read_all(%p, %d)", (void *)sb, fd); + jrk_return_defer(false); + } + + if (!jrk_sb_append_buf(sb, buf, filesize)) jrk_return_defer(false); +defer: + free(buf); + return result; +} + +bool +jrk_sb_fd_write(jrk_StringBuilder *sb, i32 fd) +{ + i64 result; + result = write(fd, (void *) sb->items, sb->size); + if (result < 0) { + jrk_eerrorv("jrk_sb_fd_write_all(%p, %d)", (void *)sb, fd); + return -1; + } + + return result; +} + +bool +jrk_sb_read_entire_file(jrk_StringBuilder *sb, char *filename) +{ + bool result = true; + i32 fd = jrk_fd_open_read(filename); + if (fd < 0) return false; + if (!jrk_sb_fd_read_all(sb, fd)) jrk_return_defer(false); + +defer: + jrk_fd_close(fd); + return result; +} + +bool +jrk_sb_write_entire_file(jrk_StringBuilder *sb, char *filename) +{ + bool result = true; + i32 fd = jrk_fd_open_write(filename); + if (fd < 0) return false; + if(!jrk_sb_fd_write(sb, fd)) jrk_return_defer(false); + +defer: + jrk_fd_close(fd); + return result; +} + void * jrk_ecalloc(u64 nmemb, u64 size) { @@ -522,171 +557,29 @@ jrk_arena_reset(jrk_Arena *arena) } bool -jrk_arena_sb_appendf(jrk_Arena *arena, jrk_StringBuilder *sb, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - i32 n = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - jrk_arena_da_reserve(arena, sb, sb->count + n + 1); - if (!sb->items) return false; - - va_start(args, fmt); - vsnprintf(sb->items + sb->count, n + 1, fmt, args); - va_end(args); - sb->count += n; - - return true; -} - -i32 -jrk_sb_appendf(jrk_StringBuilder *sb, const char *fmt, ...) -{ - i32 result = -1; - - va_list args; - va_start(args, fmt); - result = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - jrk_da_reserve(sb, sb->count + result + 1); - - va_start(args, fmt); - vsnprintf(sb->items + sb->count, result + 1, fmt, args); - va_end(args); - sb->count += result; - - return result; -} - -bool -jrk_arena_sb_append_buf_at(jrk_Arena *arena, jrk_StringBuilder *sb, char *buf, u64 size, u64 idx) +jrk_fd_size(i32 fd, u64 *size) { - if (idx >= sb->count) { - jrk_errorv("jrk_arena_sb_append_buf_at(%p, %p, %p, %ld, %ld): idx is greater than sb->count", - (void *) arena, (void *) sb, buf, size, idx); - return false; - } - - u64 new_size = sb->count + size; - char *old_items = sb->items; - - jrk_arena_da_reserve(arena, sb, new_size); - if (!sb->items) { - jrk_errorv("jrk_arena_sb_append_buf_at(%p, %p, %p, %ld, %ld): failed to reserve space for the jrk_StringBuilder", - (void *) arena, (void *) sb, buf, size, idx); + if (!size) { + jrk_errorv("jrk_fd_size(%d, %p): size ptr is NULL", fd, (void *) size); return false; } - 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; - - return true; -} - -void -jrk_sb_append_buf_at(jrk_StringBuilder *sb, char *buf, u64 size, u64 idx) -{ - jrk_assertv(idx < sb->count, "jrk_sb_append_buf_at(%p, %p, %ld, %ld): idx is greater than sb->count (%ld > %ld)", - (void *) sb, buf, size, idx, idx, sb->count); - - u64 new_size = sb->count + size; - char *temp = jrk_emalloc(new_size); - - memcpy(temp, sb->items, idx); - memcpy(temp + idx, buf, size); - memcpy(temp + idx + size, sb->items + idx, sb->count - idx); - - free(sb->items); - sb->items = temp; - sb->count = new_size; - - // NOTE: maybe keep it a proper ^2? - sb->capacity = new_size; -} - -u64 -jrk_fd_size(i32 fd) -{ struct stat statbuf = {0}; - if (fstat(fd, &statbuf) < 0) - jrk_ediev("jrk_fd_size(%d)", fd); - - return statbuf.st_size; -} - -bool -jrk_sb_fd_read_all(jrk_StringBuilder *sb, i32 fd) -{ - u64 sz = jrk_fd_size(fd); - jrk_da_reserve(sb, sz); - if (read(fd, sb->items, sz) < 0) { - jrk_eerrorv("jrk_sb_fd_read_all(%p, %d)", (void *)sb, fd); + if (fstat(fd, &statbuf) < 0) { + jrk_eerrorv("jrk_fd_size(%d, %p)", fd, (void *) size); return false; } - sb->count = sz; + *size = statbuf.st_size; return true; } -i64 -jrk_sb_fd_write_all(jrk_StringBuilder *sb, i32 fd) -{ - i64 result; - result = write(fd, (void *) sb->items, sb->count); - if (result < 0) { - jrk_eerrorv("jrk_sb_fd_write_all(%p, %d)", (void *)sb, fd); - return -1; - } - - return result; -} - void jrk_fd_close(i32 fd) { close(fd); } -bool -jrk_sb_write_file(jrk_StringBuilder *sb, char *path) -{ - i32 fd = jrk_fd_open_write(path); - if (fd < 0) return false; - if (jrk_sb_fd_write_all(sb, fd) < 0) return false; - jrk_fd_close(fd); - return true; -} - -bool -jrk_sb_read_entire_file(jrk_StringBuilder *sb, char *path) -{ - i32 fd = jrk_fd_open_read(path); - if (fd < 0) return false; - if (!jrk_sb_fd_read_all(sb, fd)) return false; - jrk_fd_close(fd); - - return true; -} - i32 jrk_fd_open_read(char *path) { @@ -731,11 +624,11 @@ jrk_fd_open_write_append(char *path) } jrk_StringView -jrk_sv_from_parts(char *data, u64 count) +jrk_sv_from_parts(char *data, u64 size) { jrk_StringView result = {0}; result.data = data; - result.count = count; + result.size = size; return result; } @@ -744,7 +637,7 @@ jrk_sv_from_cstr(char *data) { jrk_StringView result = {0}; result.data = data; - result.count = strlen(data); + result.size = strlen(data); return result; } @@ -752,16 +645,16 @@ jrk_StringView jrk_sv_trim_right(jrk_StringView sv) { u64 i = 0; - for (; i < sv.count && isspace(sv.data[sv.count - 1 - i]); ++i); - return jrk_sv_from_parts(sv.data, sv.count - i); + for (; i < sv.size && isspace(sv.data[sv.size - 1 - i]); ++i); + return jrk_sv_from_parts(sv.data, sv.size - i); } jrk_StringView jrk_sv_trim_left(jrk_StringView sv) { u64 i = 0; - for (; i < sv.count && isspace(sv.data[i]); ++i); - return jrk_sv_from_parts(sv.data + i, sv.count - i); + for (; i < sv.size && isspace(sv.data[i]); ++i); + return jrk_sv_from_parts(sv.data + i, sv.size - i); } jrk_StringView @@ -774,17 +667,17 @@ jrk_StringView jrk_sv_chop_delim(jrk_StringView *sv, char delim) { u64 i = 0; - while (i < sv->count && sv->data[i] != delim) + while (i < sv->size && sv->data[i] != delim) ++i; jrk_StringView result = jrk_sv_from_parts(sv->data, i); - if (i < sv->count) { + if (i < sv->size) { sv->data += i + 1; - sv->count -= i + 1; + sv->size -= i + 1; } else { sv->data += i; - sv->count -= i; + sv->size -= i; } return result;