jrk

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

commit 5447266dfb6bc5ad7dcc8a668f4eb78b211eeee5
Author: Jake Koroman <jake@jakekoroman.com>
Date:   Mon, 21 Jul 2025 19:35:16 -0400

Ready. Set. Go!

Diffstat:
Ajrk.h | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 196 insertions(+), 0 deletions(-)

diff --git a/jrk.h b/jrk.h @@ -0,0 +1,196 @@ +#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; +typedef int64_t i64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef float f32; +typedef double f64; + +typedef struct { + u8 *data; + u64 length; + 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 + * than dealing with using the hyper specific arr functions when + * using with strings. + */ +typedef struct { + char *data; + u64 length; +} jrk_string; + +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); + +#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_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_strchop_delim_next(jrk_str,str,delim,n) jrk_strchop_delim(jrk_str.data ? \ + str + (jrk_str.data - str) + jrk_str.length + 1 : str, \ + delim, n) + +#ifdef JRK_SHORTNAMES +#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 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 arena_expand jrk_arena_expand + +#define strchop_delim jrk_strchop_delim +#define strchop_delim_next jrk_strchop_delim_next +#define strput jrk_strput +#define strputn jrk_strputn +#define string_from_parts jrk_string_from_parts + +#endif // JRK_SHORTNAMES + +#ifdef JRK_IMPLEMENTATION +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#define jrk_die(x) do { fprintf(stderr, "%s:%d: error: "x"\n", __FILE__, __LINE__); exit(69); } while(0) +#define jrk_edie(x) do { fprintf(stderr, "%s:%d: error: "x": %s\n", __FILE__, __LINE__, strerror(errno)); exit(69); } while(0) + +#ifdef JRK_SHORTNAMES +#define die jrk_die +#define edie jrk_edie +#endif // JRK_SHORTNAMES + +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 = realloc(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) +{ + jrk_arena result; + result.length = 0; + result.capacity = n; + result.data = malloc(result.capacity); + return result; +} + +void * +jrk__arena_push(jrk_arena *arena, u64 n) +{ + while (arena->length + n >= arena->capacity) + jrk_arena_expand(arena, arena->capacity * 2); + + void *result = &arena->data[arena->length]; + arena->length += n; + return result; +} + +void +jrk_arena_expand(jrk_arena *arena, u64 new_capacity) +{ + u8 *tmp = realloc(arena->data, new_capacity); + + if (!tmp) + jrk_die("buy more ram lol"); + + arena->capacity = new_capacity; + arena->data = tmp; +} + +jrk_string +jrk_string_from_parts(char *str, u64 n) +{ + jrk_string result = {0}; + result.data = str; + result.length = n; + return result; +} + +jrk_string +jrk_strchop_delim(char *str, char delim, u64 n) +{ + for (u64 i = 0; i < n; ++i) { + if (str[i] == '\0') + return jrk_string_from_parts(str, i); + + if (str[i] == delim) + return jrk_string_from_parts(str, i); + } + + return (jrk_string) {0}; +} + +void +jrk_strput(jrk_string string) +{ + printf("%*.*s\n", (int) string.length, (int) string.length, string.data); +} + +void +jrk_strputn(jrk_string string, u64 n) +{ + printf("%*.*s\n", (int) n, (int) n, string.data); +} + +#endif // JRK_IMPLEMENTATION