#ifndef CORE_H #define CORE_H // cstdlib includes #include "math.h" #include "stdbool.h" #include "stdint.h" // necessary for int type sizes #include "stdio.h" #include "time.h" // TODO(djledda): try not to depend on this one // ### Misc macros ### #if ENABLE_ASSERT #define Assert(expression) if (!(expression)) {*(volatile int *)0 = 0;} #else #define Assert(expression) #endif #define function static #define global static #define local_persist static // ### Types ### typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; typedef uint8_t byte; typedef float real32; typedef double real64; typedef struct string string; // ### Sizes and Numbers ### #define Bytes(n) (n) #define Kilobytes(n) (n << 10) #define Megabytes(n) (n << 20) #define Gigabytes(n) (((uint64)n) << 30) #define Terabytes(n) (((uint64)n) << 40) #define Thousand(n) ((n)*1000) #define Million(n) ((n)*1000000) #define Billion(n) ((n)*1000000000LL) #define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0])) #define MemberSize(type, memberName) sizeof(((type *)0)->memberName) #define MemberType(type, memberName) typeof(((type *)0)->memberName) #define MemberSizeUnderlying(type, memberName) sizeof(*((type *)0)->memberName) #define MemberTypeUnderlying(type, memberName) typeof(*((type *)0)->memberName) // ### Arenas ### typedef struct { void *memory; size_t capacity; size_t head; } Arena; typedef struct { Arena *arena; size_t start; } Scratch; void *pushSize(Arena *arena, size_t bytes); void *pushSizeFill(Arena *arena, size_t bytes, byte fill); Arena *arenaAlloc(size_t capacity); void arenaFree(Arena *arena); void arenaFreeFrom(Arena *arena, size_t pos); void arenaPopTo(Arena *arena, void *pos); void initialiseDjStdCore(); Scratch scratchStart(Arena **conflicts, size_t conflictCount); void scratchEnd(Scratch scratch); #define PushArray(arena, type, size) (type *)pushSize(arena, sizeof(type) * (size)) #define PushArrayZero(arena, type, size) (type *)pushSizeFill(arena, sizeof(type) * (size), 0) #define PushStruct(arena, type) (type *)pushSize(arena, sizeof(type)) #define PushStructZero(arena, type) (type *)pushSizeFill(arena, sizeof(type), 0) // ### Vectors ### typedef union { struct { real32 x; real32 y; }; real32 vec[2]; } Vec2; inline function Vec2 vec2(real32 x, real32 y) { Vec2 result = {0}; result.x = x; result.y = y; return result; } typedef union { struct { real32 x; real32 y; real32 z; }; real32 vec[3]; } Vec3; inline function Vec3 vec3(real32 x, real32 y, real32 z) { Vec3 result = {0}; result.x = x; result.y = y; result.z = z; return result; } typedef union { struct { real32 r; real32 g; real32 b; real32 a; }; struct { real32 x; real32 y; real32 z; real32 w; }; real32 vec[4]; } Vec4; inline function Vec4 vec4(real32 x, real32 y, real32 z, real32 w) { Vec4 result = {0}; result.x = x; result.y = y; result.z = z; result.w = w; return result; } // ### Lists ### #define DefineList(type, prefix) \ typedef struct {\ type* data;\ size_t length;\ size_t head;\ } prefix ## List DefineList(string, String); #define PushList(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSize(arena, MemberSizeUnderlying(type, data)*size), size, 0 } #define EmptyList(type) (type){ NULL, 0, 0 } #define PushListZero(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSizeFill(arena, MemberSizeUnderlying(type, data)*size, 0), size, 0 } #define PushFullList(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSize(arena, MemberSizeUnderlying(type, data))*size, size, size } #define PushFullListZero(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSizeFill(arena, MemberSizeUnderlying(type, data)*size, 0), size, size } #define ArrayAsList(type, array) (type){ array, ArrayCount(array), ArrayCount(array) } #define AppendList(list, element) \ if ((list)->head < (list)->length) { \ (list)->data[(list)->head++] = (element); \ } #define ZeroListFull(list) memset((list)->data, 0, (list)->head * sizeof(T)) #define ZeroList(list) (list)->head = 0; \ memset((list)->data, 0, (list)->head * sizeof(T)); // ### Strings ### struct string { char *str; size_t length; }; #define STB_SPRINTF_DECORATE(name) stb_##name // define this before including if you want to change the names #include "vendor/stb_sprintf.h" #define s(lit) ((string){(char *)(lit), sizeof(lit) - 1}) #define PushString(arena, length) ((string){ (char *)pushSize(arena, length), (length) }) #define PushStringFill(arena, length, characterByte) ((string){ (char *)pushSizeFill(arena, length, characterByte), (length) }) // C Strings DefineList(char, Char); const char *cstringFromCharList(Arena *arena, CharList buf); const char *cstring(Arena *arena, string str); size_t calcStringLen(const char *str); string strFromCString(Arena *arena, const char *str); bool strEql(string s1, string s2); bool strStartsWith(string str, string testStr); bool stringContains(string str, char c); string strReverse(Arena *arena, string str); string strSlice(string str, size_t start, size_t stop); string strSliceCStr(char *data, size_t start, size_t stop); StringList strSplit(Arena *arena, string splitStr, string inputStr); string strPrintfv(Arena *arena, const char *fmt, va_list args); string strPrintf(Arena *arena, const char *fmt, ...); typedef struct { uint8 result; bool valid; } ParsePositiveIntResult; ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer); typedef struct { real32 result; bool valid; } ParsePositiveReal32Result; ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer); inline function bool isNumeric(char c); // ### Cmdline ### StringList getArgs(Arena *arena, int argc, char **argv); // ### Time ### typedef uint64 UnixTimestamp; typedef struct tm Timestamp; UnixTimestamp getSystemUnixTime(); Timestamp timestampFromUnixTime(UnixTimestamp *unixTimestamp); string formatTimeHmsUnix(Arena *arena, UnixTimestamp time); string formatTimeHms(Arena *arena, Timestamp *time); string formatTimeYmdUnix(Arena *arena, UnixTimestamp time); string formatTimeYmd(Arena *arena, Timestamp *time); // ### Linked Lists ### // TODO(djledda): implement basic linked lists (based on arenas?) // ### Logging ### typedef enum { StdStream_stdout, StdStream_stdin, StdStream_stderr, } StdStream; #define ANSI_INSTRUCTION_FROM_ENUM(ansiCodeEnum) ANSI_INSTRUCTION(ansiCodeEnum) #define ANSI_INSTRUCTION(ansiCode) "\u001b[" #ansiCode "m" #define ANSI_INSTRUCTION_STR(ansiCodeStr) "\u001b[" ansiCodeStr "m" #define ANSI_RESET ANSI_INSTRUCTION(0) #define ANSI_fg_black 30 #define ANSI_fg_red 31 #define ANSI_fg_green 32 #define ANSI_fg_yellow 33 #define ANSI_fg_blue 34 #define ANSI_fg_magenta 35 #define ANSI_fg_cyan 36 #define ANSI_fg_white 37 #define ANSI_fg_bblack 90 #define ANSI_fg_bred 91 #define ANSI_fg_bgreen 92 #define ANSI_fg_byellow 93 #define ANSI_fg_bblue 94 #define ANSI_fg_bmagenta 95 #define ANSI_fg_bcyan 96 #define ANSI_fg_bwhite 97 #define ANSI_bg_black 40 #define ANSI_bg_red 41 #define ANSI_bg_green 42 #define ANSI_bg_yellow 43 #define ANSI_bg_blue 44 #define ANSI_bg_magenta 45 #define ANSI_bg_cyan 46 #define ANSI_bg_white 47 #define ANSI_bg_bblack 100 #define ANSI_bg_bred 101 #define ANSI_bg_bgreen 102 #define ANSI_bg_byellow 103 #define ANSI_bg_bblue 104 #define ANSI_bg_bmagenta 105 #define ANSI_bg_bcyan 106 #define ANSI_bg_bwhite 107 #define COLOR_TEXT(text, foregroundcolor) ANSI_INSTRUCTION_FROM_ENUM(foregroundcolor) text ANSI_RESET #define COLOR_TEXT_BG(text, backgroundcolor) ANSI_INSTRUCTION_FROM_ENUM(backgroundcolor) text ANSI_RESET #define COLOR_TEXT_FG_BG(text, foregroundcolor, backgroundcolor) ANSI_INSTRUCTION_FROM_ENUM(foregroundcolor) ANSI_INSTRUCTION_FROM_ENUM(backgroundcolor) text ANSI_RESET #define COLOR_TEXT_RGB(text, red, green, blue) ANSI_INSTRUCTION_STR("38;2;" #red ";" #green ";" #blue) text ANSI_RESET DefineList(int, Int); void printIntList(IntList l); void printStrList(StringList l); extern void (*print)(const char *fmt, ...); // ### Loops ### #define EachIn(list, it) size_t it = 0; it < (list).head; it++ #define EachInReversed(list, it) size_t it = (list).head - 1; it >= 0 && it < (list).head; it-- #define EachInArray(arr, it) size_t it = 0; it < ArrayCount(arr); ++it // ### Misc ### int intCompare(const void *a, const void *b); #endif