#define CORE_BASE #if defined(__clang__) # define COMPILER_CLANG 1 # if defined(_WIN32) # define OS_WINDOWS 1 # elif defined(__linux__) # define OS_LINUX 1 # else # error Couldnt figure out the platform automatically # endif #elif defined(_MSC_VER) # define COMPILER_MSVC 1 # define OS_WINDOWS 1 #elif defined(__GNUC__) # define COMPILER_GCC 1 # if defined(__linux__) # define OS_LINUX 1 # endif #else # error Couldnt figure out the compiler #endif #if defined(OS_MAC) #define OS_UNIX 1 #endif #if defined(OS_LINUX) #define OS_UNIX 1 #endif #if !defined(COMPILER_MSVC) # define COMPILER_MSVC 0 #endif #if !defined(COMPILER_GCC) # define COMPILER_GCC 0 #endif #if !defined(COMPILER_CLANG) # define COMPILER_CLANG 0 #endif #if !defined(OS_WINDOWS) # define OS_WINDOWS 0 #endif #if !defined(OS_LINUX) # define OS_LINUX 0 #endif #if !defined(OS_MAC) # define OS_MAC 0 #endif #if !defined(OS_UNIX) # define OS_UNIX 0 #endif #if OS_WINDOWS #define OS_EXE ".exe" #define OS_NAME "Win32"_s #define OS_NAME_LOWER "win32"_s #elif OS_LINUX #define OS_EXE ".out" #define OS_NAME "Linux"_s #define OS_NAME_LOWER "linux"_s #elif OS_MAC #define OS_EXE ".out" #define OS_NAME "Mac"_s #define OS_NAME_LOWER "mac"_s #else #error Couldnt figure out the OS with C macros! #endif #if OS_WINDOWS #define NOMINMAX #define _CRT_SECURE_NO_WARNINGS #include #define Breakpoint __debugbreak() #define force_inline __forceinline #else #define Breakpoint (*(volatile int *)0 = 0) #define force_inline inline #endif #include #include #include typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; #define U64MAX UINT64_MAX #define U32MAX UINT32_MAX #define U16MAX UINT16_MAX #define U8MAX UINT8_MAX #define U64MIN 0 #define U32MIN 0 #define U16MIN 0 #define U8MIN 0 #define S64MAX INT64_MAX #define S64MIN INT64_MIN #define S32MAX INT32_MAX #define S32MIN INT32_MIN #define S16MAX INT16_MAX #define S16MIN INT16_MIN #define S8MAX INT8_MAX #define S8MIN INT8_MIN #define F32MAX FLT_MAX #define F32MIN FLT_MIN #define F64MAX DBL_MAX #define F64MIN DBL_MIN #define api #define CORE_Static static #define global static #define assert(x) do{if(!(x))Breakpoint;}while(0) #define assert_message(x,...) assert(x) #define invalid_codepath assert_message(0, "Invalid codepath") #define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0) #define invalid_default_case default: invalid_codepath #define not_implemented assert_message(0, "Not implemented") #define unused(x) ((void)x) #define buff_cap(x) (sizeof(x)/sizeof((x)[0])) #define is_flag_set(val,flag) ((val) & (flag)) #define set_flag(val,flag) ((val) |= (flag)) #define unset_flag(val,flag) ((val) &= (~(flag))) #define bit_flag(x) (1ull << (x)) #define kib(x) ((x)*1024llu) #define mib(x) (kib(x)*1024llu) #define gib(x) (mib(x)*1024llu) #define JOIN1(X,Y) X##Y #define JOIN(X,Y) JOIN1(X,Y) #define string_expand(x) (int)x.len, x.str struct String{ U8 *str; S64 len; }; global String string_null = {(U8 *)"null", 4}; union Intern_String{ // Basically just String String s; struct{ U8 *str; S64 len; }; }; struct Allocator { typedef void *Allocate(Allocator *, size_t); typedef void Deallocate(Allocator *, void *p); Allocate *allocate; Deallocate *deallocate; }; CORE_Static void memory_zero(void *p, size_t size); CORE_Static void deallocate_stub(Allocator *, void *) {} #define allocate_array(a, T, size,...) (T *)allocate_size(a, sizeof(T)*(size),##__VA_ARGS__) #define allocate_struct(a, T, ...) allocate_array(a, T, 1,##__VA_ARGS__) CORE_Static void *allocate_size(Allocator *allocator, size_t size, bool zero_memory = true) { void *result = allocator->allocate(allocator, size); if (zero_memory) { memory_zero(result, size); } return result; } CORE_Static void deallocate(Allocator *allocator, void *p) { assert(p); allocator->deallocate(allocator, p); } //----------------------------------------------------------------------------- // Utilities //----------------------------------------------------------------------------- CORE_Static size_t get_align_offset(size_t size, size_t align){ size_t mask = align - 1; size_t val = size & mask; if(val){ val = align - val; } return val; } CORE_Static size_t align_up(size_t size, size_t align){ size_t result = size + get_align_offset(size, align); return result; } CORE_Static size_t align_down(size_t size, size_t align){ size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0 size_t result = size - (align - get_align_offset(size, align)); return result; } CORE_Static void memory_copy(void *dst, void *src, size_t size){ U8 *d = (U8*)dst; U8 *s = (U8*)src; for(size_t i = 0; i < size; i++){ d[i] = s[i]; } } CORE_Static void memory_zero(void *p, size_t size){ U8 *pp = (U8 *)p; for(size_t i = 0; i < size; i++) pp[i] = 0; } template void swap(T &a, T &b){ T temp = a; a = b; b = temp; } template T max(T a, T b){ if(a > b) return a; return b; } template T min(T a, T b){ if(a > b) return b; return a; } template T clamp_top(T val, T max){ if(val > max) val = max; return val; } template T clamp_bot(T bot, T val){ if(val < bot) val = bot; return val; } template T clamp(T min, T val, T max){ if(val > max) val = max; if(val < min) val = min; return val; } CORE_Static U64 hash_string(String string) { U64 hash = (U64)14695981039346656037ULL; for (U64 i = 0; i < string.len; i++) { hash = hash ^ (U64)(string.str[i]); hash = hash * (U64)1099511628211ULL; } return hash; } CORE_Static U64 hash_u64(U64 x) { x *= 0xff51afd7ed558ccd; x ^= x >> 32; return x; } CORE_Static U64 hash_ptr(const void *ptr) { return hash_u64((uintptr_t)ptr); } CORE_Static U64 hash_mix(U64 x, U64 y) { // @note: murmur hash 3 mixer but I add the 'y' // which means it's probably bad, hopefully better // then some random scribble I could do x ^= (y >> 33); x *= 0xff51afd7ed558ccd; x ^= (x >> 33); x *= 0xc4ceb9fe1a85ec53; x ^= (y >> 33); return x; } CORE_Static U64 is_pow2(U64 x) { assert(x != 0); B32 result = (x & (x - 1llu)) == 0; return result; } CORE_Static U64 wrap_around_pow2(U64 x, U64 power_of_2) { assert(is_pow2(power_of_2)); U64 r = (((x)&((power_of_2)-1llu))); return r; } force_inline String operator""_s(const char *str, size_t size){ return String{(U8 *)str, (S64)size}; } force_inline B32 operator==(Intern_String a, Intern_String b){ return a.str == b.str; } force_inline B32 operator!=(Intern_String a, Intern_String b){ B32 result = a.str == b.str; return !result; } //----------------------------------------------------------------------------- // Very cool macros. Since these are macros it's recommended to wrap them // in a function and not use directly //----- ----------------------------------------------------------------------- #define SLL_QUEUE_ADD_MOD(f, l, n, next) \ do { \ if ((f) == 0) { \ (f) = (l) = (n); \ } else { \ (l) = (l)->next = (n); \ } \ } while (0) #define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next) #define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \ do { \ if ((f) == (l)) { \ (f) = (l) = 0; \ } else { \ (f) = (f)->next; \ } \ } while (0) #define SLL_QUEUE_POP_FIRST(f, l) SLL_QUEUE_POP_FIRST_MOD(f, l, next) #define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \ do { \ (new_stack_base)->next = (stack_base); \ (stack_base) = (new_stack_base); \ } while (0) #define SLL_STACK_ADD(stack_base, new_stack_base) SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) #define SLL_STACK_POP(stack_base) \ do { \ if (stack_base) { \ auto(N) = (stack_base); \ (stack_base) = (stack_base)->next; \ (N)->next = 0; \ } \ } while (0) #define DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev) \ do { \ if ((f) == 0) { \ (f) = (l) = (node); \ (node)->prev = 0; \ (node)->next = 0; \ } else { \ (l)->next = (node); \ (node)->prev = (l); \ (node)->next = 0; \ (l) = (node); \ } \ } while (0) #define DLL_QUEUE_ADD_LAST(f, l, node) DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev) #define DLL_QUEUE_ADD(f, l, node) DLL_QUEUE_ADD_LAST(f, l, node) #define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \ do { \ if ((first) == (last)) { \ assert_message((node) == (first), "Macro assert failed"); \ (first) = (last) = 0; \ } else if ((last) == (node)) { \ (last) = (last)->prev; \ (last)->next = 0; \ } else if ((first) == (node)) { \ (first) = (first)->next; \ (first)->prev = 0; \ } else { \ (node)->prev->next = (node)->next; \ (node)->next->prev = (node)->prev; \ } \ } while (0) #define DLL_QUEUE_REMOVE(first, last, node) DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) #define DLL_STACK_ADD_MOD(first, node, next, prev) \ do { \ (node)->next = (first); \ if ((first)) \ (first)->prev = (node); \ (first) = (node); \ (node)->prev = 0; \ } while (0) #define DLL_STACK_ADD(first, node) DLL_STACK_ADD_MOD(first, node, next, prev) #define DLL_STACK_REMOVE_MOD(first, node, next, prev) \ do { \ if ((node) == (first)) { \ (first) = (first)->next; \ if ((first)) \ (first)->prev = 0; \ } else { \ (node)->prev->next = (node)->next; \ if ((node)->next) \ (node)->next->prev = (node)->prev; \ } \ } while (0) #define DLL_STACK_REMOVE(first, node) DLL_STACK_REMOVE_MOD(first, node, next, prev) #define For_Linked_List_Named(a,it) for(auto *it = (a); it; it=it->next) // @todo: reference? #define For_Linked_List(a) For_Linked_List_Named(a,it) #define For_Named(a,it) for(auto &it : (a)) #define For(a) For_Named((a),it) #define Iter_Named(list, it) for(auto it = iterate(list); should_we_continue(&it); advance(&it)) #define Iter(list) Iter_Named(list, it)