// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CORE_H #define BASE_CORE_H //////////////////////////////// //~ rjf: Foreign Includes #include #include #include #include #include //////////////////////////////// //~ rjf: Third Party Includes #define STB_SPRINTF_DECORATE(name) raddbg_##name #define STB_SPRINTF_STATIC #include "third_party/stb/stb_sprintf.h" //////////////////////////////// //~ rjf: Codebase Keywords #define internal static #define global static #define local_persist static #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) # pragma section(".rdata$", read) # define read_only __declspec(allocate(".rdata$")) #elif (COMPILER_CLANG && OS_LINUX) # define read_only __attribute__((section(".rodata"))) #else // NOTE(rjf): I don't know of a useful way to do this in GCC land. // __attribute__((section(".rodata"))) looked promising, but it introduces a // strange warning about malformed section attributes, and it doesn't look // like writing to that section reliably produces access violations, strangely // enough. (It does on Clang) # define read_only #endif #if COMPILER_MSVC # define thread_static __declspec(thread) #elif COMPILER_CLANG || COMPILER_GCC # define thread_static __thread #else # error thread_static not defined for this compiler. #endif #if COMPILER_MSVC # define force_inline __forceinline #elif COMPILER_CLANG || COMPILER_GCC # define force_inline __attribute__((always_inline)) #else # error force_inline not defined for this compiler. #endif #if COMPILER_MSVC # define no_inline __declspec(noinline) #elif COMPILER_CLANG || COMPILER_GCC # define no_inline __attribute__((noinline)) #else # error no_inline not defined for this compiler. #endif //////////////////////////////// //~ rjf: Linkage Keyword Macros #if OS_WINDOWS # define shared_function C_LINKAGE __declspec(dllexport) #else # define shared_function C_LINKAGE #endif #if LANG_CPP # define C_LINKAGE_BEGIN extern "C"{ # define C_LINKAGE_END } # define C_LINKAGE extern "C" #else # define C_LINKAGE_BEGIN # define C_LINKAGE_END # define C_LINKAGE #endif //////////////////////////////// //~ rjf: Optimization Settings #if COMPILER_MSVC # define OPTIMIZE_BEGIN _Pragma("optimize(\"\", on)") # define OPTIMIZE_END _Pragma("optimize(\"\", off)") #elif COMPILER_CLANG # define OPTIMIZE_BEGIN _Pragma("clang optimize on") # define OPTIMIZE_END _Pragma("clang optimize off") #elif COMPILER_GCC # define OPTIMIZE_BEGIN _Pragma("GCC push_options") _Pragma("GCC optimize(\"O2\")") # define OPTIMIZE_END _Pragma("GCC pop_options") #else # define OPTIMIZE_BEGIN # define OPTIMIZE_END #endif #if COMPILER_MSVC && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("optimize(\"\", off)") # define NO_OPTIMIZE_END _Pragma("optimize(\"\", on)") #elif COMPILER_CLANG && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("clang optimize off") # define NO_OPTIMIZE_END _Pragma("clang optimize on") #elif COMPILER_GCC && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("GCC push_options") _Pragma("GCC optimize(\"O0\")") # define NO_OPTIMIZE_END _Pragma("GCC pop_options") #else # define NO_OPTIMIZE_BEGIN # define NO_OPTIMIZE_END #endif //////////////////////////////// //~ rjf: Versions #define Version(major, minor, patch) (U64)((((U64)(major) & 0xffff) << 32) | ((((U64)(minor) & 0xffff) << 16)) | ((((U64)(patch) & 0xffff) << 0))) #define MajorFromVersion(version) (((version) & 0xffff00000000ull) >> 32) #define MinorFromVersion(version) (((version) & 0x0000ffff0000ull) >> 16) #define PatchFromVersion(version) (((version) & 0x00000000ffffull) >> 0) //////////////////////////////// //~ rjf: Units #define KB(n) (((U64)(n)) << 10) #define MB(n) (((U64)(n)) << 20) #define GB(n) (((U64)(n)) << 30) #define TB(n) (((U64)(n)) << 40) #define Thousand(n) ((n)*1000) #define Million(n) ((n)*1000000) #define Billion(n) ((n)*1000000000) //////////////////////////////// //~ rjf: 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) //////////////////////////////// //~ rjf: 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)) //////////////////////////////// //~ rjf: Type -> Alignment #if COMPILER_MSVC # define AlignOf(T) __alignof(T) #elif COMPILER_CLANG # define AlignOf(T) __alignof(T) #elif COMPILER_GCC # define AlignOf(T) __alignof__(T) #else # error AlignOf not defined for this compiler. #endif #if COMPILER_MSVC # define AlignType(x) __declspec(align(x)) #elif COMPILER_CLANG || COMPILER_GCC # define AlignType(x) __attribute__((aligned(x))) #else # error AlignType not defined for this compiler. #endif //////////////////////////////// //~ rjf: Member Offsets #define Member(T,m) (((T*)0)->m) #define OffsetOf(T,m) IntFromPtr(&Member(T,m)) #define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off))) #define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m)) //////////////////////////////// //~ rjf: 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) #define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1)) #define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) #define EachInRange(it, range) (U64 it = (range).min; it < (range).max; it += 1) #define EachNode(it, T, first) (T *it = first; it != 0; it = it->next) //////////////////////////////// //~ rjf: Memory Operation 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 MemoryStrlen(ptr) strlen(ptr) #define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d))) #define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d)) #define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c)) #define MemoryCopyStr8(dst, s) MemoryCopy(dst, (s).str, (s).size) #define MemoryZero(s,z) memset((s),0,(z)) #define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s))) #define MemoryZeroArray(a) MemoryZero((a),sizeof(a)) #define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c)) #define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0) #define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a))) #define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a)) #define MemoryIsZeroStruct(ptr) memory_is_zero((ptr), sizeof(*(ptr))) #define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) ) #define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) ) //////////////////////////////// //~ rjf: Asserts #if COMPILER_MSVC # define Trap() __debugbreak() #elif COMPILER_CLANG || COMPILER_GCC # define Trap() __builtin_trap() #else # error Unknown trap intrinsic for this compiler. #endif #define AssertAlways(x) do{if(!(x)) {Trap();}}while(0) #if BUILD_DEBUG # define Assert(x) AssertAlways(x) #else # define Assert(x) (void)(x) #endif #define InvalidPath Assert(!"Invalid Path!") #define NotImplemented Assert(!"Not Implemented!") #define NoOp ((void)0) #define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1] //////////////////////////////// //~ rjf: Linked List Building Macros //- rjf: linked list macro helpers #define CheckNil(nil,p) ((p) == 0 || (p) == nil) #define SetNil(nil,p) ((p) = nil) //- rjf: doubly-linked-lists #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))) //- rjf: singly-linked, doubly-headed lists (queues) #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 SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ ((f)=(l)=(n),SetNil(nil,(n)->next)):\ ((n)->next=(f),(f)=(n))) #define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ (SetNil(nil,f),SetNil(nil,l)):\ ((f)=(f)->next)) //- rjf: singly-linked, singly-headed lists (stacks) #define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) #define SLLStackPop_N(f,next) ((f)=(f)->next) //- rjf: doubly-linked-list helpers #define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev) #define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev) #define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev) #define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev) #define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev) #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) //- rjf: singly-linked, doubly-headed list helpers #define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next) #define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next) //- rjf: singly-linked, singly-headed list helpers #define SLLStackPush(f,n) SLLStackPush_N(f,n,next) #define SLLStackPop(f) SLLStackPop_N(f,next) //////////////////////////////// //~ rjf: Address Sanitizer Markup #if COMPILER_MSVC # if defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # define NO_ASAN __declspec(no_sanitize_address) # else # define NO_ASAN # endif #elif COMPILER_CLANG # if defined(__has_feature) # if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # endif # endif # define NO_ASAN __attribute__((no_sanitize("address"))) #else # define NO_ASAN #endif #if ASAN_ENABLED C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size); C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size); # define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size)) # define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size)) #else # define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) # define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) #endif //////////////////////////////// //~ rjf: Misc. Helper Macros #define Stringify_(S) #S #define Stringify(S) Stringify_(S) #define Glue_(A,B) A##B #define Glue(A,B) Glue_(A,B) #define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) #define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b)) #define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0) //#if ARCH_64BIT //# define IntFromPtr(ptr) ((U64)(ptr)) //#elif ARCH_32BIT //# define IntFromPtr(ptr) ((U32)(ptr)) //#else //# error Missing pointer-to-integer cast for this architecture. //#endif //#define PtrFromInt(i) (void*)(i) #define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)) #define Compose32Bit(a,b) ((((U32)a) << 16) | ((U32)b)) #define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) #define AlignDownPow2(x,b) ((x)&(~((b) - 1))) #define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1)) #define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0) #define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0) #define ExtractBit(word, idx) (((word) >> (idx)) & 1) #define Extract8(word, pos) (((word) >> ((pos)*8)) & max_U8) #define Extract16(word, pos) (((word) >> ((pos)*16)) & max_U16) #define Extract32(word, pos) (((word) >> ((pos)*32)) & max_U32) #if LANG_CPP # define zero_struct {} #else # define zero_struct {0} #endif #if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015 # define this_function_name "unknown" #else # define this_function_name __func__ #endif //////////////////////////////// //~ rjf: 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 S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; typedef void VoidProc(void); typedef union U128 U128; union U128 { U8 u8[16]; U16 u16[8]; U32 u32[4]; U64 u64[2]; }; typedef union U256 U256; union U256 { U8 u8[32]; U16 u16[16]; U32 u32[8]; U64 u64[4]; U128 u128[2]; }; typedef union U512 U512; union U512 { U8 u8[64]; U16 u16[32]; U32 u32[16]; U64 u64[8]; U128 u128[4]; U256 u256[2]; }; //////////////////////////////// //~ rjf: Basic Type Structures typedef struct U16Array U16Array; struct U16Array { U64 count; U16 *v; }; typedef struct U32Array U32Array; struct U32Array { U64 count; U32 *v; }; typedef struct U64Array U64Array; struct U64Array { U64 count; U64 *v; }; typedef struct U128Array U128Array; struct U128Array { U64 count; U128 *v; }; //////////////////////////////// //~ rjf: Basic Types & Spaces /* typedef enum Dimension */ /* { */ /* Dimension_X, */ /* Dimension_Y, */ /* Dimension_Z, */ /* Dimension_W, */ /* } */ /* Dimension; */ /* typedef enum Side */ /* { */ /* Side_Invalid = -1, */ /* Side_Min, */ /* Side_Max, */ /* Side_COUNT, */ /* } */ /* Side; */ /* #define side_flip(s) ((Side)(!(s))) */ /* typedef enum Axis2 */ /* { */ /* Axis2_Invalid = -1, */ /* Axis2_X, */ /* Axis2_Y, */ /* Axis2_COUNT, */ /* } */ /* Axis2; */ /* #define axis2_flip(a) ((Axis2)(!(a))) */ /* typedef enum Corner */ /* { */ /* Corner_Invalid = -1, */ /* Corner_00, */ /* Corner_01, */ /* Corner_10, */ /* Corner_11, */ /* Corner_COUNT */ /* } */ /* Corner; */ typedef enum Dir2 { Dir2_Invalid = -1, Dir2_Left, Dir2_Up, Dir2_Right, Dir2_Down, Dir2_COUNT } Dir2; #define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X) #define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) //////////////////////////////// //~ rjf: Toolchain/Environment Enums typedef enum OperatingSystem { OperatingSystem_Null, OperatingSystem_Windows, OperatingSystem_Linux, OperatingSystem_Mac, OperatingSystem_COUNT, #if OS_WINDOWS OperatingSystem_CURRENT = OperatingSystem_Windows, #elif OS_LINUX OperatingSystem_CURRENT = OperatingSystem_Linux, #elif OS_MAC OperatingSystem_CURRENT = OperatingSystem_Mac, #else OperatingSystem_CURRENT = OperatingSystem_Null, #endif } OperatingSystem; typedef enum ExecutableImageKind { ExecutableImageKind_Null, ExecutableImageKind_CoffPe, ExecutableImageKind_Elf32, ExecutableImageKind_Elf64, ExecutableImageKind_Macho, ExecutableImageKind_COUNT } ExecutableImageKind; typedef enum Arch { Arch_Null, Arch_x64, Arch_x86, Arch_arm64, Arch_arm32, Arch_COUNT, } Arch; #if ARCH_X64 # define Arch_CURRENT Arch_x64 #elif ARCH_X86 # define Arch_CURRENT Arch_x86 #elif ARCH_ARM64 # define Arch_CURRENT Arch_arm64 #elif ARCH_ARM32 # define Arch_CURRENT Arch_arm32 #else # define Arch_CURRENT Arch_Null #endif typedef enum Compiler { Compiler_Null, Compiler_msvc, Compiler_gcc, Compiler_clang, Compiler_COUNT, } Compiler; #if COMPILER_MSVC # define Compiler_CURRENT Compiler_msvc #elif COMPILER_GCC # define Compiler_CURRENT Compiler_gcc #elif COMPILER_CLANG # define Compiler_CURRENT Compiler_clang #else # define Compiler_CURRENT Compiler_Null #endif //////////////////////////////// //~ rjf: Text 2D Coordinates & Ranges typedef struct TxtPt TxtPt; struct TxtPt { S64 line; S64 column; }; typedef struct TxtRng TxtRng; struct TxtRng { TxtPt min; TxtPt max; }; //////////////////////////////// //~ rjf: Globally Unique Ids typedef union Guid Guid; union Guid { struct { U32 data1; U16 data2; U16 data3; U8 data4[8]; }; U8 v[16]; }; StaticAssert(sizeof(Guid) == 16, g_guid_size_check); //////////////////////////////// //~ rjf: Basic Constants global U32 sign32 = 0x80000000; global U32 exponent32 = 0x7F800000; global U32 mantissa32 = 0x007FFFFF; global F32 big_golden32 = 1.61803398875f; global F32 small_golden32 = 0.61803398875f; global F32 pi32 = 3.1415926535897f; global F64 machine_epsilon64 = 4.94065645841247e-324; global U64 max_U64 = 0xffffffffffffffffull; global U32 max_U32 = 0xffffffff; global U16 max_U16 = 0xffff; global U8 max_U8 = 0xff; global S64 max_S64 = (S64)0x7fffffffffffffffll; global S32 max_S32 = (S32)0x7fffffff; global S16 max_S16 = (S16)0x7fff; global S8 max_S8 = (S8)0x7f; global S64 min_S64 = (S64)0x8000000000000000ll; global S32 min_S32 = (S32)0x80000000; global S16 min_S16 = (S16)0x8000; global S8 min_S8 = (S8)0x80; global const U32 bitmask1 = 0x00000001; global const U32 bitmask2 = 0x00000003; global const U32 bitmask3 = 0x00000007; global const U32 bitmask4 = 0x0000000f; global const U32 bitmask5 = 0x0000001f; global const U32 bitmask6 = 0x0000003f; global const U32 bitmask7 = 0x0000007f; global const U32 bitmask8 = 0x000000ff; global const U32 bitmask9 = 0x000001ff; global const U32 bitmask10 = 0x000003ff; global const U32 bitmask11 = 0x000007ff; global const U32 bitmask12 = 0x00000fff; global const U32 bitmask13 = 0x00001fff; global const U32 bitmask14 = 0x00003fff; global const U32 bitmask15 = 0x00007fff; global const U32 bitmask16 = 0x0000ffff; global const U32 bitmask17 = 0x0001ffff; global const U32 bitmask18 = 0x0003ffff; global const U32 bitmask19 = 0x0007ffff; global const U32 bitmask20 = 0x000fffff; global const U32 bitmask21 = 0x001fffff; global const U32 bitmask22 = 0x003fffff; global const U32 bitmask23 = 0x007fffff; global const U32 bitmask24 = 0x00ffffff; global const U32 bitmask25 = 0x01ffffff; global const U32 bitmask26 = 0x03ffffff; global const U32 bitmask27 = 0x07ffffff; global const U32 bitmask28 = 0x0fffffff; global const U32 bitmask29 = 0x1fffffff; global const U32 bitmask30 = 0x3fffffff; global const U32 bitmask31 = 0x7fffffff; global const U32 bitmask32 = 0xffffffff; global const U64 bitmask33 = 0x00000001ffffffffull; global const U64 bitmask34 = 0x00000003ffffffffull; global const U64 bitmask35 = 0x00000007ffffffffull; global const U64 bitmask36 = 0x0000000fffffffffull; global const U64 bitmask37 = 0x0000001fffffffffull; global const U64 bitmask38 = 0x0000003fffffffffull; global const U64 bitmask39 = 0x0000007fffffffffull; global const U64 bitmask40 = 0x000000ffffffffffull; global const U64 bitmask41 = 0x000001ffffffffffull; global const U64 bitmask42 = 0x000003ffffffffffull; global const U64 bitmask43 = 0x000007ffffffffffull; global const U64 bitmask44 = 0x00000fffffffffffull; global const U64 bitmask45 = 0x00001fffffffffffull; global const U64 bitmask46 = 0x00003fffffffffffull; global const U64 bitmask47 = 0x00007fffffffffffull; global const U64 bitmask48 = 0x0000ffffffffffffull; global const U64 bitmask49 = 0x0001ffffffffffffull; global const U64 bitmask50 = 0x0003ffffffffffffull; global const U64 bitmask51 = 0x0007ffffffffffffull; global const U64 bitmask52 = 0x000fffffffffffffull; global const U64 bitmask53 = 0x001fffffffffffffull; global const U64 bitmask54 = 0x003fffffffffffffull; global const U64 bitmask55 = 0x007fffffffffffffull; global const U64 bitmask56 = 0x00ffffffffffffffull; global const U64 bitmask57 = 0x01ffffffffffffffull; global const U64 bitmask58 = 0x03ffffffffffffffull; global const U64 bitmask59 = 0x07ffffffffffffffull; global const U64 bitmask60 = 0x0fffffffffffffffull; global const U64 bitmask61 = 0x1fffffffffffffffull; global const U64 bitmask62 = 0x3fffffffffffffffull; global const U64 bitmask63 = 0x7fffffffffffffffull; global const U64 bitmask64 = 0xffffffffffffffffull; global const U32 bit1 = (1<<0); global const U32 bit2 = (1<<1); global const U32 bit3 = (1<<2); global const U32 bit4 = (1<<3); global const U32 bit5 = (1<<4); global const U32 bit6 = (1<<5); global const U32 bit7 = (1<<6); global const U32 bit8 = (1<<7); global const U32 bit9 = (1<<8); global const U32 bit10 = (1<<9); global const U32 bit11 = (1<<10); global const U32 bit12 = (1<<11); global const U32 bit13 = (1<<12); global const U32 bit14 = (1<<13); global const U32 bit15 = (1<<14); global const U32 bit16 = (1<<15); global const U32 bit17 = (1<<16); global const U32 bit18 = (1<<17); global const U32 bit19 = (1<<18); global const U32 bit20 = (1<<19); global const U32 bit21 = (1<<20); global const U32 bit22 = (1<<21); global const U32 bit23 = (1<<22); global const U32 bit24 = (1<<23); global const U32 bit25 = (1<<24); global const U32 bit26 = (1<<25); global const U32 bit27 = (1<<26); global const U32 bit28 = (1<<27); global const U32 bit29 = (1<<28); global const U32 bit30 = (1<<29); global const U32 bit31 = (1<<30); global const U32 bit32 = (1<<31); global const U64 bit33 = (1ull<<32); global const U64 bit34 = (1ull<<33); global const U64 bit35 = (1ull<<34); global const U64 bit36 = (1ull<<35); global const U64 bit37 = (1ull<<36); global const U64 bit38 = (1ull<<37); global const U64 bit39 = (1ull<<38); global const U64 bit40 = (1ull<<39); global const U64 bit41 = (1ull<<40); global const U64 bit42 = (1ull<<41); global const U64 bit43 = (1ull<<42); global const U64 bit44 = (1ull<<43); global const U64 bit45 = (1ull<<44); global const U64 bit46 = (1ull<<45); global const U64 bit47 = (1ull<<46); global const U64 bit48 = (1ull<<47); global const U64 bit49 = (1ull<<48); global const U64 bit50 = (1ull<<49); global const U64 bit51 = (1ull<<50); global const U64 bit52 = (1ull<<51); global const U64 bit53 = (1ull<<52); global const U64 bit54 = (1ull<<53); global const U64 bit55 = (1ull<<54); global const U64 bit56 = (1ull<<55); global const U64 bit57 = (1ull<<56); global const U64 bit58 = (1ull<<57); global const U64 bit59 = (1ull<<58); global const U64 bit60 = (1ull<<59); global const U64 bit61 = (1ull<<60); global const U64 bit62 = (1ull<<61); global const U64 bit63 = (1ull<<62); global const U64 bit64 = (1ull<<63); //////////////////////////////// //~ rjf: Time Types typedef enum WeekDay { WeekDay_Sun, WeekDay_Mon, WeekDay_Tue, WeekDay_Wed, WeekDay_Thu, WeekDay_Fri, WeekDay_Sat, WeekDay_COUNT, } WeekDay; typedef enum Month { Month_Jan, Month_Feb, Month_Mar, Month_Apr, Month_May, Month_Jun, Month_Jul, Month_Aug, Month_Sep, Month_Oct, Month_Nov, Month_Dec, Month_COUNT, } Month; typedef struct DateTime DateTime; struct DateTime { U16 micro_sec; // [0,999] U16 msec; // [0,999] U16 sec; // [0,60] U16 min; // [0,59] U16 hour; // [0,24] U16 day; // [0,30] union { WeekDay week_day; U32 wday; }; union { Month month; U32 mon; }; U32 year; // 1 = 1 CE, 0 = 1 BC }; typedef U64 DenseTime; //////////////////////////////// //~ rjf: File Types typedef U32 FilePropertyFlags; enum { FilePropertyFlag_IsFolder = (1 << 0), }; typedef struct FileProperties FileProperties; struct FileProperties { U64 size; DenseTime modified; DenseTime created; FilePropertyFlags flags; }; //////////////////////////////// //~ rjf: Safe Casts internal U16 safe_cast_u16(U32 x); internal U32 safe_cast_u32(U64 x); internal S32 safe_cast_s32(S64 x); //////////////////////////////// //~ rjf: Large Base Type Functions internal U128 u128_zero(void); internal U128 u128_make(U64 v0, U64 v1); internal B32 u128_match(U128 a, U128 b); //////////////////////////////// //~ rjf: Bit Patterns internal U32 u32_from_u64_saturate(U64 x); internal U64 u64_up_to_pow2(U64 x); internal S32 extend_sign32(U32 x, U32 size); internal S64 extend_sign64(U64 x, U64 size); internal F32 inf32(void); internal F32 neg_inf32(void); internal U16 bswap_u16(U16 x); internal U32 bswap_u32(U32 x); internal U64 bswap_u64(U64 x); #if ARCH_LITTLE_ENDIAN # define from_be_u16(x) bswap_u16(x) # define from_be_u32(x) bswap_u32(x) # define from_be_u64(x) bswap_u64(x) #else # define from_be_u16(x) (x) # define from_be_u32(x) (x) # define from_be_u64(x) (x) #endif internal U64 count_bits_set32(U32 val); internal U64 count_bits_set64(U64 val); internal U64 ctz32(U32 val); internal U64 ctz64(U64 val); internal U64 clz32(U32 val); internal U64 clz64(U64 val); //////////////////////////////// //~ rjf: Enum -> Sign /* internal S32 sign_from_side_S32(Side side); */ /* internal F32 sign_from_side_F32(Side side); */ //////////////////////////////// //~ rjf: Memory Functions internal B32 memory_is_zero(void *ptr, U64 size); //////////////////////////////// //~ rjf: Text 2D Coordinate/Range Functions internal TxtPt txt_pt(S64 line, S64 column); internal B32 txt_pt_match(TxtPt a, TxtPt b); internal B32 txt_pt_less_than(TxtPt a, TxtPt b); internal TxtPt txt_pt_min(TxtPt a, TxtPt b); internal TxtPt txt_pt_max(TxtPt a, TxtPt b); internal TxtRng txt_rng(TxtPt min, TxtPt max); internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b); internal TxtRng txt_rng_union(TxtRng a, TxtRng b); internal B32 txt_rng_contains(TxtRng r, TxtPt pt); //////////////////////////////// //~ rjf: Toolchain/Environment Enum Functions internal U64 bit_size_from_arch(Arch arch); internal U64 byte_size_from_arch(Arch arch); internal U64 max_instruction_size_from_arch(Arch arch); //////////////////////////////// //~ rjf: Time Functions internal DenseTime dense_time_from_date_time(DateTime date_time); internal DateTime date_time_from_dense_time(DenseTime time); internal DateTime date_time_from_micro_seconds(U64 time); internal DateTime date_time_from_unix_time(U64 unix_time); //////////////////////////////// //~ rjf: Non-Fancy Ring Buffer Reads/Writes internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size); internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size); #define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) #define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) //////////////////////////////// //~ rjf: Sorts #define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function)) //////////////////////////////// internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value); //////////////////////////////// internal U64 index_of_zero_u32(U32 *ptr, U64 count); internal U64 index_of_zero_u64(U64 *ptr, U64 count); #endif // BASE_CORE_H