#include #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 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 #define rand_num jrk_rand_num #define rand_num_range jrk_rand_num_range #endif // JRK_SHORTNAMES #ifdef JRK_IMPLEMENTATION #include #include #include #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); } static inline i32 jrk_rand_num(i32 upbound) { return rand() % upbound + 1; } static inline i32 jrk_rand_num_range(i32 min, i32 max) { return rand() % (max - min + 1) + min; } #endif // JRK_IMPLEMENTATION