#pragma once #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #include #include #include #include #include #if defined(__APPLE__) && defined(__MACH__) #define OS_POSIX 1 #define OS_MAC 1 #elif defined(_WIN32) #define OS_WINDOWS 1 #elif defined(__linux__) #define OS_POSIX 1 #define OS_LINUX 1 #elif defined(__EMSCRIPTEN__) #define OS_WASM 1 #else #error Unsupported platform #endif #if defined(__clang__) #define COMPILER_CLANG 1 #elif defined(__GNUC__) || defined(__GNUG__) #define COMPILER_GCC 1 #elif defined(_MSC_VER) #define COMPILER_MSVC 1 #else #error Unsupported compiler #endif #ifndef OS_WASM #define OS_WASM 0 #endif #ifndef OS_MAC #define OS_MAC 0 #endif #ifndef OS_WINDOWS #define OS_WINDOWS 0 #endif #ifndef OS_LINUX #define OS_LINUX 0 #endif #ifndef OS_POSIX #define OS_POSIX 0 #endif #ifndef COMPILER_MSVC #define COMPILER_MSVC 0 #endif #ifndef COMPILER_CLANG #define COMPILER_CLANG 0 #endif #ifndef COMPILER_GCC #define COMPILER_GCC 0 #endif #if OS_WINDOWS #define BREAK() __debugbreak() #elif OS_LINUX #define BREAK() raise(SIGTRAP) #elif OS_WASM #include EM_JS(void, JS_Breakpoint, (), { debugger; }) #define BREAK() JS_Breakpoint() #endif #define API #define Assert(x) \ if (!(x)) { \ BREAK(); \ } #define InvalidCodepath() Assert(!"invalid codepath") #define ElseInvalidCodepath() else {InvalidCodepath()} #define KiB(x) ((x##ull) * 1024ull) #define MiB(x) (KiB(x) * 1024ull) #define GiB(x) (MiB(x) * 1024ull) #define TiB(x) (GiB(x) * 1024ull) #define Lengthof(x) ((int64_t)((sizeof(x) / sizeof((x)[0])))) #define SLICE_LAST INT64_MAX using U8 = uint8_t; using U16 = uint16_t; using U32 = uint32_t; using U64 = uint64_t; using S8 = int8_t; using S16 = int16_t; using S32 = int32_t; using S64 = int64_t; using Int = S64; using UInt = U64; template T Min(T a, T b) { if (a > b) return b; return a; } template T ClampTop(T a, T top) { return Min(a, top); } template T Max(T a, T b) { if (a > b) return a; return b; } template T ClampBottom(T bottom, T b) { return Max(bottom, b); } template T Clamp(T value, T min, T max) { if (value < min) return min; if (value > max) return max; return value; } template void Swap(T *a, T *b) { T temp = *a; *a = *b; *b = temp; } inline bool IsPowerOf2(size_t x) { size_t result = (((x) & ((x)-1)) == 0); return result; } inline size_t WrapAroundPowerOf2(size_t x, size_t pow2) { Assert(IsPowerOf2(pow2)); size_t result = (((x) & ((pow2)-1llu))); return result; } inline uint64_t HashBytes(void *data, unsigned size) { uint8_t *data8 = (uint8_t *)data; uint64_t hash = (uint64_t)14695981039346656037ULL; for (unsigned i = 0; i < size; i++) { hash = hash ^ (uint64_t)(data8[i]); hash = hash * (uint64_t)1099511628211ULL; } return hash; } inline size_t GetAlignOffset(size_t size, size_t align) { Assert(IsPowerOf2(align)); size_t mask = align - 1; size_t val = size & mask; if (val) { val = align - val; } return val; } inline size_t AlignUp(size_t size, size_t align) { size_t result = size + GetAlignOffset(size, align); return result; } inline size_t AlignDown(size_t size, size_t align) { size += 1; // Make sure when align is 8 doesn't get rounded down to 0 size_t result = size - (align - GetAlignOffset(size, align)); return result; } template struct DEFER_ExitScope { T lambda; DEFER_ExitScope(T lambda) : lambda(lambda) {} ~DEFER_ExitScope() { lambda(); } DEFER_ExitScope(const DEFER_ExitScope &i) : lambda(i.lambda){}; private: DEFER_ExitScope &operator=(const DEFER_ExitScope &); }; class DEFER_ExitScopeHelp { public: template DEFER_ExitScope operator+(T t) { return t; } }; #define DEFER_CONCAT_INTERNAL(x, y) x##y #define DEFER_CONCAT(x, y) DEFER_CONCAT_INTERNAL(x, y) #define defer const auto DEFER_CONCAT(defer__, __LINE__) = DEFER_ExitScopeHelp() + [&]() struct RandomSeed { uint64_t a; }; inline uint64_t GetRandomU64(RandomSeed *state) { uint64_t x = state->a; x ^= x << 13; x ^= x >> 7; x ^= x << 17; return state->a = x; } #define STRINGIFY_(x) x #define STRINGIFY(x) STRINGIFY_(x) #define CONCAT_(a, b) a ## b #define CONCAT(a, b) CONCAT_(a, b)