#ifndef CORE_HPP #define CORE_HPP #include #include #include #include #include // ### Types ### typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; typedef uint8_t byte; typedef float real32; typedef double real64; // ### Sizes and Numbers ### #define Bytes(n) (n) #define Kilobytes(n) (n << 10) #define Megabytes(n) (n << 20) #define Gigabytes(n) (((uint64)n) << 30) #define Terabytes(n) (((uint64)n) << 40) #define Thousand(n) ((n)*1000) #define Million(n) ((n)*1000000) #define Billion(n) ((n)*1000000000LL) #define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0])) // ### Arenas ### struct Arena { void *memory; size_t capacity; size_t head; }; void *pushSize(Arena *arena, size_t bytes) { if (arena->capacity - arena->head >= bytes) { void *ptr = (char *)arena->memory + arena->head; arena->head += bytes; return ptr; } return 0; } #define PushArray(arena, type, size) (type *)pushSize(arena, sizeof(type) * (size)) #define PushStruct(arena, type, size) (type *)pushSize(arena, sizeof(type)) Arena createArena(size_t capacity) { Arena result = {}; result.memory = mmap(0, capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); result.capacity = capacity; result.head = 0; return result; } // ### Lists ### template struct list { T* data; size_t capacity; size_t length; }; #define PushList(arena, type, size) ((list){ PushArray(arena, type, size), size, 0 }) template T *appendList(list *list, T element) { if (list->length < list->capacity) { list->data[list->length] = element; list->length++; return &(list->data[list->length - 1]); } else { return 0; } } template void zeroList(list *list) { list->length = 0; memset(list->data, 0, list->capacity * sizeof(T)); } #define foreach(it, list, type) for (size_t __i = 0; __i < list.length; __i++) { type it = list.data[__i]; #define foreach_end() } // ### Strings ### #define strlit(lit) ((string){(char *)(lit), sizeof(lit) - 1}) struct string { char *str; size_t len; }; #define PushString(arena, length) ((string){ (char *)pushSize(arena, length), (length) }) const char *cstring(Arena *arena, list buf) { char *arr = PushArray(arena, char, buf.length + 1); memmove(arr, buf.data, buf.length); arr[buf.length] = '\0'; return arr; } const char *cstring(Arena *arena, string str) { char *arr = PushArray(arena, char, str.len + 1); memmove(arr, str.str, str.len); arr[str.len] = '\0'; return arr; } bool strEql(string s1, string s2) { if (s1.len != s2.len) { return false; } for (size_t i = 0; i < s1.len; i++) { if (s1.str[i] != s2.str[i]) { return false; } } return true; } string strReverse(Arena *arena, string str) { string reversed = PushString(arena, str.len); for ( int mainIndex = str.len - 1, reversedIndex = 0; mainIndex < str.len; mainIndex--, reversedIndex++ ) { reversed.str[reversedIndex] = str.str[mainIndex]; } return reversed; } string strSlice(char *data, size_t start, size_t stop) { return { data + start, stop - start, }; } // ### File IO ### size_t getFileSize(string file) { struct stat st; stat((char *)file.str, &st); return st.st_size; } list readEntireFile(Arena *arena, string file) { FILE *input = fopen((char *)file.str, "r"); size_t filesize = getFileSize(file); list readBuffer = PushList(arena, char, filesize); readBuffer.length = filesize; fread(readBuffer.data, sizeof(byte), filesize, input); fclose(input); return readBuffer; } int cmpint(const void *a, const void *b) { int *x = (int *)a; int *y = (int *)b; return (*x > *y) - (*x < *y); } #endif