221 lines
4.5 KiB
C++
221 lines
4.5 KiB
C++
#pragma once
|
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#endif
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <signal.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
#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 <emscripten.h>
|
|
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 <class T>
|
|
T Min(T a, T b) {
|
|
if (a > b) return b;
|
|
return a;
|
|
}
|
|
|
|
template <class T>
|
|
T ClampTop(T a, T top) {
|
|
return Min(a, top);
|
|
}
|
|
|
|
template <class T>
|
|
T Max(T a, T b) {
|
|
if (a > b) return a;
|
|
return b;
|
|
}
|
|
|
|
template <class T>
|
|
T ClampBottom(T bottom, T b) {
|
|
return Max(bottom, b);
|
|
}
|
|
|
|
template <class T>
|
|
T Clamp(T value, T min, T max) {
|
|
if (value < min) return min;
|
|
if (value > max) return max;
|
|
return value;
|
|
}
|
|
|
|
template <class T>
|
|
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 <typename T>
|
|
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 <typename T>
|
|
DEFER_ExitScope<T> 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)
|