183 lines
6.0 KiB
C
183 lines
6.0 KiB
C
#pragma once
|
|
// base_core.h - Fundamental types, macros, and linked list helpers
|
|
// Inspired by raddebugger's base_core.h
|
|
|
|
#include <math.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
////////////////////////////////
|
|
// 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)
|