298 lines
12 KiB
C
298 lines
12 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
// =============================================================================
|
|
// Third party includes
|
|
|
|
#define STB_SPRINTF_DECORATE(name) juliet_##name
|
|
#define STB_SPRINTF_STATIC
|
|
#include "external/stb_sprintf/stb_sprintf.h"
|
|
|
|
#define internal static
|
|
#define global static
|
|
#define local_persist static
|
|
|
|
#if (COMPILER_CLANG && OS_WINDOWS) || COMPILER_MSVC
|
|
# pragma section(".rdata$", read)
|
|
# define read_only __declspec(allocate(".rdata$"))
|
|
#elif (COMPILER_CLANG && OS_LINUX)
|
|
# define read_only __attribute__((section(".rodata")))
|
|
#else
|
|
// Note: not possible with GCC
|
|
# define read_only
|
|
#endif
|
|
|
|
#if COMPILER_CLANG || COMPILER_GCC
|
|
# define thread_static __thread
|
|
#elif COMPILER_MSVC
|
|
# define thread_static __declspec(thread)
|
|
#else
|
|
# error thread_static not defined for this compiler
|
|
#endif
|
|
|
|
// =============================================================================
|
|
// Units
|
|
|
|
#define KB(d) ((uint64)(d) << 10)
|
|
#define MB(d) ((uint64)(d) << 20)
|
|
#define GB(d) ((uint64)(d) << 30)
|
|
#define Million(n) ((n) * 1000000)
|
|
|
|
// =============================================================================
|
|
// Branch predictor hints
|
|
|
|
#if defined(__clang__)
|
|
# define Expect(expr, val) __builtin_expect((expr), (val))
|
|
#else
|
|
# define Expect(expr, val) (expr)
|
|
#endif
|
|
|
|
#define Likely(expr) Expect(expr, 1)
|
|
#define Unlikely(expr) Expect(expr, 0)
|
|
|
|
// =============================================================================
|
|
// Min Max Clamp
|
|
|
|
#define Min(A, B) (((A) < (B) ? (A) : (B)))
|
|
#define Max(A, B) (((A) > (B) ? (A) : (B)))
|
|
#define ClampTop(A, X) Min(A, X)
|
|
#define ClampBottom(X, B) Max(X, B)
|
|
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) : (X))
|
|
|
|
// =============================================================================
|
|
// Alignment
|
|
#if COMPILER_CLANG || COMPILER_GCC
|
|
# define AlignOf(Type) __alignof(Type)
|
|
#elif COMPILER_MSVC
|
|
# define AlignOf(Type) __alignof(Type)
|
|
#else
|
|
# error AlignOf not defined for this compiler
|
|
#endif
|
|
|
|
// =============================================================================
|
|
// For loop helpers
|
|
|
|
#define EachIndex(it, count) (uint64 it = 0; it < (count); ++it)
|
|
#define EachNode(it, Type, first) (Type* it = first; it != 0; it = it->next)
|
|
|
|
// =============================================================================
|
|
// Memory Helpers
|
|
|
|
#define MemoryCopy(dst, src, size) memmove((dst), (src), (size))
|
|
#define MemorySet(dst, src, size) memset((dst), (src), (size))
|
|
#define MemoryCompare(a, b, size) memcmp((a), (b), (size))
|
|
|
|
#define MemoryZero(ptr, size) memset((ptr), 0, (size))
|
|
#define MemoryZeroStruct(s) MemoryZero((s), sizeof(*(s)))
|
|
#define MemoryZeroArray(arr) MemoryZero((arr), sizeof(arr))
|
|
|
|
#define MemoryMatch(a, b, size) (MemoryCompare((a), (b), (size)) == 0)
|
|
#define MemoryMatchStruct(a, b) MemoryMatch((a), (b), sizeof(*(a)))
|
|
#define MemoryMatchArray(a, b) MemoryMatch((a), (b), sizeof(a))
|
|
|
|
// =============================================================================
|
|
// Asserts
|
|
|
|
#if COMPILER_CLANG || COMPILER_GCC
|
|
# define Trap() __builtin_trap()
|
|
#elif COMPILER_MSVC
|
|
# define Trap() __debugbreak()
|
|
#else
|
|
# error Unknown trap intrinsic for this compiler
|
|
#endif
|
|
|
|
#define AssertAlways(cond) \
|
|
do \
|
|
{ \
|
|
if (!(cond)) \
|
|
{ \
|
|
Trap(); \
|
|
} \
|
|
} \
|
|
while (0)
|
|
#if BUILD_DEBUG
|
|
# define Assert(cond) AssertAlways(cond)
|
|
#else
|
|
# define Assert(cond) (void)(cond)
|
|
#endif
|
|
|
|
#define StaticAssert(cond, ID) global uint8 GLUE(ID, __LINE__)[(cond) ? 1 : -1]
|
|
|
|
// =============================================================================
|
|
// Linked List macro
|
|
|
|
// Linked list macro helpers
|
|
#define CheckNil(nil, ptr) ((ptr) == 0 || (ptr) == nil)
|
|
#define SetNil(nil, ptr) ((ptr) = nil)
|
|
|
|
// Doubly-linked-lists
|
|
// clang-format off
|
|
#define DLL_insert_next_prev_zero(nil, first, last, ptr, node, next, previous) \
|
|
(CheckNil(nil, first) ? ((first) = (last) = (node), SetNil(nil, (node)->next), SetNil(nil, (node)->previous)) \
|
|
: CheckNil(nil, ptr) ? ((node)->next = (first), (first)->previous = (node), (first) = (node), SetNil(nil, (node)->previous)) \
|
|
: ((ptr) == (last)) ? ((last)->next = (node), (node )->previous = (last), (last ) = (node), SetNil(nil, (node)->next)) \
|
|
: (((CheckNil(nil, ptr) && CheckNil(nil, (ptr)->next)) ? (0) : ((ptr)->next->previous = (node))), \
|
|
((node)->next = (ptr)->next), ((ptr)->next = (node)), ((node)->previous = (ptr))))
|
|
#define DLL_push_back_next_prev_zero(nil, first, last, node, next, previous) \
|
|
DLL_insert_next_prev_zero(nil, first, last, last, node, next, previous)
|
|
#define DLL_remove_next_prev_zero(nil, first, last, node, next, previous) \
|
|
(((node) == (first) ? (first) = (node)->next : (0)), ((node) == (last) ? (last) = (last)->previous : (0)), \
|
|
(CheckNil(nil, (node)->previous) ? (0) : ((node)->previous->next = (node)->next)), \
|
|
(CheckNil(nil, (node)->next) ? (0) : ((node)->next->previous = (node)->previous)))
|
|
// clang-format on
|
|
|
|
// Single link double head lists (= queues)
|
|
#define SLL_queue_push_next_zero(nil, first, last, node, next) \
|
|
(CheckNil(nil, first) ? ((first) = (last) = (node), SetNil(nil, (node)->next)) \
|
|
: ((last)->next = (node), (last) = (node), SetNil(nil, (node)->next)))
|
|
|
|
// Single (link & head) lists (= stacks)
|
|
#define SLL_stack_push_next(first, node, next) ((node)->next = (first), (first) = (node))
|
|
#define SLL_stack_pop_next(first, next) ((first) = (first)->next);
|
|
|
|
// Double linked list helpers
|
|
#define DLL_push_back_next_prev(first, last, node, next, previous) \
|
|
DLL_push_back_next_prev_zero(0, first, last, node, next, previous)
|
|
#define DLL_remove_next_prev(first, last, node, next, prev) DLL_remove_next_prev_zero(0, first, last, node, next, prev)
|
|
#define DLL_push_back(first, last, node) DLL_push_back_next_prev_zero(0, first, last, node, next, previous)
|
|
#define DLL_remove(first, last, node) DLL_remove_next_prev_zero(0, first, last, node, next, previous)
|
|
|
|
// Queue helpers
|
|
#define SLL_queue_push(first, last, node) SLL_queue_push_next_zero(0, first, last, node, next)
|
|
|
|
// Stack helpers
|
|
#define SLL_stack_push(first, node) SLL_stack_push_next(first, node, next)
|
|
#define SLL_stack_pop(first) SLL_stack_pop_next(first, next)
|
|
|
|
// =============================================================================
|
|
// Helpers
|
|
|
|
#define AlignPow2(x, align) (((x) + (align) - 1) & (~((align) - 1)))
|
|
|
|
#define Stringify_(S) #S
|
|
#define Stringify(S) Stringify_(S)
|
|
|
|
#define GLUE_(A, B) A##B
|
|
#define GLUE(A, B) GLUE_(A, B)
|
|
|
|
#define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
|
|
#if ARCH_64BIT
|
|
# define IntFromPtr(ptr) ((uint64)(ptr))
|
|
#else
|
|
# error Missing pointer to integer cast for this architecture
|
|
#endif
|
|
#define PtrFromInt(i) (void*)(i)
|
|
|
|
// =============================================================================
|
|
// Core Types
|
|
|
|
typedef uint8_t uint8;
|
|
typedef uint16_t uint16;
|
|
typedef uint32_t uint32;
|
|
typedef uint64_t uint64;
|
|
typedef int8_t int8;
|
|
typedef int16_t int16;
|
|
typedef int32_t int32;
|
|
typedef int64_t int64;
|
|
typedef float float32;
|
|
typedef double float64;
|
|
|
|
typedef int8 bool8;
|
|
typedef int16 bool16;
|
|
typedef int32 bool32;
|
|
typedef int64 bool64;
|
|
|
|
// =============================================================================
|
|
// Core Constants
|
|
|
|
global uint8 max_uint8 = 0xFF;
|
|
global uint16 max_uint16 = 0xFFFF;
|
|
global uint32 max_uint32 = 0xFFFFFFFF;
|
|
global uint64 max_uint64 = 0xFFFFFFFFFFFFFFFFll;
|
|
|
|
global int8 max_int8 = (int8)0x7F;
|
|
global int16 max_int16 = (int16)0x7FFF;
|
|
global int32 max_int32 = (int32)0x7FFFFFFF;
|
|
global int64 max_int64 = (int64)0x7FFFFFFFFFFFFFFFll;
|
|
|
|
global const uint32 bitmask1 = 0x00000001;
|
|
global const uint32 bitmask2 = 0x00000003;
|
|
global const uint32 bitmask3 = 0x00000007;
|
|
global const uint32 bitmask4 = 0x0000000f;
|
|
global const uint32 bitmask5 = 0x0000001f;
|
|
global const uint32 bitmask6 = 0x0000003f;
|
|
global const uint32 bitmask7 = 0x0000007f;
|
|
global const uint32 bitmask8 = 0x000000ff;
|
|
global const uint32 bitmask9 = 0x000001ff;
|
|
global const uint32 bitmask10 = 0x000003ff;
|
|
global const uint32 bitmask11 = 0x000007ff;
|
|
global const uint32 bitmask12 = 0x00000fff;
|
|
global const uint32 bitmask13 = 0x00001fff;
|
|
global const uint32 bitmask14 = 0x00003fff;
|
|
global const uint32 bitmask15 = 0x00007fff;
|
|
global const uint32 bitmask16 = 0x0000ffff;
|
|
global const uint32 bitmask17 = 0x0001ffff;
|
|
global const uint32 bitmask18 = 0x0003ffff;
|
|
global const uint32 bitmask19 = 0x0007ffff;
|
|
global const uint32 bitmask20 = 0x000fffff;
|
|
global const uint32 bitmask21 = 0x001fffff;
|
|
global const uint32 bitmask22 = 0x003fffff;
|
|
global const uint32 bitmask23 = 0x007fffff;
|
|
global const uint32 bitmask24 = 0x00ffffff;
|
|
global const uint32 bitmask25 = 0x01ffffff;
|
|
global const uint32 bitmask26 = 0x03ffffff;
|
|
global const uint32 bitmask27 = 0x07ffffff;
|
|
global const uint32 bitmask28 = 0x0fffffff;
|
|
global const uint32 bitmask29 = 0x1fffffff;
|
|
global const uint32 bitmask30 = 0x3fffffff;
|
|
global const uint32 bitmask31 = 0x7fffffff;
|
|
global const uint32 bitmask32 = 0xffffffff;
|
|
|
|
global const uint32 bit1 = (1 << 0);
|
|
global const uint32 bit2 = (1 << 1);
|
|
global const uint32 bit3 = (1 << 2);
|
|
global const uint32 bit4 = (1 << 3);
|
|
global const uint32 bit5 = (1 << 4);
|
|
global const uint32 bit6 = (1 << 5);
|
|
global const uint32 bit7 = (1 << 6);
|
|
global const uint32 bit8 = (1 << 7);
|
|
global const uint32 bit9 = (1 << 8);
|
|
global const uint32 bit10 = (1 << 9);
|
|
global const uint32 bit11 = (1 << 10);
|
|
global const uint32 bit12 = (1 << 11);
|
|
global const uint32 bit13 = (1 << 12);
|
|
global const uint32 bit14 = (1 << 13);
|
|
global const uint32 bit15 = (1 << 14);
|
|
global const uint32 bit16 = (1 << 15);
|
|
global const uint32 bit17 = (1 << 16);
|
|
global const uint32 bit18 = (1 << 17);
|
|
global const uint32 bit19 = (1 << 18);
|
|
global const uint32 bit20 = (1 << 19);
|
|
global const uint32 bit21 = (1 << 20);
|
|
global const uint32 bit22 = (1 << 21);
|
|
global const uint32 bit23 = (1 << 22);
|
|
global const uint32 bit24 = (1 << 23);
|
|
global const uint32 bit25 = (1 << 24);
|
|
global const uint32 bit26 = (1 << 25);
|
|
global const uint32 bit27 = (1 << 26);
|
|
global const uint32 bit28 = (1 << 27);
|
|
global const uint32 bit29 = (1 << 28);
|
|
global const uint32 bit30 = (1 << 29);
|
|
global const uint32 bit31 = (1 << 30);
|
|
global const uint32 bit32 = (1 << 31);
|
|
|
|
// =============================================================================
|
|
// Safe Casts
|
|
|
|
internal uint16 safe_cast_uint16(uint32 val);
|
|
internal uint32 safe_cast_uint32(uint64 val);
|
|
internal int32 safe_cast_int32(int64 val);
|
|
|
|
// =============================================================================
|
|
// Time functions
|
|
|
|
internal uint64 now_time_us();
|
|
internal void sleep_ms(uint32 ms);
|