#ifndef UI_UTILS #define UI_UTILS #include #include #include #include #include #include #include #include #ifdef _GNU_SOURCE #include #endif #define UI_INTERNAL static #define UI_GLOBAL typedef signed char i8; typedef unsigned char u8; typedef signed short int i16; typedef unsigned short int u16; typedef signed int i32; typedef unsigned int u32; typedef signed long int i64; typedef unsigned long int u64; UI_INTERNAL void __crash_error(const char *message, const char *file, u32 line) { fprintf(stderr, "(%s:%d): %s\n", file, line, message); exit(1); } #define crash_error(message) __crash_error(message, __FILE__, __LINE__) #define crash_errno() __crash_error(strerror(errno), __FILE__, __LINE__) #define assert_mmap(expr) \ if ((expr) == MAP_FAILED) \ crash_errno() #define assert_errno(expr) \ if (errno != 0) \ crash_errno() #define assert_success(actual, expected) \ if ((actual) != expected) \ crash_error("assertion failed") #define assert_failure(actual, expected) \ if ((actual) == expected) \ crash_error("assertion failed") typedef struct { uint64_t size; const char *buf; } String; String string_slice(const char *cStr) { String str = {0}; str.size = strlen(cStr); str.buf = cStr; return str; } typedef struct { u64 size; u64 capacity; u8 *buffer; } Arena; Arena *arena_init(void) { Arena *arena = malloc(sizeof(Arena)); size_t page_size = sysconf(_SC_PAGE_SIZE); arena->capacity = page_size * 4; assert_mmap(arena->buffer = mmap(0, arena->capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)); return arena; } void *arena_alloc(Arena *arena, u64 size, u8 align) { void *mem; u8 offset; u64 available = arena->capacity - arena->size; if (size > available) { assert_mmap(arena->buffer = mremap(arena->buffer, arena->size, arena->size + (available * 2), 0)); } mem = &(arena->buffer[arena->size]); offset = (u64)mem % align; mem = (void *)((u64)mem + offset); arena->size += size + offset; return mem; } void arena_zero(Arena *arena) { arena->size = 0; memset(arena->buffer, 0, arena->size); } void arena_free(Arena *arena) { if (munmap(arena->buffer, arena->capacity) == -1) { crash_error("can't unmap arena"); } arena->buffer = 0; arena->size = 0; arena->capacity = 0; } typedef struct { Arena *arena; u64 initial; } ArenaTemp; ArenaTemp *arena_temp(Arena *arena) { ArenaTemp *temp = malloc(sizeof(ArenaTemp)); temp->arena = arena; temp->initial = arena->size; return temp; } void arena_temp_free(ArenaTemp *temp) { temp->arena->size = temp->initial; free(temp); } #if __STDC_VERSION__ >= 202311L #define arena_type(arena, type) \ (type *)(arena_alloc(arena, sizeof(type), alignof(type))) #define arena_array(arena, type, size) \ (type *)(arena_alloc(arena, sizeof(type) * size, alignof(type))) #elif __STDC_VERSION__ >= 201112L (type *)(arena_alloc(arena, sizeof(type), _Alignof(type))) #define arena_array(arena, type, size) \ (type *)(arena_alloc(arena, sizeof(type) * size, _Alignof(type))) #else #define arena_type(arena, type) \ (type *)(arena_alloc(arena, sizeof(type), __alignof__(type))) #define arena_array(arena, type, size) \ (type *)(arena_alloc(arena, sizeof(type) * size, __alignof__(type))) #endif #endif