#ifndef CORE_H #define CORE_H // cstdlib includes #include #include // necessary for int type sizes #include #include // TODO(dledda): 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; // ### 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])) // ### Arenas ### struct Arena { void *memory; size_t capacity; size_t head; }; struct Scratch { Arena *arena; size_t start; }; void *pushSize(Arena *arena, size_t bytes); Arena *arenaAlloc(size_t capacity); void arenaFree(Arena *arena); void arenaFreeFrom(Arena *arena, size_t pos); void initialiseCore(); Scratch scratchStart(Arena **conflicts, size_t conflictCount); void scratchEnd(Scratch scratch); #define PushArray(arena, type, size) (type *)pushSize(arena, sizeof(type) * (size)) #define PushStruct(arena, type) (type *)pushSize(arena, sizeof(type)) // ### Vectors ### template union Vector2 { struct { T x; T y; }; T vec[2]; }; template inline function Vector2 vec2(T x, T y) { Vector2 result = {0}; result.x = x; result.y = y; return result; } template union Vector3 { struct { T x; T y; T z; }; T vec[3]; }; template inline function Vector3 vec3(T x, T y, T z) { Vector3 result = {0}; result.x = x; result.y = y; result.z = z; return result; } template union Vector4 { struct { T x; T y; T z; T w; }; T vec[4]; }; template inline function Vector4 vec4(T x, T y, T z, T w) { Vector4 result = {0}; result.x = x; result.y = y; result.z = z; result.w = w; return result; } // ### Lists ### template struct list { T* data; size_t length; size_t head; }; #define PushList(arena, type, size) (list{ PushArray(arena, type, size), size, 0 }) #define PushFullList(arena, type, size) (list{ PushArray(arena, type, size), size, size }) template T *appendList(list *list, T element); template void zeroList(list *list); template void zeroListFull(list *list); template list listSlice(list l, size_t start, size_t stop = 0); // ### 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 strlit(lit) (string{(char *)(lit), sizeof(lit) - 1}) #define PushString(arena, length) (string{ (char *)pushSize(arena, length), (length) }) // C Strings const char *cstring(Arena *arena, list 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 stringContains(string str, char c); string strReverse(Arena *arena, string str); string strSlice(string str, size_t start, size_t stop = 0); string strSlice(char *data, size_t start, size_t stop = 0); list strSplit(Arena *arena, string splitStr, string inputStr); string strPrintfv(Arena *arena, const char *fmt, va_list args); string strPrintf(Arena *arena, const char *fmt, ...); int8 parsePositiveInt(string str, size_t *lengthPointer); real32 parsePositiveReal32(Arena *arena, string str, size_t *lengthPointer); inline function bool isNumeric(char c); // ### File IO ### string readEntireFile(Arena *arena, string filename); bool writeEntireFile(Arena *arena, string filename, const byte *contents, size_t contentsLength); bool fileAppend(Arena *arena, string filename, const byte *contents, size_t contentsLength); // ### Cmdline ### list getArgs(Arena *arena, int argc, char **argv); // ### Time ### typedef uint64 UnixTimestamp; typedef tm Timestamp; UnixTimestamp getSystemUnixTime(); Timestamp timestampFromUnixTime(UnixTimestamp *unixTimestamp); string formatTimeHms(Arena *arena, UnixTimestamp time); string formatTimeHms(Arena *arena, Timestamp *time); string formatTimeYmd(Arena *arena, UnixTimestamp time); string formatTimeYmd(Arena *arena, Timestamp *time); // ### Linked Lists ### // TODO(dledda): implement basic linked lists (based on arenas?) // ### Logging ### enum LogTarget { LogTarget_stdout, LogTarget_stdin, LogTarget_stderr, LogTarget_count, }; void log(list l, LogTarget target = LogTarget_stdout); void log(list l, LogTarget target = LogTarget_stdout); void log(const char *fmt, ...); void logError(const char *fmt, ...); // ### Loops ### #define EachIn(list, it) size_t it = 0; it < list.length; it++ #define EachInReversed(list, it) size_t it = list.length - 1; it >= 0 && it < list.length; it-- #define EachInArray(arr, it) size_t it = 0; it < ArrayCount(arr); ++it // ### Misc ### int intCompare(const void *a, const void *b); #endif