/* ** ** TODO: instructions will go here ** */ #if !defined(MR4TH_BASE_H) #define MR4TH_BASE_H 1 //////////////////////////////////////////////// //////////////////////////////////////////////// ////////////////// MACROS ////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////// // Build Mode Defaults & Checks #if !defined(MR4TH_DISABLE_UNITY_BUILD) # define MR4TH_DISABLE_UNITY_BUILD 0 #endif #if !defined(MR4TH_CORE_MODE) # define MR4TH_CORE_MODE 0 #endif #if !defined(MR4TH_PLUGIN_MODE) # define MR4TH_PLUGIN_MODE 0 #endif #if !defined(MR4TH_STANDALONE_MODE) # define MR4TH_STANDALONE_MODE 0 #endif #if !defined(MR4TH_PROFILING_PROVIDER) # define MR4TH_PROFILING_PROVIDER 0 #endif #if !MR4TH_CORE_MODE && !MR4TH_PLUGIN_MODE && !MR4TH_STANDALONE_MODE # undef MR4TH_STANDALONE_MODE # define MR4TH_STANDALONE_MODE 1 #endif #if (MR4TH_CORE_MODE && MR4TH_PLUGIN_MODE) # error conflicing mr4th build mode #endif #if (MR4TH_CORE_MODE && MR4TH_STANDALONE_MODE) # error conflicing mr4th build mode #endif #if (MR4TH_PLUGIN_MODE && MR4TH_STANDALONE_MODE) # error conflicing mr4th build mode #endif //////////////////////////////// // Context Cracking // development settings #if !defined(MR4TH_ASSERTS) # define MR4TH_ASSERTS 0 #endif #if !defined(MR4TH_SANITIZER) # define MR4TH_SANITIZER 0 #endif #if !defined(MR4TH_PROFILING_MANUAL) # define MR4TH_PROFILING_MANUAL 0 #endif #if !defined(MR4TH_PROFILING_AUTO) # define MR4TH_PROFILING_AUTO 0 #endif #if defined(MR4TH_PROFILING_USER) # error the user should not set MR4TH_PROFILING_USER, instead set MR4TH_PROFILING_MANUAL or MR4TH_PROFILING_AUTO #endif #if MR4TH_PROFILING_MANUAL || MR4TH_PROFILING_AUTO # define MR4TH_PROFILING_USER 1 #else # define MR4TH_PROFILING_USER 0 #endif // untangle compiler, os, & architecture #if defined(__clang__) # define COMPILER_CLANG 1 # if defined(_WIN32) # define OS_WINDOWS 1 # elif defined(__gnu_linux__) # define OS_LINUX 1 # elif defined(__APPLE__) && defined(__MACH__) # define OS_MAC 1 # else # error missing OS detection # endif # if defined(__amd64__) # define ARCH_X64 1 // TODO(allen): verify this works on clang # elif defined(__i386__) # define ARCH_X86 1 // TODO(allen): verify this works on clang # elif defined(__arm__) # define ARCH_ARM 1 // TODO(allen): verify this works on clang # elif defined(__aarch64__) # define ARCH_ARM64 1 # else # error missing ARCH detection # endif #elif defined(_MSC_VER) # define COMPILER_CL 1 # if defined(_WIN32) # define OS_WINDOWS 1 # else # error missing OS detection # endif # if defined(_M_AMD64) # define ARCH_X64 1 # elif defined(_M_I86) # define ARCH_X86 1 # elif defined(_M_ARM) # define ARCH_ARM 1 // TODO(allen): ARM64? # else # error missing ARCH detection # endif #elif defined(__GNUC__) # define COMPILER_GCC 1 # if defined(_WIN32) # define OS_WINDOWS 1 # elif defined(__gnu_linux__) # define OS_LINUX 1 # elif defined(__APPLE__) && defined(__MACH__) # define OS_MAC 1 # else # error missing OS detection # endif # if defined(__amd64__) # define ARCH_X64 1 # elif defined(__i386__) # define ARCH_X86 1 # elif defined(__arm__) # define ARCH_ARM 1 # elif defined(__aarch64__) # define ARCH_ARM64 1 # else # error missing ARCH detection # endif #else # error no context cracking for this compiler #endif #if !defined(COMPILER_CL) # define COMPILER_CL 0 #endif #if !defined(COMPILER_CLANG) # define COMPILER_CLANG 0 #endif #if !defined(COMPILER_GCC) # define COMPILER_GCC 0 #endif #if !defined(OS_WINDOWS) # define OS_WINDOWS 0 #endif #if !defined(OS_LINUX) # define OS_LINUX 0 #endif #if !defined(OS_MAC) # define OS_MAC 0 #endif #if !defined(ARCH_X64) # define ARCH_X64 0 #endif #if !defined(ARCH_X86) # define ARCH_X86 0 #endif #if !defined(ARCH_ARM) # define ARCH_ARM 0 #endif #if !defined(ARCH_ARM64) # define ARCH_ARM64 0 #endif // language #if defined(__cplusplus) # define LANG_CXX 1 #else # define LANG_C 1 #endif #if !defined(LANG_CXX) # define LANG_CXX 0 #endif #if !defined(LANG_C) # define LANG_C 0 #endif // language version: C #if LANG_C # if !defined(__STDC_VERSION__) # define LANGVER_C90 1 # elif (__STDC_VERSION__ == 199901) # define LANGVER_C99 1 # elif (__STDC_VERSION__ == 201112) # define LANGVER_C11 1 # elif (__STDC_VERSION__ == 201710) # define LANGVER_C17 1 # elif (__STDC_VERSION__ == 202000) # define LANGVER_C23 1 # else # error unrecorgnized C version # endif #endif #if !defined(LANGVER_C90) # define LANGVER_C90 0 #endif #if !defined(LANGVER_C99) # define LANGVER_C99 0 #endif #if !defined(LANGVER_C11) # define LANGVER_C11 0 #endif #if !defined(LANGVER_C17) # define LANGVER_C17 0 #endif #if !defined(LANGVER_C23) # define LANGVER_C23 0 #endif // language version: C++ #if LANG_CXX # if (__cplusplus == 199711) # define LANGVER_CXX98 1 # elif (__cplusplus == 201103) # define LANGVER_CXX11 1 # elif (__cplusplus == 201402) # define LANGVER_CXX14 1 # elif (__cplusplus == 201703) # define LANGVER_CXX17 1 # elif (__cplusplus == 202002) # define LANGVER_CXX20 1 # elif (__cplusplus == 202302) # define LANGVER_CXX23 1 # else # error unrecorgnized C++ version # endif #endif #if !defined(LANGVER_CXX98) # define LANGVER_CXX98 0 #endif #if !defined(LANGVER_CXX11) # define LANGVER_CXX11 0 #endif #if !defined(LANGVER_CXX14) # define LANGVER_CXX14 0 #endif #if !defined(LANGVER_CXX17) # define LANGVER_CXX17 0 #endif #if !defined(LANGVER_CXX20) # define LANGVER_CXX20 0 #endif #if !defined(LANGVER_CXX23) # define LANGVER_CXX23 0 #endif // determine intrinsics mode #if OS_WINDOWS # if COMPILER_CL || COMPILER_CLANG # define INTRINSICS_MICROSOFT 1 # endif #endif #if OS_LINUX # if COMPILER_CLANG || COMPILER_GCC # define INTRINSICS_BUILT_IN 1 # endif #endif #if !defined(INTRINSICS_MICROSOFT) # define INTRINSICS_MICROSOFT 0 #endif #if !defined(INTRINSICS_BUILT_IN) # define INTRINSICS_BUILT_IN 0 #endif // setup pointer size macro #if ARCH_X64 || ARCH_ARM64 # define ARCH_ADDRSIZE 64 #else # define ARCH_ADDRSIZE 32 #endif #define ARCH_LITTLE_ENDIAN 1 #define ARCH_BIG_ENDIAN 0 // TODO(allen): target image format //////////////////////////////// // Macros: Symbol Markers // linkage, storage, & other "attribute" like things #define MR4TH_SYMBOL_STATIC static #if LANG_CXX # define MR4TH_SYMBOL_LINK extern "C" #else # define MR4TH_SYMBOL_LINK extern #endif #if OS_WINDOWS # define MR4TH_SYMBOL_EXPORT __declspec(dllexport) #elif OS_LINUX || OS_MAC # define MR4TH_SYMBOL_EXPORT __attribute__((visibility("default"))) #else # error MR4TH_SYMBOL_EXPORT not defined for this OS #endif #if OS_WINDOWS # define MR4TH_SYM_IMPORT __declspec(dllimport) #elif OS_LINUX || OS_MAC # define MR4TH_SYM_IMPORT #else # error MR4TH_SYMBOL_IMPORT not defined for this OS #endif #if COMPILER_CL # define MR4TH_THREADVAR __declspec(thread) #elif COMPILER_CLANG || COMPILER_GCC # define MR4TH_THREADVAR __thread #else # error MR4TH_THREADVAR not defined for this compiler #endif #if COMPILER_CLANG || COMPILER_GCC # if OS_MAC # define MR4TH_SEC_R(N) __attribute__((__section__("__TEXT,"N))) # define MR4TH_SEC_RW(N) __attribute__((__section__("__READ,"N))) # else # define MR4TH_SEC_R(N) __attribute__((__section__(N))) # define MR4TH_SEC_RW(N) __attribute__((__section__(N))) # endif #elif COMPILER_CL # define MR4TH_SEC_R(N) __declspec(allocate(N)) # define MR4TH_SEC_RW(N) __declspec(allocate(N)) #else # error MR4TH_SEC_R/MR4TH_SEC_RW not defined for this compiler/OS #endif #if COMPILER_CLANG || COMPILER_GCC #if OS_WINDOWS # define MR4TH_READ_ONLY MR4TH_SEC_R(".rdata") const #else # define MR4TH_READ_ONLY MR4TH_SEC_R(".rodata") const #endif #elif COMPILER_CL # pragma section(".m4rdata",read) # define MR4TH_READ_ONLY MR4TH_SEC_R(".m4rdata") const #else # define MR4TH_READ_ONLY # error MR4TH_READ_ONLY not defined for this compiler #endif // symbol kinds #if MR4TH_DISABLE_UNITY_BUILD # define MR4TH_SYMBOL MR4TH_SYMBOL_LINK #else # define MR4TH_SYMBOL MR4TH_SYMBOL_STATIC #endif #if MR4TH_CORE_MODE # define MR4TH_SYMBOL_MUST_SHARE MR4TH_SYMBOL_EXPORT #elif MR4TH_PLUGIN_MODE # define MR4TH_SYMBOL_MUST_SHARE MR4TH_SYMBOL_IMPORT #else # define MR4TH_SYMBOL_MUST_SHARE MR4TH_SYMBOL #endif // align-as #if COMPILER_CL # define MR4TH_ALIGN_AS_LIT(n) __declspec(align(n)) #elif COMPILER_CLANG || COMPILER_GCC # define MR4TH_ALIGN_AS_LIT(n) __attribute__(( __aligned__(n) )) #else # error MR4TH_ALIGN_AS_LIT not defined for this compiler #endif // do-not-eliminate #if OS_WINDOWS # define MR4TH_DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N)) # define MR4TH_DO_NOT_ELIMINATE__S1(N) MR4TH_DO_NOT_ELIMINATE__S0(N) # define MR4TH_DO_NOT_ELIMINATE(N) MR4TH_DO_NOT_ELIMINATE__S1(N) #else # define MR4TH_DO_NOT_ELIMINATE(N) #endif // before-main abstraction #if OS_WINDOWS # pragma section(".CRT$XCU", read) # if LANG_CXX # define MR4TH_BEFORE_MAIN_(n) \ static void n(void); \ __declspec(allocate(".CRT$XCU")) \ __pragma(comment(linker,"/include:" #n "__")) \ extern "C" void (*n##__)(void); \ void (*n##__)(void) = n; \ static void n(void) # else # define MR4TH_BEFORE_MAIN_(n) \ static void n(void); \ __declspec(allocate(".CRT$XCU")) \ __pragma(comment(linker,"/include:" #n "__")) \ void (*n##__)(void) = n; \ static void n(void) # endif # define MR4TH_BEFORE_MAIN(n) MR4TH_BEFORE_MAIN_(n) #elif OS_LINUX # define MR4TH_BEFORE_MAIN(n) \ __attribute__((constructor)) static void n(void) #else # error MR4TH_BEFORE_MAIN missing for this OS #endif // sanitizer #if COMPILER_CLANG && MR4TH_SANITIZER # include #endif #if MR4TH_SANITIZER # define AsanPoison(p,z) __asan_poison_memory_region((p),(z)) # define AsanUnpoison(p,z) __asan_unpoison_memory_region((p),(z)) #else # define AsanPoison(p,z) # define AsanUnpoison(p,z) #endif //////////////////////////////// // Macros: Common Expressions // macro writing utilities #define Stmnt(S) do{ S }while(0) #define Stringify_(S) #S #define Stringify(S) Stringify_(S) #define Glue_(A,B) A##B #define Glue(A,B) Glue_(A,B) // assert #if !defined(AssertBreak) # define AssertBreak() (*(volatile int*)0 = 0) #endif #if MR4TH_ASSERTS # define Assert(c) Stmnt( if (!(c)){ AssertBreak(); } ) #else # define Assert(c) #endif #define StaticAssert(c,l) typedef U8 Glue(l,__LINE__) [(c)?1:-1] // memory operations #define MemoryZero(p,z) memory_zero((p), (z)) #define MemoryZeroStruct(p) MemoryZero((p), sizeof(*(p))) #define MemoryZeroArray(p) MemoryZero((p), sizeof(p)) #define MemoryZeroRange(f,o) MemoryZero((f), (U8*)(o) - (U8*)(f)) #define MemoryMatch(a,b,z) (memory_match((a),(b),(z))) #define MemoryCopy(d,s,z) memory_move((d), (s), (z)) #define MemoryCopyStruct(d,s) MemoryCopy((d),(s),Min(sizeof(*(d)),sizeof(*(s)))) #define MemoryCopyArray(d,s) MemoryCopy((d),(s),Min(sizeof(s),sizeof(d))) // misc expressions #define ArrayCount(a) (sizeof(a)/sizeof(*(a))) #define IntFromPtr(p) (UAddr)(p) #define PtrFromInt(n) (void*)((UAddr)(n)) #define PtrDif(a,b) ((U8*)(a) - (U8*)(b)) #define Member(T,m) (((T*)0)->m) #define AddrOfMember(T,m) (void*)(&Member(T,m)) #define OffsetOfMember(T,m) IntFromPtr(&Member(T,m)) #define OffsetOfMemberV(s,m) PtrDif(&s->m, s) #define MemberAddr(T,m) AddrOfMember(T,m) #define MemberOff(T,m) OffsetOfMember(T,m) #define Min(a,b) (((a)<(b))?(a):(b)) #define Max(a,b) (((a)>(b))?(a):(b)) #define Clamp(a,x,b) (((x)<(a))?(a):((b)<(x))?(b):(x)) #define ClampTop(a,b) Min(a,b) #define ClampBot(a,b) Max(a,b) #define Swap(T,a,b) Stmnt( T t_ = (a); (a) = (b); (b) = t_; ) #define SignedIntFromCompare(a,b) (S32)( ((b)<(a)) - ((a)<(b)) ) #define AlignUpPow2(x,p) (((x) + (p) - 1)&~((p) - 1)) #define AlignDownPow2(x,p) ((x)&~((p) - 1)) #define IsPow2OrZero(x) (((x)&((x)-1)) == 0) #define CeilIntDiv(n,d) (((n) + (d) - 1)/(d)) #define KB(x) ((U64)(x) << 10llu) #define MB(x) ((U64)(x) << 20llu) #define GB(x) ((U64)(x) << 30llu) #define TB(x) ((U64)(x) << 40llu) #define Thousand(x) ((x)*1000llu) #define Million(x) ((x)*1000000llu) #define Billion(x) ((x)*1000000000llu) #define Trillion(x) ((x)*1000000000000llu) #define AsciiID4(a,b,c,d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a)) #if LANG_CXX # define CLiteral(T) T #else # define CLiteral(T) (T) #endif //////////////////////////////// // Macros: Linked Lists #define DLLPushBack_NPZ(f,l,n,next,prev,nil)\ (((f) == (nil))?\ ((f)=(l)=(n),(n)->next=(n)->prev=(nil)):\ ((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=(nil))) #define DLLPushBack(f,l,n) DLLPushBack_NPZ(f,l,n,next,prev,0) #define DLLPushFront(f,l,n) DLLPushBack_NPZ(l,f,n,prev,next,0) #define DLLInsert_NPZ(f,l,p,n,next,prev,nil) \ (((p) != (l))?\ ((n)->next = (p)->next,\ (n)->prev = (p),\ (p)->next->prev = (n),\ (p)->next = (n))\ :((n)->next = (nil),\ (n)->prev = (l),\ (l)->next = (n),\ (l) = (n))) #define DLLInsert(f,l,p,n) DLLInsert_NPZ(f,l,p,n,next,prev,0) #define DLLRemove_NPZ(f,l,n,next,prev,nil)\ ((f)==(n)?\ ((f)==(l)?\ ((f)=(l)=(nil)):\ ((f)=(f)->next,(f)->prev=(nil))):\ (l)==(n)?\ ((l)=(l)->prev,(l)->next=(nil)):\ ((n)->next->prev=(n)->prev,\ (n)->prev->next=(n)->next)) #define DLLRemove(f,l,n) DLLRemove_NPZ(f,l,n,next,prev,0) #define SLLQueuePush_NZ(f,l,n,next,nil) (((f)==(nil)?\ (f)=(l)=(n):\ ((l)->next=(n),(l)=(n))),\ (n)->next=(nil)) #define SLLQueuePush(f,l,n) SLLQueuePush_NZ(f,l,n,next,0) #define SLLQueuePushFront_NZ(f,l,n,next,nil) ((f)==(nil)?\ ((f)=(l)=(n),(n)->next=(nil)):\ ((n)->next=(f),(f)=(n))) #define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(f,l,n,next,0) #define SLLQueuePop_NZ(f,l,next,nil) ((f)==(l)?\ (f)=(l)=(nil):\ ((f)=(f)->next)) #define SLLQueuePop(f,l) SLLQueuePop_NZ(f,l,next,0) #define SLLStackPush_N(f,n,next) ((n)->next=(f),(f)=(n)) #define SLLStackPush(f,n) SLLStackPush_N(f,n,next) #define SLLStackPop_NZ(f,next,nil) ((f)==(nil)?(nil):\ ((f)=(f)->next)) #define SLLStackPop(f) SLLStackPop_NZ(f,next,0) //////////////////////////////////////////////// //////////////////////////////////////////////// ////////////////// TYPES /////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////// // Types: Basic #include #include #include typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; #if ARCH_ADDRSIZE == 32 typedef U32 UAddr; typedef S32 SAddr; #elif ARCH_ADDRSIZE == 64 typedef U64 UAddr; typedef S64 SAddr; #else # error UAddr and SAddr not defined for this architecture #endif typedef void VoidFunc(void); //////////////////////////////// // Types: Symbolic Constants typedef enum Axis{ Axis_X = 0, Axis_Y = 1, Axis_Z = 2, Axis_W = 3 } Axis; typedef enum Side{ Side_Min = 0, Side_Max = 1 } Side; typedef enum OperatingSystem{ OperatingSystem_Null = 0, OperatingSystem_Windows = 1, OperatingSystem_Linux = 2, OperatingSystem_Mac = 3, OperatingSystem_COUNT } OperatingSystem; typedef enum Architecture{ Architecture_Null = 0, Architecture_X64 = 1, Architecture_X86 = 2, Architecture_Arm = 3, Architecture_Arm64 = 4, Architecture_COUNT } Architecture; typedef enum Month{ Month_Jan = 1, Month_Feb = 2, Month_Mar = 3, Month_Apr = 4, Month_May = 5, Month_Jun = 6, Month_Jul = 7, Month_Aug = 8, Month_Sep = 9, Month_Oct = 10, Month_Nov = 11, Month_Dec = 12, } Month; typedef enum DayOfWeek{ DayOfWeek_Sunday = 0, DayOfWeek_Monday = 1, DayOfWeek_Tuesday = 2, DayOfWeek_Wednesday = 3, DayOfWeek_Thursday = 4, DayOfWeek_Friday = 5, DayOfWeek_Saturday = 6 } DayOfWeek; typedef U32 DataAccessFlags; enum{ DataAccessFlag_Read = (1 << 0), DataAccessFlag_Write = (1 << 1), DataAccessFlag_Execute = (1 << 2), }; //////////////////////////////// // Types: Compound Types typedef struct V2F32{ F32 x; F32 y; } V2F32; typedef struct V3F32{ F32 x; F32 y; F32 z; } V3F32; typedef struct V4F32{ F32 x; F32 y; F32 z; F32 w; } V4F32; typedef struct RangeF32{ F32 min; F32 max; } RangeF32; typedef struct RectF32{ union{ struct{ F32 x0; F32 y0; F32 x1; F32 y1; }; struct{ V2F32 p0; V2F32 p1; }; }; } RectF32; //////////////////////////////// // Types: Time typedef U64 DenseTime; typedef struct DateTime{ U16 msec; // [0,999] U8 sec; // [0,60] U8 min; // [0,59] U8 hour; // [0,23] U8 day; // [1,31] U8 mon; // [1,12] S16 year; // 1 = 1 CE; 2020 = 2020 CE; 0 = 1 BCE; -100 = 101 BCE; etc. } DateTime; //////////////////////////////// // Types: File Properties typedef U32 FilePropertyFlags; enum{ FilePropertyFlag_IsFolder = (1 << 0), }; typedef struct FileProperties{ U64 size; FilePropertyFlags flags; DenseTime create_time; DenseTime modify_time; DataAccessFlags access; } FileProperties; //////////////////////////////// // Types: Arena typedef struct Arena Arena; typedef struct ArenaTemp{ Arena *arena; U64 pos; } ArenaTemp; //////////////////////////////// // Types: String typedef struct String8{ U8 *str; U64 size; } String8; typedef struct String8Node{ struct String8Node *next; String8 string; } String8Node; typedef struct String8List{ String8Node *first; String8Node *last; U64 node_count; U64 total_size; } String8List; typedef struct StringJoin{ String8 pre; String8 mid; String8 post; } StringJoin; typedef U32 StringMatchFlags; enum{ StringMatchFlag_NoCase = (1 << 0), StringMatchFlag_PrefixMatch = (1 << 1), }; typedef struct String16{ U16 *str; U64 size; } String16; typedef struct String32{ U32 *str; U64 size; } String32; #define str8_expand(s) (int)((s).size), ((s).str) typedef struct StringDecode{ U32 codepoint; U32 size; } StringDecode; //////////////////////////////// // Types: Stream typedef struct STREAM STREAM; typedef void STREAM_Handle; //////////////////////////////// // Types: Buffer typedef struct BUFFER{ void *base; U64 size; U64 commit_pos; } BUFFER; #define BUFFER_TYPED(T, name) union{ BUFFER buffer; T *ptr; } name //////////////////////////////// // Types: Hash Table typedef struct HASH_Node{ struct HASH_Node *next; U64 hash; U64 val; } HASH_Node; //////////////////////////////// // Types: Log typedef void LOG_LogToProc(void *uptr, String8 str); typedef struct LOG_Node{ struct LOG_Node *next; U64 pos; String8List log; LOG_LogToProc *logto; void *uptr; } LOG_Node; typedef struct LOG_ThreadVars{ Arena *arena; LOG_Node *stack; } LOG_ThreadVars; //////////////////////////////// // Types: Error typedef struct ER_Node{ struct ER_Node *next; U64 pos; String8 error; } ER_Node; typedef struct ER_ThreadVars{ Arena *arena; ER_Node *stack; U64 over_stack; } ER_ThreadVars; //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////// CONSTANTS ///////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// #define min_S8 ((S8) 0x80) #define min_S16 ((S16)0x8000) #define min_S32 ((S32)0x80000000) #define min_S64 ((S64)0x8000000000000000llu) #define max_S8 ((S8) 0x7f) #define max_S16 ((S16)0x7fff) #define max_S32 ((S32)0x7fffffff) #define max_S64 ((S64)0x7fffffffffffffffllu) #define max_U8 0xff #define max_U16 0xffff #define max_U32 0xffffffff #define max_U64 0xffffffffffffffffllu #define machine_epsilon_F32 1.1920929e-7f #define pi_F32 3.14159265359f #define tau_F32 6.28318530718f #define e_F32 2.71828182846f #define gold_big_F32 1.61803398875f #define gold_small_F32 0.61803398875f #define machine_epsilon_F64 2.220446e-16 #define pi_F64 3.14159265359 #define tau_F64 6.28318530718 #define e_F64 2.71828182846 #define gold_big_F64 1.61803398875 #define gold_small_F64 0.61803398875 #define inf_F32_as_U32 0x7f800000 #define neg_inf_F32_as_U32 0xff800000 #define inf_F64_as_U64 0x7ff0000000000000 #define neg_inf_F64_as_U64 0xfff0000000000000 #define set_inf_F32(x) (*(U32*)(&(x)) = inf_F32_as_U32) #define set_neg_inf_F32(x) (*(U32*)(&(x)) = neg_inf_F32_as_U32) #define set_inf_F64(x) (*(U64*)(&(x)) = inf_F64_as_U64) #define set_neg_inf_F64(x) (*(U64*)(&(x)) = neg_inf_F64_as_U64) //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////// INTRINSICS //////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// #if INTRINSICS_MICROSOFT # include # define intrinsic_rdtsc() __rdtsc() # define intrinsic_maxbit(o,x) _BitScanReverse64((o),(x)) #elif INTRINSICS_BUILT_IN # define intrinsic_rdtsc() __rdtsc() # define intrinsic_maxbit(o,x) (*(o) = __builtin_clzll(x),(x)!=0) #endif //////////////////////////////////////////////// //////////////////////////////////////////////// /////////////// DECLARATIONS /////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////// // Functions: Numerical/Math // float infinity/NaN MR4TH_SYMBOL B32 is_inf_or_nan_F32(F32 x); MR4TH_SYMBOL B32 is_inf_or_nan_F64(F64 x); // float signs, rounding, and modulus MR4TH_SYMBOL F32 abs_F32(F32 x); MR4TH_SYMBOL F32 sign_F32(F32 x); MR4TH_SYMBOL F32 trunc_F32(F32 x); MR4TH_SYMBOL F32 floor_F32(F32 x); MR4TH_SYMBOL F32 ceil_F32(F32 x); MR4TH_SYMBOL F32 nearest_F32(F32 x); MR4TH_SYMBOL F32 mod_F32(F32 x, F32 m); MR4TH_SYMBOL F32 frac_F32(F32 x); MR4TH_SYMBOL F64 abs_F64(F64 x); MR4TH_SYMBOL F64 sign_F64(F64 x); MR4TH_SYMBOL F64 trunc_F64(F64 x); MR4TH_SYMBOL F64 floor_F64(F64 x); MR4TH_SYMBOL F64 ceil_F64(F64 x); MR4TH_SYMBOL F64 nearest_F64(F64 x); MR4TH_SYMBOL F64 mod_F64(F64 x, F64 m); MR4TH_SYMBOL F64 frac_F64(F64 x); // transcendental functions MR4TH_SYMBOL F32 sin_F32(F32 x); MR4TH_SYMBOL F32 cos_F32(F32 x); MR4TH_SYMBOL F32 tan_F32(F32 x); MR4TH_SYMBOL F32 atan_F32(F32 x); MR4TH_SYMBOL F32 atan2_F32(F32 x, F32 y); MR4TH_SYMBOL F32 sqrt_F32(F32 x); MR4TH_SYMBOL F32 inv_sqrt_F32(F32 x); MR4TH_SYMBOL F32 ln_F32(F32 x); MR4TH_SYMBOL F32 pow_F32(F32 base, F32 x); MR4TH_SYMBOL F64 sin_F64(F64 x); MR4TH_SYMBOL F64 cos_F64(F64 x); MR4TH_SYMBOL F64 tan_F64(F64 x); MR4TH_SYMBOL F64 atan_F64(F64 x); MR4TH_SYMBOL F64 atan2_F64(F64 x, F64 y); MR4TH_SYMBOL F64 sqrt_F64(F64 x); MR4TH_SYMBOL F64 inv_sqrt_F64(F64 x); MR4TH_SYMBOL F64 ln_F64(F64 x); MR4TH_SYMBOL F64 pow_F64(F64 base, F64 x); // linear interpolation MR4TH_SYMBOL F32 lerp(F32 a, F32 t, F32 b); MR4TH_SYMBOL F32 unlerp(F32 a, F32 x, F32 b); // integer rounding & truncating MR4TH_SYMBOL U32 next_pow2_U32(U32 x); MR4TH_SYMBOL S32 sign_extend_S32(S32 x, U32 bitidx); MR4TH_SYMBOL U64 next_pow2_U64(U32 x); MR4TH_SYMBOL S64 sign_extend_S64(S64 x, U32 bitidx); //////////////////////////////// // Functions: Compound Types // vector macros #define v2(x,y) CLiteral(V2F32){(x),(y)} #define v3(x,y,z) CLiteral(V3F32){(x),(y),(z)} #define v4(x,y,z,w) CLiteral(V4F32){(x),(y),(z),(w)} #define v2_expanded(v) ((v).x), ((v).y) #define v3_expanded(v) ((v).x), ((v).y), ((v).z) #define v4_expanded(v) ((v).x), ((v).y), ((v).z), ((v).w) #define rect_expanded(r) ((r).x0), ((r).y0), ((r).x1), ((r).y1) #define v2_exop_scalar(sc, op, v) ((sc) op ((v).x)), ((sc) op ((v).y)) #define v3_exop_scalar(sc, op, v) ((sc) op ((v).x)), ((sc) op ((v).y)), ((sc) op ((v).z)) #define v4_exop_scalar(sc, op, v) ((sc) op ((v).x)), ((sc) op ((v).y)), ((sc) op ((v).z)), ((sc) op ((v).w)) #define v2_exop(v1, op, v2) ((v1).x op ((v2).x)), ((v1).y op ((v2).y)) #define v3_exop(v1, op, v2) ((v1).x op ((v2).x)), ((v1).y op ((v2).y)), ((v1).z op ((v2).z)) #define v4_exop(v1, op, v2) ((v1).x op ((v2).x)), ((v1).y op ((v2).y)), ((v1).z op ((v2).z)), ((v1).w op ((v2).w)) #define v2_op_scalar(sc, op, v) CLiteral(V2F32){ v2_exop_scalar(sc,op,v) } #define v3_op_scalar(sc, op, v) CLiteral(V3F32){ v3_exop_scalar(sc,op,v) } #define v4_op_scalar(sc, op, v) CLiteral(V4F32){ v4_exop_scalar(sc,op,v) } #define v2_op(v1, op, v2) CLiteral(V2F32){ v2_exop(v1,op,v2) } #define v3_op(v1, op, v2) CLiteral(V3F32){ v3_exop(v1,op,v2) } #define v4_op(v1, op, v2) CLiteral(V4F32){ v4_exop(v1,op,v2) } #define sc_lerp(s1, l, s2) ((s1) + (l)*((s2) - (s1))) #define v2_lerp(v1, l, v2) v2( sc_lerp((v1).x, l, (v2).x), sc_lerp((v1).y, l, (v2).y) ) #define v3_lerp(v1, l, v2) v3( sc_lerp((v1).x, l, (v2).x), sc_lerp((v1).y, l, (v2).y), sc_lerp((v1).z, l, (v2).z) ) #define v4_lerp(v1, l, v2) v4( sc_lerp((v1).x, l, (v2).x), sc_lerp((v1).y, l, (v2).y), sc_lerp((v1).z, l, (v2).z), sc_lerp((v1).w, l, (v2).w) ) #define v2_dim_from_rect(r) CLiteral(V2F32){ (r).x1 - (r).x0, (r).y1 - (r).y0 } // range macros #define rangef32(min,max) CLiteral(RangeF32){(min),(max)} // 2d vectors MR4TH_SYMBOL V2F32 v2_polar(F32 theta, F32 radius); MR4TH_SYMBOL F32 angle_from_v2f32(V2F32 v); MR4TH_SYMBOL V2F32 v2_unit(V2F32 v); // 3d vectors MR4TH_SYMBOL V3F32 v3_spherical(F32 theta_xz, F32 theta_yz, F32 radius); MR4TH_SYMBOL V3F32 v3_cross(V3F32 a, V3F32 b); MR4TH_SYMBOL V3F32 v3_unit(V3F32 v); // 4x4 matrix MR4TH_SYMBOL B32 mat4x4_inv(F32 *in, F32 *out); MR4TH_SYMBOL void mat4x4_mul(F32 *a, F32 *b, F32 *out); //////////////////////////////// // Functions: Memory Operations MR4TH_SYMBOL void memory_zero(void *ptr, U64 size); MR4TH_SYMBOL void memory_fill(void *ptr, U64 size, U8 fillbyte); MR4TH_SYMBOL B32 memory_match(void *a, void *b, U64 size); MR4TH_SYMBOL void*memory_move(void *a, void *b, U64 size); //////////////////////////////// // Functions: Symbolic Constants MR4TH_SYMBOL OperatingSystem operating_system_from_context(void); MR4TH_SYMBOL Architecture architecture_from_context(void); MR4TH_SYMBOL char* string_from_operating_system(OperatingSystem os); MR4TH_SYMBOL char* string_from_architecture(Architecture arch); MR4TH_SYMBOL char* string_from_month(Month month); MR4TH_SYMBOL char* string_from_day_of_week(DayOfWeek day_of_week); //////////////////////////////// // Functions: Time MR4TH_SYMBOL DenseTime dense_time_from_date_time(DateTime *date_time); MR4TH_SYMBOL DateTime date_time_from_dense_time(DenseTime dense_time); //////////////////////////////// // Functions: Arenas // arena core MR4TH_SYMBOL_MUST_SHARE Arena* arena_new(U64 reserve_size, U64 alignment, B32 growing); MR4TH_SYMBOL_MUST_SHARE void arena_release(Arena *arena); MR4TH_SYMBOL_MUST_SHARE void* arena_push_no_zero(Arena *arena, U64 size); MR4TH_SYMBOL_MUST_SHARE void arena_pop_to(Arena *arena, U64 pos); MR4TH_SYMBOL_MUST_SHARE U64 arena_current_pos(Arena *arena); MR4TH_SYMBOL_MUST_SHARE U64 arena_current_align(Arena *arena); MR4TH_SYMBOL_MUST_SHARE void arena_set_align(Arena *arena, U64 alignment); MR4TH_SYMBOL_MUST_SHARE ArenaTemp arena_get_scratch(Arena **conflict_array, U32 count); // arena helpers MR4TH_SYMBOL Arena* arena_alloc(void); MR4TH_SYMBOL void* arena_push(Arena *arena, U64 size); MR4TH_SYMBOL void arena_pop_amount(Arena *arena, U64 amount); MR4TH_SYMBOL void arena_align(Arena *arena, U64 pow2_align); #define push_array(a,T,c) (T*)arena_push((a), sizeof(T)*(c)) #define push_array_no_zero(a,T,c) (T*)arena_push_no_zero((a), sizeof(T)*(c)) #define push_array_copy(a,T,c,p) (T*)(MemoryCopy(push_array(a,T,c), (p), sizeof(T)*(c))) MR4TH_SYMBOL ArenaTemp arena_begin_temp(Arena *arena); MR4TH_SYMBOL void arena_end_temp(ArenaTemp *temp); #define arena_release_scratch(temp) arena_end_temp(temp) //////////////////////////////// // Functions: Strings // characters MR4TH_SYMBOL B32 char_is_whitespace(U8 c); MR4TH_SYMBOL B32 char_is_slash(U8 c); MR4TH_SYMBOL B32 char_is_digit(U8 c); MR4TH_SYMBOL U8 char_to_uppercase(U8 c); MR4TH_SYMBOL U8 char_to_lowercase(U8 c); // in-place constructors #define str8(p,z) CLiteral(String8){(U8*)(p), (z)} MR4TH_SYMBOL String8 str8_range(U8 *first, U8 *opl); MR4TH_SYMBOL String8 str8_cstring(U8 *cstr); MR4TH_SYMBOL String8 str8_cstring_capped(U8 *cstr, U8 *opl); MR4TH_SYMBOL String16 str16_cstring(U16 *cstr); // literal constructors #define str8_lit(s) CLiteral(String8){(U8*)(s), sizeof(s) - 1} #define str8_lit_const(s) {(U8*)(s), sizeof(s) - 1} // compound constructors MR4TH_SYMBOL void str8_list_push(Arena *arena, String8List *list, String8 string); MR4TH_SYMBOL void str8_list_push_front(Arena *arena, String8List *list, String8 string); MR4TH_SYMBOL String8List str8_list_copy(Arena *arena, String8List *list); MR4TH_SYMBOL String8 str8_join(Arena *arena, String8List *list, StringJoin *optional_join); MR4TH_SYMBOL String8List str8_split(Arena *arena, String8 string, U8 *split_characters, U32 count); MR4TH_SYMBOL String8 str8_pushfv(Arena *arena, char *fmt, va_list args); MR4TH_SYMBOL String8 str8_pushf(Arena *arena, char *fmt, ...); MR4TH_SYMBOL void str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...); MR4TH_SYMBOL String8 str8_push_copy(Arena *arena, String8 string); // substrings MR4TH_SYMBOL String8 str8_prefix(String8 str, U64 size); MR4TH_SYMBOL String8 str8_chop(String8 str, U64 amount); MR4TH_SYMBOL String8 str8_postfix(String8 str, U64 size); MR4TH_SYMBOL String8 str8_skip(String8 str, U64 amount); MR4TH_SYMBOL String8 str8_skip_chop_whitespace(String8 str); // hash MR4TH_SYMBOL U64 str8_hash(String8 str); // compare MR4TH_SYMBOL B32 str8_match(String8 a, String8 b, StringMatchFlags flags); // path helpers MR4TH_SYMBOL String8 str8_chop_last_slash(String8 string); MR4TH_SYMBOL String8 str8_file_name_from_path(String8 full_file_name); MR4TH_SYMBOL String8 str8_base_name_from_file_name(String8 file_name); // stylized constructors MR4TH_SYMBOL String8 str8_join_flags(Arena *arena, String8List *list); // unicode MR4TH_SYMBOL StringDecode str_decode_utf8(U8 *str, U32 cap); MR4TH_SYMBOL U32 str_encode_utf8(U8 *dst, U32 codepoint); MR4TH_SYMBOL StringDecode str_decode_utf16(U16 *str, U32 cap); MR4TH_SYMBOL U32 str_encode_utf16(U16 *dst, U32 codepoint); MR4TH_SYMBOL String32 str32_from_str8(Arena *arena, String8 string); MR4TH_SYMBOL String8 str8_from_str32(Arena *arena, String32 string); MR4TH_SYMBOL String16 str16_from_str8(Arena *arena, String8 string); MR4TH_SYMBOL String8 str8_from_str16(Arena *arena, String16 string); // numeric conversion MR4TH_SYMBOL B32 str8_is_u64(String8 string, U32 radix); MR4TH_SYMBOL U64 u64_from_str8(String8 string, U32 radix); MR4TH_SYMBOL U64 u64_from_str8_c_syntax(String8 string); MR4TH_SYMBOL S64 s64_from_str8_c_syntax(String8 string); MR4TH_SYMBOL F64 f64_from_str8(String8 string); //////////////////////////////// // Functions: Stream // stream core MR4TH_SYMBOL_MUST_SHARE STREAM* stream_new(void); MR4TH_SYMBOL_MUST_SHARE void stream_release(STREAM *stream); MR4TH_SYMBOL_MUST_SHARE void stream_clear(STREAM *stream); MR4TH_SYMBOL_MUST_SHARE void stream_write(STREAM *stream, String8 data); MR4TH_SYMBOL_MUST_SHARE U8* stream_alloc(STREAM *stream, U64 size); MR4TH_SYMBOL_MUST_SHARE U64 stream_total_size(STREAM *stream); MR4TH_SYMBOL_MUST_SHARE STREAM_Handle* stream_next_chunk(STREAM *stream, STREAM_Handle *handle, String8 *chunk_out); // stream helpers MR4TH_SYMBOL String8 stream_read(Arena *arena, STREAM *stream); MR4TH_SYMBOL void stream_printfv(STREAM *stream, char *fmt, va_list args); MR4TH_SYMBOL void stream_printf(STREAM *stream, char *fmt, ...); //////////////////////////////// // Functions: Buffer MR4TH_SYMBOL void buffer_alloc(BUFFER *buffer, U64 reserve_size); MR4TH_SYMBOL void buffer_release(BUFFER *buffer); MR4TH_SYMBOL void buffer_reset(BUFFER *buffer); MR4TH_SYMBOL void buffer_commit_off__call(BUFFER *buffer, U64 off); #define buffer_commit_off(b, off) \ if ((b)->commit_pos < (off) && (off) <= (b)->size){ \ buffer_commit_off__call((b),(off)); } #define buffer_typed_commit_idx(b, idx) \ buffer_commit_off(&(b)->buffer, (idx)*sizeof(*(b)->ptr)) //////////////////////////////// // Types: Hash Table MR4TH_SYMBOL void hash_buckets_init(BUFFER *buckets, U64 count); MR4TH_SYMBOL HASH_Node* hash_buckets_first(BUFFER *buckets, U64 hash); MR4TH_SYMBOL void hash_buckets_expand(BUFFER *buckets, U64 capacity); MR4TH_SYMBOL void hash_buckets_insert(Arena *arena, BUFFER *buckets, U64 hash, U64 val); //////////////////////////////// // Functions: Log MR4TH_SYMBOL void log_accum_begin(LOG_LogToProc *proc, void *uptr); MR4TH_SYMBOL B32 log_gathering(void); MR4TH_SYMBOL void log_emit(String8 message); MR4TH_SYMBOL void log_emitf(char *fmt, ...); MR4TH_SYMBOL String8 log_accum_end(Arena *arena); //////////////////////////////// // Functions: Errors MR4TH_SYMBOL void er_accum_begin(void); MR4TH_SYMBOL void er_emit(String8 error); MR4TH_SYMBOL void er_emitf(char *fmt, ...); MR4TH_SYMBOL String8 er_accum_end(Arena *arena); //////////////////////////////////////////////// //////////////////////////////////////////////// ///////// DECLARATIONS PROFILING /////////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////// // Profiling: Implementable Interface #if MR4TH_PROFILING_USER || MR4TH_PROFILING_PROVIDER MR4TH_SYMBOL_LINK void prof_open(char *name); MR4TH_SYMBOL_LINK void prof_close(void); MR4TH_SYMBOL_LINK void prof_thread_begin(void); MR4TH_SYMBOL_LINK void prof_thread_end(void); MR4TH_SYMBOL_LINK void prof_thread_flush(void); MR4TH_SYMBOL_LINK void prof_begin(char *name, U32 len); MR4TH_SYMBOL_LINK void prof_end(void); #endif //////////////////////////////// // Profiling: User Interface #if MR4TH_PROFILING_USER # define ProfOpen(n) prof_open((char*)(n)) # define ProfClose() prof_close() # define ProfThreadBegin() prof_thread_begin() # define ProfThreadEnd() prof_thread_end() # define ProfThreadFlush() prof_thread_flush() # define ProfBegin(n) prof_begin((n), sizeof(n) - 1) # define ProfEnd() prof_end() #else # define ProfOpen(n) # define ProfClose() # define ProfThreadBegin() # define ProfThreadEnd() # define ProfThreadFlush() # define ProfBegin(n) # define ProfEnd() #endif #if MR4TH_PROFILING_MANUAL # define ProfBeginManual(n) ProfBegin(n) # define ProfEndManual() ProfEnd() #else # define ProfBeginManual(n) # define ProfEndManual() #endif #define ProfBeginFunc() ProfBeginManual(__FUNCTION__) #define ProfEndFunc() ProfEndManual() //////////////////////////////////////////////// //////////////////////////////////////////////// /////// DECLARATIONS OS ABSTRACTION //////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////// // Shared Types typedef struct OS_FileIter{ U8 v[640]; } OS_FileIter; typedef enum OS_SystemPath{ OS_SystemPath_CurrentDirectory = 0, OS_SystemPath_Binary = 1, OS_SystemPath_UserData = 2, OS_SystemPath_TempData = 3, OS_SystemPath_COUNT } OS_SystemPath; typedef void OS_Library; typedef struct OS_VRange{ void *addr; U64 size; } OS_VRange; //////////////////////////////// // Implementable Functions: Process Setup MR4TH_SYMBOL void os_main_init(int argc, char **argv); MR4TH_SYMBOL String8List os_command_line_arguments(void); MR4TH_SYMBOL void os_exit_process(U32 code); //////////////////////////////// // Implementable Functions: Memory Functions MR4TH_SYMBOL void* os_memory_reserve(U64 size); MR4TH_SYMBOL B32 os_memory_commit(void *ptr, U64 size); MR4TH_SYMBOL void os_memory_decommit(void *ptr, U64 size); MR4TH_SYMBOL void os_memory_release(void *ptr, U64 size); MR4TH_SYMBOL B32 os_memory_protect(void *ptr, U64 size, DataAccessFlags access_flags); //////////////////////////////// // Implementable Functions: File Handling MR4TH_SYMBOL String8 os_file_read(Arena *arena, String8 file_name); typedef String8 OS_FileWriteCallback(void *udata); MR4TH_SYMBOL B32 os_file_write_callback(String8 file_name, void *udata, OS_FileWriteCallback *callback); MR4TH_SYMBOL FileProperties os_file_properties(String8 file_name); MR4TH_SYMBOL B32 os_file_delete(String8 file_name); MR4TH_SYMBOL B32 os_file_rename(String8 og_name, String8 new_name); MR4TH_SYMBOL B32 os_file_make_directory(String8 path); MR4TH_SYMBOL B32 os_file_delete_directory(String8 path); MR4TH_SYMBOL OS_FileIter os_file_iter_init(Arena *arena, String8 path); MR4TH_SYMBOL B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, String8 *name_out, FileProperties *prop_out); MR4TH_SYMBOL void os_file_iter_end(OS_FileIter *iter); MR4TH_SYMBOL String8 os_file_path(Arena *arena, OS_SystemPath path); MR4TH_SYMBOL void os_set_current_directory(String8 path); //////////////////////////////// // Implementable Functions: Time MR4TH_SYMBOL DateTime os_now_universal_time(void); MR4TH_SYMBOL DateTime os_local_time_from_universal(DateTime *date_time); MR4TH_SYMBOL DateTime os_universal_time_from_local(DateTime *date_time); MR4TH_SYMBOL U32 os_time_stamp_32_from_date_time(DateTime *date_time); MR4TH_SYMBOL U64 os_now_ticks(void); MR4TH_SYMBOL void os_get_microseconds_per_tick(U64 *usecs_out, U64 *ticks_out); MR4TH_SYMBOL void os_sleep_milliseconds(U32 t); //////////////////////////////// // Implementable Functions: Libraries MR4TH_SYMBOL OS_Library* os_lib_load(String8 path); MR4TH_SYMBOL VoidFunc* os_lib_get_proc(OS_Library *lib, char *name); MR4TH_SYMBOL void os_lib_release(OS_Library *lib); MR4TH_SYMBOL OS_Library* os_lib_from_addr(void *addr); MR4TH_SYMBOL OS_VRange os_lib_image_range(OS_Library *lib); //////////////////////////////// // Implementable Functions: Entropy MR4TH_SYMBOL void os_get_entropy(void *data, U64 size); //////////////////////////////// // Helper Functions: File Handling MR4TH_SYMBOL B32 os_file_write(String8 file_name, String8 data); MR4TH_SYMBOL B32 os_file_write_list(String8 file_name, String8Node *first_node); MR4TH_SYMBOL B32 os_file_write_stream(String8 file_name, STREAM *stream); //////////////////////////////// // Helper Functions: Libraries MR4TH_SYMBOL OS_VRange os_this_image(void); /******************************* ** Begin Base Win32 ** *******************************/ #if OS_WINDOWS //////////////////////////////// // Win32 Includes #include #include #include //////////////////////////////// // Win32 Types typedef struct W32_FileIter{ HANDLE handle; WIN32_FIND_DATAW find_data; B32 done; } W32_FileIter; StaticAssert(sizeof(W32_FileIter) <= sizeof(OS_FileIter), w32_fileiter); //////////////////////////////// // Win32 Functions: Specialized Init for WinMain MR4TH_SYMBOL void w32_WinMain_init(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd); MR4TH_SYMBOL HINSTANCE w32_get_instance(void); //////////////////////////////// // Win32 Functions: Time Helpers MR4TH_SYMBOL DateTime w32_date_time_from_system_time(SYSTEMTIME *in); MR4TH_SYMBOL SYSTEMTIME w32_system_time_from_date_time(DateTime *in); MR4TH_SYMBOL DenseTime w32_dense_time_from_file_time(FILETIME *file_time); //////////////////////////////// // Win32 Functions: File Helpers MR4TH_SYMBOL FilePropertyFlags w32_prop_flags_from_attribs(DWORD attribs); MR4TH_SYMBOL DataAccessFlags w32_access_from_attributes(DWORD attribs); //////////////////////////////// // Win32 Helper Macro #define W32_PROC_ADDR(v,m,s) (*(PROC*)(&(v))) = GetProcAddress((m),(s)) #endif /* OS_WINDOWS */ /******************************* ** End Base Win32 ** *******************************/ /******************************* ** Begin Base Linux ** *******************************/ #if OS_LINUX //////////////////////////////// // Linux Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////// // Linux Types typedef struct LNX_FileIter{ DIR *dir; struct dirent *dp; String8 path; } LNX_FileIter; StaticAssert(sizeof(LNX_FileIter) <= sizeof(OS_FileIter), lnx_fileiter); //////////////////////////////// // Linux Functions: Time Helpers MR4TH_SYMBOL DateTime lnx_date_time_from_tm(struct tm *tm); MR4TH_SYMBOL DenseTime lnx_dense_time_from_time_t(time_t time); MR4TH_SYMBOL struct tm lnx_tm_from_date_time(DateTime *date_time); //////////////////////////////// // Linux Functions: File Helpers MR4TH_SYMBOL FilePropertyFlags lnx_prop_flags_from_mode(mode_t mode); MR4TH_SYMBOL DataAccessFlags lnx_access_from_mode(mode_t mode); MR4TH_SYMBOL FileProperties lnx_file_properties_from_stat(struct stat *st); MR4TH_SYMBOL String8 lnx_proc_file_read(Arena *arena, char *path); #endif /* OS_LINUX */ /******************************* ** End Base Linux ** *******************************/ //////////////////////////////////////////////// //////////////////////////////////////////////// ///////////////// M4 Printf //////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// // stb_sprintf.h STB_SPRINTF_H_INCLUDE /* Single file sprintf replacement. Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. Hereby placed in public domain. This is a full sprintf replacement that supports everything that the C runtime sprintfs support, including float/double, 64-bit integers, hex floats, field parameters (%*.*d stuff), length reads backs, etc. Why would you need this if sprintf already exists? Well, first off, it's *much* faster (see below). It's also much smaller than the CRT versions code-space-wise. We've also added some simple improvements that are super handy (commas in thousands, callbacks at buffer full, for example). Finally, the format strings for MSVC and GCC differ for 64-bit integers (among other small things), so this lets you use the same format strings in cross platform code. It uses the standard single file trick of being both the header file and the source itself. If you just include it normally, you just get the header file function definitions. To get the code, you include it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. It only uses va_args macros from the C runtime to do it's work. It does cast doubles to S64s and shifts and divides U64s, which does drag in CRT code on most platforms. It compiles to roughly 8K with float support, and 4K without. As a comparison, when using MSVC static libs, calling sprintf drags in 16K. API: ==== int stbsp_sprintf( char * buf, char const * fmt, ... ) int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) Convert an arg list into a buffer. stbsp_snprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); Convert into a buffer, calling back every STB_SPRINTF_MIN chars. Your callback can then copy the chars out, print them or whatever. This function is actually the workhorse for everything else. The buffer you pass in must hold at least STB_SPRINTF_MIN characters. // you return the next buffer to use or 0 to stop converting void stbsp_set_separators( char comma, char period ) Set the comma and period characters to use. FLOATS/DOUBLES: =============== This code uses a internal float->ascii conversion method that uses doubles with error correction (double-doubles, for ~105 bits of precision). This conversion is round-trip perfect - that is, an atof of the values output here will give you the bit-exact double back. One difference is that our insignificant digits will be different than with MSVC or GCC (but they don't match each other either). We also don't attempt to find the minimum length matching float (pre-MSVC15 doesn't either). If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT and you'll save 4K of code space. NOTE(allen): MODIFICATION - I've hard coded that this copy *does* use floats 64-BIT INTS: ============ This library also supports 64-bit integers and you can use MSVC style or GCC style indicators (%I64d or %lld). It supports the C99 specifiers for size_t and ptr_diff_t (%jd %zd) as well. EXTRAS: ======= Like some GCCs, for integers and floats, you can use a ' (single quote) specifier and commas will be inserted on the thousands: "%'d" on 12345 would print 12,345. For integers and floats, you can use a "$" specifier and the number will be converted to float and then divided to get kilo, mega, giga or tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is "2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn 2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three $:s: "%$$$d" -> "2.42 M". To remove the space between the number and the suffix, add "_" specifier: "%_$d" -> "2.53M". In addition to octal and hexadecimal conversions, you can print integers in binary: "%b" for 256 would print 100. PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): =================================================================== "%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) "%24d" across all 32-bit ints (4.5x/4.2x faster) "%x" across all 32-bit ints (4.5x/3.8x faster) "%08x" across all 32-bit ints (4.3x/3.8x faster) "%f" across e-10 to e+10 floats (7.3x/6.0x faster) "%e" across e-10 to e+10 floats (8.1x/6.0x faster) "%g" across e-10 to e+10 floats (10.0x/7.1x faster) "%f" for values near e-300 (7.9x/6.5x faster) "%f" for values near e+300 (10.0x/9.1x faster) "%e" for values near e-300 (10.1x/7.0x faster) "%e" for values near e+300 (9.2x/6.0x faster) "%.320f" for values near e-300 (12.6x/11.2x faster) "%a" for random values (8.6x/4.3x faster) "%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) "%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) "%s%s%s" for 64 char strings (7.1x/7.3x faster) "...512 char string..." ( 35.0x/32.5x faster!) */ #if defined(__clang__) #if defined(__has_feature) && defined(__has_attribute) #if __has_feature(address_sanitizer) #if __has_attribute(__no_sanitize__) #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) #elif __has_attribute(__no_sanitize_address__) #define STBSP__ASAN __attribute__((__no_sanitize_address__)) #elif __has_attribute(__no_address_safety_analysis__) #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) #endif #endif #endif #elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ #define STBSP__ASAN __attribute__((__no_sanitize_address__)) #endif #endif #ifndef STBSP__ASAN #define STBSP__ASAN #endif #ifdef STB_SPRINTF_STATIC #define STBSP__PUBLICDEC static #define STBSP__PUBLICDEF static STBSP__ASAN #else #ifdef __cplusplus #define STBSP__PUBLICDEC extern "C" #define STBSP__PUBLICDEF extern "C" STBSP__ASAN #else #define STBSP__PUBLICDEC extern #define STBSP__PUBLICDEF STBSP__ASAN #endif #endif #if defined(__has_attribute) #if __has_attribute(format) #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) #endif #endif #ifndef STBSP__ATTRIBUTE_FORMAT #define STBSP__ATTRIBUTE_FORMAT(fmt,va) #endif #ifdef _MSC_VER #define STBSP__NOTUSED(v) (void)(v) #else #define STBSP__NOTUSED(v) (void)sizeof(v) #endif //#include // size_t, ptrdiff_t #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); STBSP__PUBLICDEC int m4_vsprintf(char *buf, char const *fmt, va_list va); STBSP__PUBLICDEC int m4_vsnprintf(char *buf, int count, char const *fmt, va_list va); STBSP__PUBLICDEC int m4_sprintf(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); STBSP__PUBLICDEC int m4_snprintf(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); STBSP__PUBLICDEC int m4_vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); STBSP__PUBLICDEC void m4_set_separators(char comma, char period); /* ** NOTE(allen): sprintf modifications notes ** ** Legend for specifier allocation: ** [ ] - specifier is free for use ** [#] - used by stb_sprintf default ** [$] - used by built-in custom printing logic ** ** Specifier allocation: ** a[#] - hex float ** A[#] - hex float ** b[#] - binary ** B[#] - binary ** c[#] - char ** C[ ] ** d[#] - integer ** D[ ] ** e[#] - float ** E[#] - float ** f[#] - float ** F[ ] ** g[#] - float ** G[#] - float ** h[#] - half width ** H[ ] ** i[#] - integer ** I[#] - size[Microsoft-Style] ** j[#] - size[size_t] ** J[ ] ** k[ ] ** K[ ] ** l[#] - size[long]/size[long long] ** L[ ] ** m[ ] ** M[ ] ** n[#] - write-bytes ** N[$] - indentation ** o[#] - octal ** O[ ] ** p[ ] ** P[ ] ** q[ ] ** Q[ ] ** r[ ] ** R[ ] ** s[#] - cstr ** S[$] - String8 ** t[#] - size[ptrdiff_t] ** T[ ] ** u[#] - unsigned integer ** U[ ] ** v[ ] ** V[ ] ** w[ ] ** W[ ] ** x[#] - hex ** X[#] - hex ** y[ ] ** Y[ ] ** z[#] - size[size_t] ** Z[ ] ** 0[#] - leading zeroes ** 1[ ] ** 2[ ] ** 3[ ] ** 4[ ] ** 5[ ] ** 6[ ] ** 7[ ] ** 8[ ] ** 9[ ] ** $[$] - memory size (modified from stb_sprintf.h) ** ?[ ] ** */ #endif /* MR4TH_BASE_H */ /* ** TODO: ** [ ] m4_printf plugins experiment ** ** [ ] unicode support ** [ ] high performance encode/decode factorization ** [ ] unicode string conversions should take string lists "Better unicode conversions here" ** [ ] math implementation replacements ** [ ] clib elimination option ** [x] manually implement memset,memcmp,memmove ** [x] basic C implementations ** [ ] high performance implementations (hand written assembly perhaps? -- or at least use vector intrinsics) ** [ ] necessary stubs for clib elimination ** [ ] Test out the usage process ** [ ] default (unity build standalone) ** [ ] standalone multi-unit ** [ ] core & plugin ** [ ] Write instructions ** [ ] Write examples ** ** [ ] Multi-threading primitives ** [ ] Thread-safe STREAM */