|
@@ -1,6 +1,9 @@ |
|
|
|
|
|
#include <unistd.h> // TODO(djledda): get outta here |
|
|
|
|
|
#include <math.h> |
|
|
|
|
|
#include <string.h> |
|
|
#define STB_SPRINTF_IMPLEMENTATION |
|
|
#define STB_SPRINTF_IMPLEMENTATION |
|
|
#include "core.h" |
|
|
#include "core.h" |
|
|
#include "os.h" |
|
|
|
|
|
|
|
|
#include "os.cpp" |
|
|
|
|
|
|
|
|
void *pushSize(Arena *arena, size_t bytes) { |
|
|
void *pushSize(Arena *arena, size_t bytes) { |
|
|
if (arena->capacity - arena->head >= bytes) { |
|
|
if (arena->capacity - arena->head >= bytes) { |
|
@@ -20,13 +23,7 @@ Arena *arenaAlloc(size_t capacity) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void arenaFree(Arena *arena) { |
|
|
void arenaFree(Arena *arena) { |
|
|
os_free(arena); |
|
|
|
|
|
#if OS_WINDOWS |
|
|
|
|
|
VirtualFree(arena, NULL, MEM_RELEASE); |
|
|
|
|
|
#elif OS_LINUX |
|
|
|
|
|
// TODO(dledda): implement this for Linux |
|
|
|
|
|
Assert(false); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
os_free(arena, arena->capacity); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void arenaFreeFrom(Arena *arena, size_t position) { |
|
|
void arenaFreeFrom(Arena *arena, size_t position) { |
|
@@ -60,6 +57,9 @@ Scratch scratchStart(Arena **conflicts, size_t conflictCount) { |
|
|
return scratch; |
|
|
return scratch; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define DeferLoop(begin_stmnt, end_stmnt) for(int __defer_i = ((begin_stmnt), 0); __defer_i < 1; (++__defer_i, (end_stmnt))) |
|
|
|
|
|
#define WithScratch(scratchName) Scratch scratchName; DeferLoop(scratchName = scratchStart(0, 0), scratchEnd(scratchName)) |
|
|
|
|
|
|
|
|
void scratchEnd(Scratch scratch) { |
|
|
void scratchEnd(Scratch scratch) { |
|
|
arenaFreeFrom(scratch.arena, scratch.start); |
|
|
arenaFreeFrom(scratch.arena, scratch.start); |
|
|
} |
|
|
} |
|
@@ -86,6 +86,13 @@ void zeroList(list<T> *list) { |
|
|
memset(list->data, 0, list->head * sizeof(T)); |
|
|
memset(list->data, 0, list->head * sizeof(T)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline string operator""_s(const char *cstrLiteral, unsigned long length) { |
|
|
|
|
|
return { |
|
|
|
|
|
(char *)cstrLiteral, |
|
|
|
|
|
length, |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const char *cstring(Arena *arena, list<char> buf) { |
|
|
const char *cstring(Arena *arena, list<char> buf) { |
|
|
char *arr = PushArray(arena, char, buf.length + 1); |
|
|
char *arr = PushArray(arena, char, buf.length + 1); |
|
|
memmove(arr, buf.data, buf.length); |
|
|
memmove(arr, buf.data, buf.length); |
|
@@ -166,7 +173,7 @@ list<T> listSlice(list<T> l, size_t start, size_t stop) { |
|
|
if (stop == 0) { |
|
|
if (stop == 0) { |
|
|
stop = l.head; |
|
|
stop = l.head; |
|
|
} |
|
|
} |
|
|
// TODO(dledda): maybe assert instead |
|
|
|
|
|
|
|
|
// TODO(djledda): maybe assert instead |
|
|
if (stop > l.head || start > stop) { |
|
|
if (stop > l.head || start > stop) { |
|
|
return {0}; |
|
|
return {0}; |
|
|
} |
|
|
} |
|
@@ -181,7 +188,7 @@ string strSlice(string str, size_t start, size_t stop) { |
|
|
if (stop == 0) { |
|
|
if (stop == 0) { |
|
|
stop = str.length; |
|
|
stop = str.length; |
|
|
} |
|
|
} |
|
|
// TODO(dledda): maybe assert instead |
|
|
|
|
|
|
|
|
// TODO(djledda): maybe assert instead |
|
|
if (stop > str.length || start > stop) { |
|
|
if (stop > str.length || start > stop) { |
|
|
return {0}; |
|
|
return {0}; |
|
|
} |
|
|
} |
|
@@ -207,9 +214,9 @@ bool stringContains(string str, char c) { |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const char NUMERIC_CHARS[] = "0123456789"; |
|
|
|
|
|
|
|
|
string NUMERIC_CHARS = "0123456789"_s; |
|
|
inline bool isNumeric(char c) { |
|
|
inline bool isNumeric(char c) { |
|
|
return stringContains(strlit(NUMERIC_CHARS), c); |
|
|
|
|
|
|
|
|
return stringContains(NUMERIC_CHARS, c); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
list<string> strSplit(Arena *arena, string splitStr, string inputStr) { |
|
|
list<string> strSplit(Arena *arena, string splitStr, string inputStr) { |
|
@@ -317,17 +324,16 @@ string readEntireFile(Arena *arena, string filename) { |
|
|
struct stat st; |
|
|
struct stat st; |
|
|
stat((char *)filename.str, &st); |
|
|
stat((char *)filename.str, &st); |
|
|
size_t fsize = st.st_size; |
|
|
size_t fsize = st.st_size; |
|
|
string readBuffer = PushString(arena, filesize); |
|
|
|
|
|
readBuffer.length = filesize; |
|
|
|
|
|
fread(readBuffer.str, sizeof(byte), filesize, input); |
|
|
|
|
|
|
|
|
string readBuffer = PushString(arena, fsize); |
|
|
|
|
|
fread(readBuffer.str, sizeof(byte), readBuffer.length, input); |
|
|
fclose(input); |
|
|
fclose(input); |
|
|
return readBuffer; |
|
|
return readBuffer; |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool writeEntireFile(Arena *arena, string filename, const byte *contents, size_t contentsLength) { |
|
|
bool writeEntireFile(Arena *arena, string filename, const byte *contents, size_t contentsLength) { |
|
|
#if OS_WINDOWS |
|
|
|
|
|
bool result = false; |
|
|
bool result = false; |
|
|
|
|
|
#if OS_WINDOWS |
|
|
HANDLE fileHandle = CreateFileA(cstring(arena, filename), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL); |
|
|
HANDLE fileHandle = CreateFileA(cstring(arena, filename), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL); |
|
|
if (fileHandle != INVALID_HANDLE_VALUE) { |
|
|
if (fileHandle != INVALID_HANDLE_VALUE) { |
|
|
DWORD bytesWritten; |
|
|
DWORD bytesWritten; |
|
@@ -337,15 +343,15 @@ bool writeEntireFile(Arena *arena, string filename, const byte *contents, size_t |
|
|
} |
|
|
} |
|
|
CloseHandle(fileHandle); |
|
|
CloseHandle(fileHandle); |
|
|
} |
|
|
} |
|
|
return result; |
|
|
|
|
|
#elif OS_LINUX |
|
|
#elif OS_LINUX |
|
|
Assert(false); |
|
|
Assert(false); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool fileAppend(Arena *arena, string filename, const byte *contents, size_t contentsLength) { |
|
|
bool fileAppend(Arena *arena, string filename, const byte *contents, size_t contentsLength) { |
|
|
#if OS_WINDOWS |
|
|
|
|
|
bool result = false; |
|
|
bool result = false; |
|
|
|
|
|
#if OS_WINDOWS |
|
|
HANDLE fileHandle = CreateFileA(cstring(arena, filename), FILE_APPEND_DATA | FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
|
|
HANDLE fileHandle = CreateFileA(cstring(arena, filename), FILE_APPEND_DATA | FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
|
|
if (fileHandle != INVALID_HANDLE_VALUE) { |
|
|
if (fileHandle != INVALID_HANDLE_VALUE) { |
|
|
DWORD bytesWritten; |
|
|
DWORD bytesWritten; |
|
@@ -356,10 +362,10 @@ bool fileAppend(Arena *arena, string filename, const byte *contents, size_t cont |
|
|
} |
|
|
} |
|
|
CloseHandle(fileHandle); |
|
|
CloseHandle(fileHandle); |
|
|
} |
|
|
} |
|
|
return result; |
|
|
|
|
|
#elif OS_LINUX |
|
|
#elif OS_LINUX |
|
|
Assert(false); |
|
|
Assert(false); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
list<string> getArgs(Arena *arena, int argc, char **argv) { |
|
|
list<string> getArgs(Arena *arena, int argc, char **argv) { |
|
@@ -382,7 +388,7 @@ Timestamp timestampFromUnixTime(UnixTimestamp *unixTimestamp) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
string formatTimeHms(Arena *arena, UnixTimestamp time) { |
|
|
string formatTimeHms(Arena *arena, UnixTimestamp time) { |
|
|
local_persist const string format = strlit("HH-MM-SS"); |
|
|
|
|
|
|
|
|
local_persist const string format = "HH-MM-SS"_s; |
|
|
string buf = PushString(arena, format.length); |
|
|
string buf = PushString(arena, format.length); |
|
|
tm *timestamp = gmtime((time_t *)&time); |
|
|
tm *timestamp = gmtime((time_t *)&time); |
|
|
strftime(buf.str, buf.length + 1, "%T", timestamp); |
|
|
strftime(buf.str, buf.length + 1, "%T", timestamp); |
|
@@ -390,14 +396,14 @@ string formatTimeHms(Arena *arena, UnixTimestamp time) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
string formatTimeHms(Arena *arena, Timestamp *time) { |
|
|
string formatTimeHms(Arena *arena, Timestamp *time) { |
|
|
local_persist const string format = strlit("HH-MM-SS"); |
|
|
|
|
|
|
|
|
local_persist const string format = "HH-MM-SS"_s; |
|
|
string buf = PushString(arena, format.length); |
|
|
string buf = PushString(arena, format.length); |
|
|
strftime(buf.str, buf.length + 1, "%T", (tm *)time); |
|
|
strftime(buf.str, buf.length + 1, "%T", (tm *)time); |
|
|
return buf; |
|
|
return buf; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
string formatTimeYmd(Arena *arena, UnixTimestamp time) { |
|
|
string formatTimeYmd(Arena *arena, UnixTimestamp time) { |
|
|
local_persist const string format = strlit("YYYY-mm-dd"); |
|
|
|
|
|
|
|
|
local_persist const string format = "YYYY-mm-dd"_s; |
|
|
string buf = PushString(arena, format.length); |
|
|
string buf = PushString(arena, format.length); |
|
|
tm *timestamp = gmtime((time_t *)&time); |
|
|
tm *timestamp = gmtime((time_t *)&time); |
|
|
strftime(buf.str, buf.length + 1, "%Y-%m-%d", timestamp); |
|
|
strftime(buf.str, buf.length + 1, "%Y-%m-%d", timestamp); |
|
@@ -405,7 +411,7 @@ string formatTimeYmd(Arena *arena, UnixTimestamp time) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
string formatTimeYmd(Arena *arena, Timestamp *time) { |
|
|
string formatTimeYmd(Arena *arena, Timestamp *time) { |
|
|
local_persist const string format = strlit("YYYY-mm-dd"); |
|
|
|
|
|
|
|
|
local_persist const string format = "YYYY-mm-dd"_s; |
|
|
string buf = PushString(arena, format.length); |
|
|
string buf = PushString(arena, format.length); |
|
|
strftime(buf.str, buf.length + 1, "%Y-%m-%d", (tm *)time); |
|
|
strftime(buf.str, buf.length + 1, "%Y-%m-%d", (tm *)time); |
|
|
return buf; |
|
|
return buf; |
|
@@ -433,8 +439,21 @@ function void __core_log(LogTarget target, const char *fmt, va_list argList) { |
|
|
} |
|
|
} |
|
|
WriteFile(stdHandle, result.str, (DWORD)result.length, &done, 0); |
|
|
WriteFile(stdHandle, result.str, (DWORD)result.length, &done, 0); |
|
|
#elif OS_LINUX |
|
|
#elif OS_LINUX |
|
|
// TODO(dledda): implementation |
|
|
|
|
|
Assert(false); |
|
|
|
|
|
|
|
|
// TODO(djledda): finish implementation without cstdlib |
|
|
|
|
|
switch (target) { |
|
|
|
|
|
case LogTarget_stdin: |
|
|
|
|
|
write(0, (const void *)result.str, result.length); |
|
|
|
|
|
break; |
|
|
|
|
|
case LogTarget_stderr: |
|
|
|
|
|
fflush(stderr); |
|
|
|
|
|
write(2, (const void *)result.str, result.length); |
|
|
|
|
|
break; |
|
|
|
|
|
case LogTarget_stdout: |
|
|
|
|
|
default: |
|
|
|
|
|
fflush(stdout); |
|
|
|
|
|
write(1, (const void *)result.str, result.length); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
scratchEnd(scratch); |
|
|
scratchEnd(scratch); |
|
|
} |
|
|
} |
|
|