295 lines
9.1 KiB
C
295 lines
9.1 KiB
C
#ifndef BASE_TYPES_H
|
|
#define BASE_TYPES_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
/////////////////////////
|
|
//~ Macros
|
|
|
|
/////////////////////////
|
|
//- Linking keywords
|
|
|
|
// TODO(anton): Understand this, yoinked from rjf's layer.
|
|
#if LANG_CPP
|
|
# define no_name_mangle extern "C"
|
|
#else
|
|
# define no_name_mangle
|
|
#endif
|
|
|
|
// TODO(anton): OS_WINDOWS dll import/export macros
|
|
|
|
/////////////////////////
|
|
//- Keywords
|
|
// Static is stupid and means different things depending on context in C and C++.
|
|
// These defines increases readability.
|
|
#define function static // Function internal to compilation unit.
|
|
#define local_persist static
|
|
#define global static
|
|
#define fallthrough // for use in switch statements, for clarity..
|
|
|
|
// TODO(anton): Understand and add good comment on this.
|
|
#if LANG_CPP
|
|
# define root_global no_name_mangle
|
|
# define root_function function
|
|
#else
|
|
# define root_global extern
|
|
# define root_function function
|
|
#endif
|
|
|
|
#define inline_function inline static
|
|
|
|
#if OS_WINDOWS
|
|
# pragma section(".roglob", read)
|
|
# define read_only __declspec(allocate(".roglob"))
|
|
#else
|
|
# define read_only
|
|
#endif
|
|
|
|
#if COMPILER_MSVC
|
|
# define per_thread __declspec(thread)
|
|
#else
|
|
# error Thread keyword not abstracted on compiler.
|
|
#endif
|
|
|
|
/////////////////////////
|
|
//- Memory operations
|
|
// It's nice to put these in macros, so we can swap out the functionality from standard library, eventually.
|
|
#define MemoryCopy memcpy
|
|
#define MemoryMove memmove
|
|
#define MemorySet memset
|
|
|
|
// NOTE(anton): This gives a 4127 compiler warning for the sizeof conditional. This should be ignored
|
|
#define MemoryCopyStruct(dst, src) do { Assert(sizeof(*(dst)) == sizeof(*(src))); MemoryCopy((dst), (src), sizeof(*(dst))); } while(0)
|
|
|
|
#define MemoryZero(ptr, size) MemorySet((ptr), 0, (size))
|
|
#define MemoryZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
|
|
#define MemoryZeroArray(arr) MemoryZero((arr), sizeof(arr))
|
|
|
|
/////////////////////////
|
|
//- Integer/pointer/array/type manipulations
|
|
|
|
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
|
|
#define IntFromPtr(p) (U64)(((U8*)p) - 0)
|
|
#define PtrFromInt(i) (void*)(((U8*)0) + i)
|
|
#define Member(type, member_name) ((type *)0)->member_name
|
|
// TODO(anton): Understand why this becomes offset actually
|
|
#define OffsetOf(type, member_name) IntFromPtr(&Member(type, member_name))
|
|
// TODO(anton): Understand this
|
|
#define BaseFromMember(type, member_name, ptr) (type *)((U8 *)(ptr) - OffsetOf(type, member_name))
|
|
|
|
#define Bytes(n) (n)
|
|
#define Kilobytes(n) (n << 10) // 2^10 == 1024 etc
|
|
#define Megabytes(n) (n << 20)
|
|
#define Gigabytes(n) (((U64)n) << 30)
|
|
#define Terabytes(n) (((U64)n) << 40)
|
|
|
|
#define Thousand(n) ((n)*1000)
|
|
#define Million(n) ((n)*1000000)
|
|
#define Billion(n) ((n)*1000000000LL)
|
|
|
|
#define AbsoluteValueU64(x) (U64)llabs((U64)(x))
|
|
|
|
/////////////////////////
|
|
//- Linked list helpers
|
|
|
|
#define CheckNull(p) ((p)==0)
|
|
#define SetNull(p) ((p)=0)
|
|
// Link list helper macros that are a bit involved
|
|
|
|
// Suffixes N,P,Z means that we have (N)ext, (P)rev arguments and/or a (Z)ero check and/or set argument
|
|
// f, l, n are "first", "last", "node" I think?
|
|
// DLL
|
|
// Doubly Linked List: Each node has a prev and next pointer. Operations: Push back, Push front, remove
|
|
#define DLLInsert_NPZ(f,l,p,n,next,prev,zchk,SetNull) \
|
|
(zchk(f) ? (((f) = (l) = (n)), SetNull((n)->next), SetNull((n)->prev)) :\
|
|
zchk(p) ? (SetNull((n)->prev), (n)->next = (f), (zchk(f) ? (0) : ((f)->prev = (n))), (f) = (n)) :\
|
|
((zchk((p)->next) ? (0) : (((p)->next->prev) = (n))), (n)->next = (p)->next, (n)->prev = (p), (p)->next = (n),\
|
|
((p) == (l) ? (l) = (n) : (0))))
|
|
|
|
#define DLLPushBack_NPZ(f,l,n,next,prev,zchk,SetNull) DLLInsert_NPZ(f,l,l,n,next,prev,zchk,SetNull)
|
|
|
|
#define DLLPushBack_NP(f, l, n, next, prev, zchk) \
|
|
(zchk(f) ? ((f)=(l)=(n),(n)->next=(n)->prev=0) : ((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=0))
|
|
|
|
// If f == n we put f to f->next, and f->prev = 0.
|
|
// Else if l == n, we put l=l->prev, l->next = 0.
|
|
// If l != n and f != n we set n->next->prev to n->prev, and n->prev->next to n->next
|
|
|
|
#define DLLRemove_NP(f, l, n, next, prev) (((f) == (n) ? \
|
|
((f)=(f)->next, (f)->prev=0) : \
|
|
(l) == (n) ? \
|
|
((l)=(l)->prev, (l)->next=0) : \
|
|
((n)->next->prev=(n)->prev, \
|
|
(n)->prev->next=(n)->next) ))
|
|
|
|
#define DLLRemove_NPZ(f,l,n,next,prev,zchk,SetNull) (((f)==(n))?\
|
|
((f)=(f)->next, (zchk(f) ? (SetNull(l)) : SetNull((f)->prev))):\
|
|
((l)==(n))?\
|
|
((l)=(l)->prev, (zchk(l) ? (SetNull(f)) : SetNull((l)->next))):\
|
|
((zchk((n)->next) ? (0) : ((n)->next->prev=(n)->prev)),\
|
|
(zchk((n)->prev) ? (0) : ((n)->prev->next=(n)->next))))
|
|
|
|
#define DLLPushBack(f, l, n) DLLPushBack_NPZ(f, l, n, next, prev, CheckNull, SetNull)
|
|
// For front push I can just switch prev/next!
|
|
#define DLLPushFront(f, l, n) DLLPushBack_NPZ(l, f, n, prev, next, CheckNull, SetNull)
|
|
#define DLLRemove(f, l, n) DLLRemove_NPZ(f, l, n, next, prev, CheckNull, SetNull)
|
|
|
|
|
|
// SLL, queue or stack.
|
|
// These are from rjf's layer.
|
|
|
|
////////////////
|
|
// Queue
|
|
// Queue has only a next pointer. But we can push from front also.
|
|
// zchk = zero check, SetNull = zero set
|
|
#define QueuePush_NZ(f, l, n, next, zchk, SetNull) (zchk(f)?\
|
|
(((f)=(l)=(n)), SetNull((n)->next)):\
|
|
((l)->next=(n),(l)=(n),SetNull((n)->next)))
|
|
|
|
#define QueuePushFront_NZ(f, l, n, next, zchk, SetNull) ( zchk(f) ? \
|
|
((f)=(l)=(n)), SetNull((n)->next) : \
|
|
((n)->next = (f)), ((f) = (n)) )
|
|
|
|
#define QueuePop_NZ(f, l, next, zchk, SetNull) ( (f)==(l) ? \
|
|
(SetNull(f), SetNull(l)) : ((f)=(f)->next))
|
|
|
|
#define QueuePush(f, l, n) QueuePush_NZ(f, l, n, next, CheckNull, SetNull)
|
|
#define QueuePushFront(f, l, n) QueuePushFront_NZ(f, l, n, next, CheckNull, SetNull)
|
|
#define QueuePop(f, l) QueuePop_NZ(f, l, next, CheckNull, SetNull)
|
|
|
|
////////////////
|
|
// Stack
|
|
#define StackPush_N(f, n, next) ((n)->next=(f), (f)=(n)) // Take the first element and set it to n->next, and set the first element to the node n.
|
|
#define StackPop_NZ(f, next, zchk) (zchk(f) ? 0 : ((f)=(f)->next)) // If first element is not zero we say that the first element is f->next, ie we pop f and put f->next on top.
|
|
|
|
#define StackPush(f, n) StackPush_N(f, n, next)
|
|
#define StackPop(f) StackPop_NZ(f, next, CheckNull)
|
|
|
|
/////////////////////////
|
|
//- Clamp/min/max
|
|
#define Min(a, b) (((a)<(b)) ? (a) : (b))
|
|
#define Max(a, b) (((a)>(b)) ? (a) : (b))
|
|
#define ClampTop(x, a) Min(x,a) // "Top" since we are cutting off anything above Min(x,a)
|
|
#define ClampBot(a, x) Max(a,x) // "Bot" since we're cutting off anything below Max(a,x)
|
|
// If a > x we get a, else we see if b < x and then get b if true, else x.
|
|
// TODO(anton): Is this actually what we want from a Clamp?
|
|
#define Clamp(a, x, b) (((a)>(x))?(a):((b)<(x))?(b):(x))
|
|
|
|
//- loop
|
|
#define DeferLoop(start, end) for(int _i_ = ((start), 0); _i_ == 0; _i_ += 1, (end))
|
|
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
|
|
|
#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)
|
|
|
|
|
|
/////////////////////////
|
|
//~ Base types
|
|
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;
|
|
typedef void VoidFunction(void);
|
|
|
|
/////////////////////////
|
|
//~ Numerical limits
|
|
read_only global U8 U8Max = 0xFF;
|
|
read_only global U8 U8Min = 0;
|
|
read_only global U32 U32Max = 0xFFFFFFFF;
|
|
read_only global U32 U32Min = 0;
|
|
read_only global U64 U64Max = 0xFFFFFFFFFFFFFFFF;
|
|
|
|
// TODO(anton): Rest of the limits, unsigned and signed integer values
|
|
read_only global U32 SignF32 = 0x80000000;
|
|
|
|
|
|
//- compiler, shut up! helpers
|
|
#define unused_variable(name) (void)name
|
|
|
|
/////////////////////////
|
|
//~ Base enums
|
|
|
|
// Describing a 2-coordinate system
|
|
typedef enum Axis2
|
|
{
|
|
Axis2_Invalid = -1,
|
|
Axis2_X,
|
|
Axis2_Y,
|
|
Axis2_COUNT
|
|
}
|
|
Axis2;
|
|
#define Axis2_flip(a) ((Axis2)(!(a)))
|
|
|
|
// Corners of a rectangle.
|
|
// 00 ----- 10
|
|
// | |
|
|
// 01 ----- 11
|
|
typedef enum Corner
|
|
{
|
|
Corner_Invalid = -1,
|
|
Corner_00,
|
|
Corner_01,
|
|
Corner_10,
|
|
Corner_11,
|
|
Corner_COUNT
|
|
}
|
|
Corner;
|
|
|
|
////////////////////////////////
|
|
//~ Member Offset Helper
|
|
|
|
typedef struct MemberOffset MemberOffset;
|
|
struct MemberOffset
|
|
{
|
|
U64 v;
|
|
};
|
|
|
|
#define MemberOff(S, member) (MemberOffset){OffsetOf(S, member)}
|
|
#define MemberOffLit(S, member) {OffsetOf(S, member)}
|
|
#define MemberFromOff(ptr, type, memoff) (*(type *)((U8 *)ptr + memoff.v))
|
|
|
|
/////////////////////////
|
|
//~ Assertions
|
|
|
|
#if OS_WINDOWS
|
|
# define break_debugger() __debugbreak()
|
|
#else
|
|
# error not implemented
|
|
#endif
|
|
|
|
#undef Assert
|
|
#define Assert(b) do { if(!(b)) { break_debugger(); } } while(0)
|
|
|
|
#if !defined(LOG_NOT_IMPLEMENTED)
|
|
# define LOG_NOT_IMPLEMENTED printf("\nFATAL ERROR: Not implemented yet.\n"); Assert(false); exit(1);
|
|
#endif
|
|
|
|
/////////////////////////
|
|
//~ Bit patterns
|
|
#define AlignUpToPow2(bytes_to_align, alignment_bytes) (((bytes_to_align) + (alignment_bytes - 1)) & ~(alignment_bytes - 1))
|
|
|
|
inline_function F32
|
|
absolute_value_F32(F32 f)
|
|
{
|
|
union { U32 u; F32 f; } x;
|
|
x.f = f;
|
|
x.u = x.u & ~SignF32;
|
|
return x.f;
|
|
}
|
|
|
|
// TODO(anton): Understand rjf's bit patterns
|
|
|
|
#endif //BASE_TYPES_H
|