Musa-Cpp-Lib-V2/lib/Base/Base.h

190 lines
5.3 KiB
C++

#pragma once
#define LANG_CPP 1
#define BUILD_CONSOLE_INTERFACE BUILD_DEBUG
#if ARCH_CPU_X64
#include "CPU_X64.cpp"
#define PLATFORM_MEMORY_PAGE_SIZE 4096
#define PLATFORM_MEMORY_LARGE_PAGE_SIZE 2097152
#define CPU_REGISTER_WIDTH_BYTES 8
#define CPU_CACHE_LINE_SIZE 64
#else
#error "CPU not supported (yet)!"
#endif
#if OS_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#undef ERROR // why...
#else
#error "This configuration is NOT supported. Only Windows with MSVC is currently supported."
#endif
#ifndef PROTOTYPING_API
#ifdef OS_WINDOWS
#define PROTOTYPING_API extern "C" __declspec(dllexport)
#else
#define PROTOTYPING_API
#endif
#endif // #ifndef PROTOTYPING_API
#define C_API
#define TEMPORARY_API
#define DEPRECATED_API
#include <string.h>
#include <stdint.h>
// Primitive 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 bool b8; // just use bool for b8s
typedef s16 b16;
typedef s32 b32;
typedef s64 b64;
typedef float f32;
typedef double f64;
// Units
#define KB(n) (((s64)(n)) << 10)
#define MB(n) (((s64)(n)) << 20)
#define GB(n) (((s64)(n)) << 30)
#define TB(n) (((s64)(n)) << 40)
#define Thousand(n) ((n)*1000)
#define Million(n) ((n)*1000000)
#define Billion(n) ((n)*1000000000)
#define internal static
#define global static
#define local_persist static // I don't like these, so I generally won't use them!
#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 || (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
#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
// Maybe move to a different file.
force_inline s64 Align_To_Page_Size(s64 n) {
return (n + PLATFORM_MEMORY_PAGE_SIZE - 1) & (~(PLATFORM_MEMORY_PAGE_SIZE-1));
}
template <typename T>
force_inline T Align (T value, s64 alignment) {
s64 intermediate = (((s64)value) + alignment - 1) & (~(alignment - 1));
return (T)intermediate;
}
// #TODO: template this so it works with any pointer type
// force_inline u8* Align_To_Cache_Line(u8* address)
/*
force_inline s64 Align_Forwards(s64 size, s64 alignment) {
return (((size + alignment - 1) / alignment) * alignment);
}
*/
// Branchless nextpow2 implementation. Returns zero if v is negative.
// All it does is fill in all the bits to the right of the most significant bit.
force_inline s64 Next_Power_Of_Two(s64 v) {
v -= 1;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v += 1;
return v;
}
#define Stringify_(S) #S
#define Stringify(S) Stringify_(S)
#define Concat_(A,B) A##B
#define Concat(A,B) Concat_(A,B)
#if COMPILER_MSVC
# define debug_break() __debugbreak()
#elif COMPILER_CLANG || COMPILER_GCC
# define debug_break() __builtin_trap()
#else
# define debug_break()
# error Unknown trap intrinsic for this compiler.
#endif
#define AssertAlways(x) do{if(!(x)) {debug_break();}}while(0)
#if BUILD_DEBUG
# define Assert(x) AssertAlways(x)
#else
# define Assert(x) (void)(x)
#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
// Disable some of MSVC most aggressive Debug runtime checks in function header/footer (used in some simple/low-level functions)
#if COMPILER_MSVC
#define MSVC_RUNTIME_CHECKS_OFF __pragma(runtime_checks("",off)) __pragma(check_stack(off)) __pragma(strict_gs_check(push,off))
#define MSVC_RUNTIME_CHECKS_RESTORE __pragma(runtime_checks("",restore)) __pragma(check_stack()) __pragma(strict_gs_check(pop))
#else
#define MSVC_RUNTIME_CHECKS_OFF
#define MSVC_RUNTIME_CHECKS_RESTORE
#endif
// ForExpansions. Not sure if this is a good idea...
// #TODO: Maybe remove these. I prefer verbose and clear over this.
#define For(_idx_, _until_) for (s64 _idx_ = 0; _idx_ < _until_; ++_idx_)
#define ForBetween(_idx_, _start_, _until_) for (s64 _idx_ = _start_; _idx_ < _until_; ++_idx_)
#define ForArray(_idx_, _array_) for (s64 _idx_ = 0; _idx_ < (_array_).count; ++_idx_)
#define ForArrayStartingAt(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
#define ForUpTo(_it_, _end_) for (s64 _it_ = 0; _it_ < _end_; _it_ += 1)
// Scoped Macros/Functions for auto_reset and auto_release
// usage `Auto_Reset guard(arena);` within a scope.
#define auto_reset(x) \
Auto_Reset Concat(_auto_reset_guard_, __LINE__)(x)
#define push_allocator(x) Push_Allocator Concat(_push_alloc_guard_, __LINE__)(x)
#define push_alignment(x, y) \
Push_Alignment Concat(_push_align_guard_, __LINE__)(x, y)
#define push_arena(x) \
Push_Arena Concat(_push_alloc_guard_, __LINE__)(x)
#define auto_release_temp() auto_release(get_temp_allocator());
#define auto_release(x) \
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)