#pragma once // base_core.h - Fundamental types, macros, and linked list helpers // Inspired by raddebugger's base_core.h #include #include #include #include #include //////////////////////////////// // Codebase keywords #ifndef __APPLE__ #define internal static #define global static #endif #define local_persist static #define trvke true //////////////////////////////// // Base types typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef S32 B32; typedef float F32; typedef double F64; //////////////////////////////// // Limits #define max_U8 0xFF #define max_U16 0xFFFF #define max_U32 0xFFFFFFFF #define max_U64 0xFFFFFFFFFFFFFFFFull #define max_S8 0x7F #define max_S16 0x7FFF #define max_S32 0x7FFFFFFF #define max_S64 0x7FFFFFFFFFFFFFFFll //////////////////////////////// // Units #define KB(n) (((U64)(n)) << 10) #define MB(n) (((U64)(n)) << 20) #define GB(n) (((U64)(n)) << 30) //////////////////////////////// // Clamps, Mins, Maxes #define Min(A, B) (((A) < (B)) ? (A) : (B)) #define Max(A, B) (((A) > (B)) ? (A) : (B)) #define ClampTop(A, X) Min(A, X) #define ClampBot(X, B) Max(X, B) #define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) \ : (X)) //////////////////////////////// // Alignment / Sizing #define AlignPow2(x, b) (((x) + (b)-1) & (~((b)-1))) #define AlignDownPow2(x, b) ((x) & (~((b)-1))) #define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) //////////////////////////////// // Memory macros #define MemoryCopy(dst, src, size) memmove((dst), (src), (size)) #define MemorySet(dst, byte, size) memset((dst), (byte), (size)) #define MemoryCompare(a, b, size) memcmp((a), (b), (size)) #define MemoryZero(s, z) memset((s), 0, (z)) #define MemoryZeroStruct(s) MemoryZero((s), sizeof(*(s))) #define MemoryZeroArray(a) MemoryZero((a), sizeof(a)) #define MemoryMatch(a, b, z) (MemoryCompare((a), (b), (z)) == 0) //////////////////////////////// // Pointer / integer casts #define IntFromPtr(ptr) ((U64)(ptr)) #define PtrFromInt(i) (void *)(i) #define OffsetOf(T, m) IntFromPtr(&(((T *)0)->m)) //////////////////////////////// // Member access #define CastFromMember(T, m, ptr) (T *)(((U8 *)(ptr)) - OffsetOf(T, m)) //////////////////////////////// // For-Loop construct macros #define DeferLoop(begin, end) for (int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) #define DeferLoopChecked(begin, end) for (int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) #define EachIndex(it, count) (U64 it = 0; it < (count); it += 1) #define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1) //////////////////////////////// // Glue / Stringify #define Stringify_(S) #S #define Stringify(S) Stringify_(S) #define Glue_(A, B) A##B #define Glue(A, B) Glue_(A, B) #define Swap(T, a, b) \ do { \ T t__ = a; \ a = b; \ b = t__; \ } while (0) //////////////////////////////// // Assert #if defined(_MSC_VER) #define Trap() __debugbreak() #elif defined(__clang__) || defined(__GNUC__) #define Trap() __builtin_trap() #else #define Trap() (*(volatile int *)0 = 0) #endif #define AssertAlways(x) \ do { \ if (!(x)) { Trap(); } \ } while (0) #ifdef _DEBUG #define Assert(x) AssertAlways(x) #else #define Assert(x) (void)(x) #endif #define InvalidPath Assert(!"Invalid Path!") #define NotImplemented Assert(!"Not Implemented!") //////////////////////////////// // Linked list macros // Nil-aware doubly-linked-list operations #define CheckNil(nil, p) ((p) == 0 || (p) == nil) #define SetNil(nil, p) ((p) = nil) // Doubly-linked-list (with nil support) #define DLLInsert_NPZ(nil, f, l, p, n, next, prev) \ (CheckNil(nil, f) ? ((f) = (l) = (n), SetNil(nil, (n)->next), SetNil(nil, (n)->prev)) : CheckNil(nil, p) ? ((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil, (n)->prev)) \ : ((p) == (l)) ? ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) \ : (((!CheckNil(nil, p) && CheckNil(nil, (p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p)))) #define DLLPushBack_NPZ(nil, f, l, n, next, prev) DLLInsert_NPZ(nil, f, l, l, n, next, prev) #define DLLPushFront_NPZ(nil, f, l, n, next, prev) DLLInsert_NPZ(nil, l, f, f, n, prev, next) #define DLLRemove_NPZ(nil, f, l, n, next, prev) \ (((n) == (f) ? (f) = (n)->next : (0)), \ ((n) == (l) ? (l) = (l)->prev : (0)), \ (CheckNil(nil, (n)->prev) ? (0) : ((n)->prev->next = (n)->next)), \ (CheckNil(nil, (n)->next) ? (0) : ((n)->next->prev = (n)->prev))) // Convenience wrappers using 0 as nil #define DLLPushBack(f, l, n) DLLPushBack_NPZ(0, f, l, n, next, prev) #define DLLPushFront(f, l, n) DLLPushFront_NPZ(0, f, l, n, next, prev) #define DLLRemove(f, l, n) DLLRemove_NPZ(0, f, l, n, next, prev) // Singly-linked queue (doubly-headed) #define SLLQueuePush_NZ(nil, f, l, n, next) \ (CheckNil(nil, f) ? ((f) = (l) = (n), SetNil(nil, (n)->next)) : ((l)->next = (n), (l) = (n), SetNil(nil, (n)->next))) #define SLLQueuePush(f, l, n) SLLQueuePush_NZ(0, f, l, n, next) #define SLLQueuePushFront(f, l, n) (((n)->next = (f)), ((f) = (n))) #define SLLQueuePop(f, l) ((f) == (l) ? ((f) = 0, (l) = 0) : ((f) = (f)->next)) // Singly-linked stack #define SLLStackPush(f, n) ((n)->next = (f), (f) = (n)) #define SLLStackPop(f) ((f) = (f)->next)