597 lines
28 KiB
C
597 lines
28 KiB
C
// NOTE: [$PRIN] Dqn_Print =========================================================================
|
|
enum Dqn_PrintStd
|
|
{
|
|
Dqn_PrintStd_Out,
|
|
Dqn_PrintStd_Err,
|
|
};
|
|
|
|
enum Dqn_PrintBold
|
|
{
|
|
Dqn_PrintBold_No,
|
|
Dqn_PrintBold_Yes,
|
|
};
|
|
|
|
struct Dqn_PrintStyle
|
|
{
|
|
Dqn_PrintBold bold;
|
|
bool colour;
|
|
uint8_t r, g, b;
|
|
};
|
|
|
|
enum Dqn_PrintESCColour
|
|
{
|
|
Dqn_PrintESCColour_Fg,
|
|
Dqn_PrintESCColour_Bg,
|
|
};
|
|
|
|
// NOTE: Print Style ===============================================================================
|
|
DQN_API Dqn_PrintStyle Dqn_Print_StyleColour (uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold);
|
|
DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32 (uint32_t rgb, Dqn_PrintBold bold);
|
|
DQN_API Dqn_PrintStyle Dqn_Print_StyleBold ();
|
|
|
|
// NOTE: Print Standard Out ========================================================================
|
|
#define Dqn_Print(string) Dqn_Print_Std(Dqn_PrintStd_Out, string)
|
|
#define Dqn_Print_F(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__)
|
|
#define Dqn_Print_FV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Out, fmt, args)
|
|
|
|
#define Dqn_Print_Style(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Out, style, string)
|
|
#define Dqn_Print_FStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__)
|
|
#define Dqn_Print_FVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Out, style, fmt, args)
|
|
|
|
#define Dqn_Print_Ln(string) Dqn_Print_StdLn(Dqn_PrintStd_Out, string)
|
|
#define Dqn_Print_LnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__)
|
|
#define Dqn_Print_LnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Out, fmt, args)
|
|
|
|
#define Dqn_Print_LnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Out, style, string);
|
|
#define Dqn_Print_LnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__);
|
|
#define Dqn_Print_LnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Out, style, fmt, args);
|
|
|
|
// NOTE: Print =====================================================================================
|
|
DQN_API void Dqn_Print_Std (Dqn_PrintStd std_handle, Dqn_String8 string);
|
|
DQN_API void Dqn_Print_StdF (Dqn_PrintStd std_handle, char const *fmt, ...);
|
|
DQN_API void Dqn_Print_StdFV (Dqn_PrintStd std_handle, char const *fmt, va_list args);
|
|
|
|
DQN_API void Dqn_Print_StdStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string);
|
|
DQN_API void Dqn_Print_StdFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, char const *fmt, ...);
|
|
DQN_API void Dqn_Print_StdFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, char const *fmt, va_list args);
|
|
|
|
DQN_API void Dqn_Print_StdLn (Dqn_PrintStd std_handle, Dqn_String8 string);
|
|
DQN_API void Dqn_Print_StdLnF (Dqn_PrintStd std_handle, char const *fmt, ...);
|
|
DQN_API void Dqn_Print_StdLnFV (Dqn_PrintStd std_handle, char const *fmt, va_list args);
|
|
|
|
DQN_API void Dqn_Print_StdLnStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string);
|
|
DQN_API void Dqn_Print_StdLnFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, char const *fmt, ...);
|
|
DQN_API void Dqn_Print_StdLnFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, char const *fmt, va_list args);
|
|
|
|
// NOTE: ANSI Formatting Codes =====================================================================
|
|
Dqn_String8 Dqn_Print_ESCColourString (Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b);
|
|
Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint32_t value);
|
|
|
|
#define Dqn_Print_ESCColourFgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b)
|
|
#define Dqn_Print_ESCColourBgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b)
|
|
#define Dqn_Print_ESCColourFg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b).data
|
|
#define Dqn_Print_ESCColourBg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b).data
|
|
|
|
#define Dqn_Print_ESCColourFgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value)
|
|
#define Dqn_Print_ESCColourBgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value)
|
|
#define Dqn_Print_ESCColourFgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value).data
|
|
#define Dqn_Print_ESCColourBgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value).data
|
|
|
|
#define Dqn_Print_ESCReset "\x1b[0m"
|
|
#define Dqn_Print_ESCBold "\x1b[1m"
|
|
#define Dqn_Print_ESCResetString DQN_STRING8(Dqn_Print_ESCReset)
|
|
#define Dqn_Print_ESCBoldString DQN_STRING8(Dqn_Print_ESCBold)
|
|
|
|
#if !defined(DQN_NO_FS)
|
|
#if defined(DQN_OS_WIN32) && defined(DQN_NO_WIN)
|
|
#error "Filesystem APIs requires Windows API, DQN_NO_WIN must not be defined"
|
|
#endif
|
|
// NOTE: [$FSYS] Dqn_Fs ============================================================================
|
|
// NOTE: FS Manipulation =======================================================
|
|
// TODO(dqn): We should have a Dqn_String8 interface and a CString interface
|
|
//
|
|
// NOTE: API ===================================================================
|
|
// @proc Dqn_FsDelete
|
|
// @desc Delete the item specified at the path. This function *CAN* not delete directories unless
|
|
// the directory is empty.
|
|
// @return True if deletion was successful, false otherwise
|
|
|
|
enum Dqn_FsInfoType
|
|
{
|
|
Dqn_FsInfoType_Unknown,
|
|
Dqn_FsInfoType_Directory,
|
|
Dqn_FsInfoType_File,
|
|
};
|
|
|
|
struct Dqn_FsInfo
|
|
{
|
|
bool exists;
|
|
Dqn_FsInfoType type;
|
|
uint64_t create_time_in_s;
|
|
uint64_t last_write_time_in_s;
|
|
uint64_t last_access_time_in_s;
|
|
uint64_t size;
|
|
};
|
|
|
|
DQN_API bool Dqn_Fs_Exists (Dqn_String8 path);
|
|
DQN_API bool Dqn_Fs_DirExists(Dqn_String8 path);
|
|
DQN_API Dqn_FsInfo Dqn_Fs_GetInfo (Dqn_String8 path);
|
|
DQN_API bool Dqn_Fs_Copy (Dqn_String8 src, Dqn_String8 dest, bool overwrite);
|
|
DQN_API bool Dqn_Fs_MakeDir (Dqn_String8 path);
|
|
DQN_API bool Dqn_Fs_Move (Dqn_String8 src, Dqn_String8 dest, bool overwrite);
|
|
DQN_API bool Dqn_Fs_Delete (Dqn_String8 path);
|
|
|
|
// NOTE: R/W Entire File ===========================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Fs_WriteString8, Dqn_Fs_WriteCString8
|
|
// @desc Write the string to a file at the path overwriting if necessary.
|
|
|
|
// @proc Dqn_Fs_ReadString8, Dqn_Fs_ReadCString8
|
|
// @desc Read the file at the path to a string.
|
|
|
|
DQN_API bool Dqn_Fs_WriteCString8(char const *file_path, Dqn_usize file_path_size, char const *buffer, Dqn_usize buffer_size);
|
|
DQN_API bool Dqn_Fs_Write (Dqn_String8 file_path, Dqn_String8 buffer);
|
|
DQN_API char *Dqn_Fs_ReadCString8 (char const *path, Dqn_usize path_size, Dqn_usize *file_size, Dqn_Allocator allocator);
|
|
DQN_API Dqn_String8 Dqn_Fs_Read (Dqn_String8 path, Dqn_Allocator allocator);
|
|
|
|
// NOTE: R/W Stream API ============================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Fs_OpenFile
|
|
// @desc Open a handle to the file
|
|
|
|
// @proc Dqn_Fs_WriteFile
|
|
// @desc Append to the file specified by the handle with the given buffer.
|
|
|
|
// @proc Dqn_Fs_CloseFile
|
|
// @desc Close the file at specified by the handle
|
|
|
|
struct Dqn_FsFile
|
|
{
|
|
void *handle;
|
|
char error[512];
|
|
uint16_t error_size;
|
|
};
|
|
|
|
enum Dqn_FsFileOpen
|
|
{
|
|
Dqn_FsFileOpen_CreateAlways, ///< Create file if it does not exist, otherwise, zero out the file and open
|
|
Dqn_FsFileOpen_OpenIfExist, ///< Open file at path only if it exists
|
|
Dqn_FsFileOpen_OpenAlways, ///< Open file at path, create file if it does not exist
|
|
};
|
|
|
|
enum Dqn_FsFileAccess
|
|
{
|
|
Dqn_FsFileAccess_Read = 1 << 0,
|
|
Dqn_FsFileAccess_Write = 1 << 1,
|
|
Dqn_FsFileAccess_Execute = 1 << 2,
|
|
Dqn_FsFileAccess_AppendOnly = 1 << 3, ///< This flag cannot be combined with any other acess mode
|
|
Dqn_FsFileAccess_ReadWrite = Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write,
|
|
Dqn_FsFileAccess_All = Dqn_FsFileAccess_ReadWrite | Dqn_FsFileAccess_Execute,
|
|
};
|
|
|
|
DQN_API Dqn_FsFile Dqn_Fs_OpenFile (Dqn_String8 path, Dqn_FsFileOpen open_mode, uint32_t access);
|
|
DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize size);
|
|
DQN_API void Dqn_Fs_CloseFile(Dqn_FsFile *file);
|
|
#endif // !defined(DQN_NO_FS)
|
|
|
|
// NOTE: File system paths =========================================================================
|
|
// Helper data structure for building paths suitable for OS consumption.
|
|
//
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_FsPath_AddRef, Dqn_FsPath_Add
|
|
// @desc Append a path to the file path. The passed in path can be specify
|
|
// both a single level or multiple directories with different path separators.
|
|
// The path will be decomposed into individual sections in the function.
|
|
//
|
|
// For example passing
|
|
// - "path/to/your/desired/folder" is valid
|
|
// - "path" is valid
|
|
// - "path/to\your/desired\folder" is valid
|
|
|
|
// @proc Dqn_FsPath_Pop
|
|
// @desc Remove the last appended path level from the current path stored in
|
|
// the FsPath.
|
|
//
|
|
// For example "path/to/your/desired/folder" popped produces
|
|
// "path/to/your/desired"
|
|
|
|
// @proc Dqn_FsPath_Convert
|
|
// @desc Convert the path specified in the string to the OS native separated
|
|
// path.
|
|
|
|
#if !defined(Dqn_FsPathOSSeperator)
|
|
#if defined(DQN_OS_WIN32)
|
|
#define Dqn_FsPathOSSeperator "\\"
|
|
#else
|
|
#define Dqn_FsPathOSSeperator "/"
|
|
#endif
|
|
#define Dqn_FsPathOSSeperatorString DQN_STRING8(Dqn_FsPathOSSeperator)
|
|
#endif
|
|
|
|
struct Dqn_FsPathLink
|
|
{
|
|
Dqn_String8 string;
|
|
Dqn_FsPathLink *next;
|
|
Dqn_FsPathLink *prev;
|
|
};
|
|
|
|
struct Dqn_FsPath
|
|
{
|
|
Dqn_FsPathLink *head;
|
|
Dqn_FsPathLink *tail;
|
|
Dqn_usize string_size;
|
|
uint16_t links_size;
|
|
};
|
|
|
|
DQN_API bool Dqn_FsPath_AddRef (Dqn_Arena *arena, Dqn_FsPath *fs_path, Dqn_String8 path);
|
|
DQN_API bool Dqn_FsPath_Add (Dqn_Arena *arena, Dqn_FsPath *fs_path, Dqn_String8 path);
|
|
DQN_API bool Dqn_FsPath_AddF (Dqn_Arena *arena, Dqn_FsPath *fs_path, char const *fmt, ...);
|
|
DQN_API bool Dqn_FsPath_Pop (Dqn_FsPath *fs_path);
|
|
DQN_API Dqn_String8 Dqn_FsPath_BuildWithSeparator(Dqn_Arena *arena, Dqn_FsPath const *fs_path, Dqn_String8 path_separator);
|
|
DQN_API Dqn_String8 Dqn_FsPath_Convert (Dqn_Arena *arena, Dqn_String8 path);
|
|
DQN_API Dqn_String8 Dqn_FsPath_ConvertF (Dqn_Arena *arena, char const *fmt, ...);
|
|
#define Dqn_FsPath_BuildFwdSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("/"))
|
|
#define Dqn_FsPath_BuildBackSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("\\"))
|
|
|
|
#if !defined(Dqn_FsPath_Build)
|
|
#if defined(DQN_OS_WIN32)
|
|
#define Dqn_FsPath_Build(arena, fs_path) Dqn_FsPath_BuildBackSlash(arena, fs_path)
|
|
#else
|
|
#define Dqn_FsPath_Build(arena, fs_path) Dqn_FsPath_BuildFwdSlash(arena, fs_path)
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: [$DATE] Dqn_Date ==========================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Date_EpochTime
|
|
// @desc Produce the time elapsed since the Unix epoch
|
|
// (e.g. 1970-01-01T00:00:00Z) in seconds
|
|
|
|
struct Dqn_DateHMSTimeString
|
|
{
|
|
char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")];
|
|
uint8_t date_size;
|
|
|
|
char hms[DQN_ARRAY_UCOUNT("HH:MM:SS")];
|
|
uint8_t hms_size;
|
|
};
|
|
|
|
struct Dqn_DateHMSTime
|
|
{
|
|
uint8_t day;
|
|
uint8_t month;
|
|
int16_t year;
|
|
|
|
uint8_t hour;
|
|
uint8_t minutes;
|
|
uint8_t seconds;
|
|
};
|
|
|
|
DQN_API Dqn_DateHMSTime Dqn_Date_HMSLocalTimeNow ();
|
|
DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeStringNow(char date_separator = '-', char hms_separator = ':');
|
|
DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeString (Dqn_DateHMSTime time, char date_separator = '-', char hms_separator = ':');
|
|
DQN_API uint64_t Dqn_Date_EpochTime ();
|
|
|
|
#if defined(DQN_OS_WIN32)
|
|
#if !defined(DQN_NO_WIN)
|
|
// NOTE: [$WIND] Dqn_Win ===========================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Win_LastErrorToBuffer, Dqn_Win_LastError
|
|
// @desc Retrieve the latest error code and message Windows produced for the
|
|
// most recent Win32 API call.
|
|
|
|
// @proc Dqn_Win_MakeProcessDPIAware
|
|
// @desc Call once at application start-up to ensure that the application is
|
|
// DPI aware on Windows and ensure that application UI is scaled up
|
|
// appropriately for the monitor.
|
|
|
|
struct Dqn_WinErrorMsg
|
|
{
|
|
unsigned long code;
|
|
char data[DQN_KILOBYTES(64) - 1]; // Maximum error size
|
|
unsigned long size;
|
|
};
|
|
DQN_API void Dqn_Win_LastErrorToBuffer(Dqn_WinErrorMsg *msg);
|
|
DQN_API Dqn_WinErrorMsg Dqn_Win_LastError();
|
|
DQN_API void Dqn_Win_MakeProcessDPIAware();
|
|
|
|
// NOTE: Windows String8 <-> String16 ===========================================
|
|
// Convert a UTF8 <-> UTF16 string.
|
|
//
|
|
// The exact size buffer required for this function can be determined by
|
|
// calling this function with the 'dest' set to null and 'dest_size' set to 0,
|
|
// the return size is the size required for conversion not-including space for
|
|
// the null-terminator. This function *always* null-terminates the input
|
|
// buffer.
|
|
//
|
|
// Returns the number of u8's (for UTF16->8) OR u16's (for UTF8->16)
|
|
// written/required for conversion. 0 if there was a conversion error and can be
|
|
// queried using 'Dqn_Win_LastError'
|
|
|
|
DQN_API int Dqn_Win_CString8ToCString16 (char const *src, int src_size, wchar_t *dest, int dest_size);
|
|
DQN_API int Dqn_Win_String8ToCString16 (Dqn_String8 src, wchar_t *dest, int dest_size);
|
|
DQN_API Dqn_String16 Dqn_Win_String8ToString16Allocator (Dqn_String8 src, Dqn_Allocator allocator);
|
|
|
|
DQN_API int Dqn_Win_CString16ToCString8 (wchar_t const *src, int src_size, char *dest, int dest_size);
|
|
DQN_API Dqn_String8 Dqn_Win_CString16ToString8Allocator(wchar_t const *src, int src_size, Dqn_Allocator allocator);
|
|
DQN_API int Dqn_Win_String16ToCString8 (Dqn_String16 src, char *dest, int dest_size);
|
|
DQN_API Dqn_String8 Dqn_Win_String16ToString8Allocator (Dqn_String16 src, Dqn_Allocator allocator);
|
|
|
|
// NOTE: Path navigatoin ===========================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Win_EXEDirW, Dqn_Win_EXEDirWArena
|
|
// @desc Evaluate the current executable's directory that is running when this
|
|
// function is called.
|
|
// @param[out] buffer The buffer to write the executable directory into. Set
|
|
// this to null to calculate the required buffer size for the directory.
|
|
// @param[in] size The size of the buffer given. Set this to 0 to calculate the
|
|
// required buffer size for the directory.
|
|
// @return The length of the executable directory string. If this return value
|
|
// exceeds the capacity of the 'buffer', the 'buffer' is untouched.
|
|
|
|
// @proc Dqn_Win_WorkingDir, Dqn_Win_WorkingDirW
|
|
// @param[in] suffix (Optional) A suffix to append to the current working directory
|
|
|
|
// @proc Dqn_Win_FolderIterate, Dqn_Win_FolderWIterate
|
|
// @desc Iterate the files in the specified folder at the path
|
|
#if 0
|
|
for (Dqn_WinFolderIterator it = {}; Dqn_Win_FolderIterate("C:/your/path/", &it); ) {
|
|
printf("%.*s\n", DQN_STRING_FMT(it.file_name));
|
|
}
|
|
#endif
|
|
|
|
struct Dqn_Win_FolderIteratorW
|
|
{
|
|
void *handle;
|
|
Dqn_String16 file_name;
|
|
wchar_t file_name_buf[512];
|
|
};
|
|
|
|
struct Dqn_Win_FolderIterator
|
|
{
|
|
void *handle;
|
|
Dqn_String8 file_name;
|
|
char file_name_buf[512];
|
|
};
|
|
|
|
DQN_API Dqn_usize Dqn_Win_EXEDirW (wchar_t *buffer, Dqn_usize size);
|
|
DQN_API Dqn_String16 Dqn_Win_EXEDirWArena (Dqn_Arena *arena);
|
|
DQN_API Dqn_String8 Dqn_Win_WorkingDir (Dqn_Allocator allocator, Dqn_String8 suffix);
|
|
DQN_API Dqn_String16 Dqn_Win_WorkingDirW (Dqn_Allocator allocator, Dqn_String16 suffix);
|
|
DQN_API bool Dqn_Win_FolderIterate (Dqn_String8 path, Dqn_Win_FolderIterator *it);
|
|
DQN_API bool Dqn_Win_FolderWIterate(Dqn_String16 path, Dqn_Win_FolderIteratorW *it);
|
|
#endif // !defined(DQN_NO_WIN)
|
|
|
|
#if !defined(DQN_NO_WINNET)
|
|
// NOTE: [$WINN] Dqn_WinNet ========================================================================
|
|
// TODO(dqn): Useful options to expose in the handle
|
|
// https://docs.microsoft.com/en-us/windows/win32/wininet/option-flags
|
|
// INTERNET_OPTION_CONNECT_RETRIES -- default is 5 retries
|
|
// INTERNET_OPTION_CONNECT_TIMEOUT -- milliseconds
|
|
// INTERNET_OPTION_RECEIVE_TIMEOUT
|
|
// INTERNET_OPTION_SEND_TIMEOUT
|
|
//
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_Win_NetHandleInitHTTPMethod, Dqn_Win_NetHandleInitHTTPMethodCString
|
|
// @desc Setup a handle to the URL with the given HTTP verb.
|
|
//
|
|
// This function is the same as calling Dqn_Win_NetHandleInit() followed by
|
|
// Dqn_Win_NetHandleSetHTTPMethod().
|
|
//
|
|
// @param http_method The HTTP request type, e.g. "GET" or "POST" e.t.c
|
|
|
|
// @proc Dqn_Win_NetHandleSetHTTPMethod
|
|
// @desc Set the HTTP request method for the given handle. This function can
|
|
// be used on a pre-existing valid handle that has at the minimum been
|
|
// initialised.
|
|
|
|
enum Dqn_WinNetHandleState
|
|
{
|
|
Dqn_WinNetHandleState_Invalid,
|
|
Dqn_WinNetHandleState_Initialised,
|
|
Dqn_WinNetHandleState_HttpMethodReady,
|
|
Dqn_WinNetHandleState_RequestFailed,
|
|
Dqn_WinNetHandleState_RequestGood,
|
|
};
|
|
|
|
// The number of bytes each pump of the connection downloads at most. If this is
|
|
// zero we default to DQN_WIN_NET_HANDLE_DOWNLOAD_SIZE.
|
|
#if !defined(DQN_WIN_NET_HANDLE_DOWNLOAD_SIZE)
|
|
#define DQN_WIN_NET_HANDLE_DOWNLOAD_SIZE 4096
|
|
#endif
|
|
|
|
struct Dqn_WinNetHandle
|
|
{
|
|
// NOTE: We copy out the host name because it needs to be null-terminated.
|
|
// Luckily, we can assume a DNS domain won't exceed 256 characters so this
|
|
// will generally always work.
|
|
char host_name[256];
|
|
int host_name_size;
|
|
|
|
// NOTE: Everything after the domain/host name part of the string i.e. the
|
|
// '/test' part of the full url 'mywebsite.com/test'.
|
|
// TODO(dqn): I don't want to make our network API allocate here so we don't
|
|
// copy the string since we require that the string is null-terminated so
|
|
// then taking a pointer to the input string should work .. maybe this is
|
|
// ok?
|
|
char *url;
|
|
int url_size;
|
|
|
|
// NOTE: docs.microsoft.com/en-us/windows/win32/wininet/setting-and-retrieving-internet-options#scope-of-hinternet-handle
|
|
// These handles have three levels:
|
|
//
|
|
// The root HINTERNET handle (created by a call to InternetOpen) would contain all the Internet options that affect this instance of WinINet.
|
|
// HINTERNET handles that connect to a server (created by a call to InternetConnect)
|
|
// HINTERNET handles associated with a resource or enumeration of resources on a particular server.
|
|
//
|
|
// More detailed information about the HINTERNET dependency is listed here
|
|
// NOTE: https://docs.microsoft.com/en-us/windows/win32/wininet/appendix-a-hinternet-handles
|
|
void *internet_open_handle;
|
|
void *internet_connect_handle;
|
|
void *http_handle;
|
|
Dqn_WinNetHandleState state;
|
|
};
|
|
|
|
enum Dqn_WinNetHandleRequestHeaderFlag
|
|
{
|
|
Dqn_WinNetHandleRequestHeaderFlag_Add,
|
|
Dqn_WinNetHandleRequestHeaderFlag_AddIfNew,
|
|
Dqn_WinNetHandleRequestHeaderFlag_Replace,
|
|
Dqn_WinNetHandleRequestHeaderFlag_Count,
|
|
};
|
|
|
|
struct Dqn_WinNetHandleResponse
|
|
{
|
|
Dqn_String8 raw_headers;
|
|
Dqn_String8 *headers;
|
|
Dqn_usize headers_size;
|
|
|
|
// NOTE: Headers pulled from the 'raw_headers' for convenience
|
|
uint64_t content_length;
|
|
Dqn_String8 content_type;
|
|
};
|
|
|
|
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitCString (char const *url, int url_size);
|
|
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInit (Dqn_String8 url);
|
|
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethodCString (char const *url, int url_size, char const *http_method);
|
|
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethod (Dqn_String8 url, Dqn_String8 http_method);
|
|
DQN_API void Dqn_Win_NetHandleClose (Dqn_WinNetHandle *handle);
|
|
DQN_API bool Dqn_Win_NetHandleIsValid (Dqn_WinNetHandle const *handle);
|
|
DQN_API void Dqn_Win_NetHandleSetUserAgentCString (Dqn_WinNetHandle *handle, char const *user_agent, int user_agent_size);
|
|
DQN_API bool Dqn_Win_NetHandleSetHTTPMethod (Dqn_WinNetHandle *handle, char const *method);
|
|
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderCString8(Dqn_WinNetHandle *handle, char const *header, int header_size, uint32_t mode);
|
|
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderString8 (Dqn_WinNetHandle *handle, Dqn_String8 header, uint32_t mode);
|
|
DQN_API Dqn_WinNetHandleResponse Dqn_Win_NetHandleSendRequest (Dqn_WinNetHandle *handle, Dqn_Allocator allocator, char const *post_data, unsigned long post_data_size);
|
|
DQN_API bool Dqn_Win_NetHandlePump (Dqn_WinNetHandle *handle, char *dest, int dest_size, size_t *download_size);
|
|
DQN_API char * Dqn_Win_NetHandlePumpCString8 (Dqn_WinNetHandle *handle, Dqn_Arena *arena, size_t *download_size);
|
|
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpString8 (Dqn_WinNetHandle *handle, Dqn_Arena *arena);
|
|
DQN_API void Dqn_Win_NetHandlePumpToCRTFile (Dqn_WinNetHandle *handle, FILE *file);
|
|
DQN_API char * Dqn_Win_NetHandlePumpToAllocCString (Dqn_WinNetHandle *handle, size_t *download_size);
|
|
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpToAllocString (Dqn_WinNetHandle *handle);
|
|
#endif // !defined(DQN_NO_WINNET)
|
|
#endif // defined(DQN_OS_WIN32)
|
|
|
|
// NOTE: [$OSYS] Dqn_OS ============================================================================
|
|
// NOTE: API =======================================================================================
|
|
// @proc Dqn_OS_SecureRNGBytes
|
|
// @desc Generate cryptographically secure bytes
|
|
|
|
// @proc Dqn_OS_EXEDir
|
|
// @desc Retrieve the executable directory without the trailing '/' or
|
|
// ('\' for windows). If this fails an empty string is returned.
|
|
|
|
// @proc Dqn_OS_PerfCounterFrequency
|
|
// @desc Get the number of ticks in the performance counter per second for the
|
|
// operating system you're running on. This value can be used to calculate
|
|
// duration from OS performance counter ticks.
|
|
|
|
// @proc Dqn_OS_EstimateTSCPerSecond
|
|
// @desc Estimate how many timestamp count's (TSC) there are per second. TSC
|
|
// is evaluated by calling __rdtsc() or the equivalent on the platform. This
|
|
// value can be used to convert TSC durations into seconds.
|
|
//
|
|
// @param duration_ms_to_gauge_tsc_frequency How many milliseconds to spend
|
|
// measuring the TSC rate of the current machine. 100ms is sufficient to
|
|
// produce a fairly accurate result with minimal blocking in applications.
|
|
|
|
/// Record time between two time-points using the OS's performance counter.
|
|
struct Dqn_OSTimer
|
|
{
|
|
uint64_t start;
|
|
uint64_t end;
|
|
};
|
|
|
|
DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint32_t size);
|
|
#if (defined(DQN_OS_WIN32) && !defined(DQN_NO_WIN)) || !defined(DQN_OS_WIN32)
|
|
DQN_API Dqn_String8 Dqn_OS_EXEDir (Dqn_Allocator allocator);
|
|
#endif
|
|
DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds);
|
|
DQN_API uint64_t Dqn_OS_PerfCounterNow ();
|
|
DQN_API uint64_t Dqn_OS_PerfCounterFrequency();
|
|
DQN_API Dqn_f64 Dqn_OS_PerfCounterS (uint64_t begin, uint64_t end);
|
|
DQN_API Dqn_f64 Dqn_OS_PerfCounterMs (uint64_t begin, uint64_t end);
|
|
DQN_API Dqn_f64 Dqn_OS_PerfCounterMicroS (uint64_t begin, uint64_t end);
|
|
DQN_API Dqn_f64 Dqn_OS_PerfCounterNs (uint64_t begin, uint64_t end);
|
|
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin ();
|
|
DQN_API void Dqn_OS_TimerEnd (Dqn_OSTimer *timer);
|
|
DQN_API Dqn_f64 Dqn_OS_TimerS (Dqn_OSTimer timer);
|
|
DQN_API Dqn_f64 Dqn_OS_TimerMs (Dqn_OSTimer timer);
|
|
DQN_API Dqn_f64 Dqn_OS_TimerMicroS (Dqn_OSTimer timer);
|
|
DQN_API Dqn_f64 Dqn_OS_TimerNs (Dqn_OSTimer timer);
|
|
DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency);
|
|
|
|
// NOTE: [$TCTX] Dqn_ThreadContext =================================================================
|
|
// Each thread is assigned in their thread-local storage (TLS) scratch and
|
|
// permanent arena allocators. These can be used for allocations with a lifetime
|
|
// scoped to the lexical scope or for storing data permanently using the arena
|
|
// paradigm.
|
|
//
|
|
// TLS in this implementation is implemented using the `thread_local` C/C++
|
|
// keyword.
|
|
//
|
|
// NOTE: API
|
|
//
|
|
// @proc Dqn_Thread_GetContext
|
|
// @desc Get the current thread's context- this contains all the metadata for managing
|
|
// the thread scratch data. In general you probably want Dqn_Thread_GetScratch()
|
|
// which ensures you get a usable scratch arena for temporary allocations
|
|
// without having to worry about selecting the right arena from the state.
|
|
//
|
|
// @proc Dqn_Thread_GetScratch
|
|
// @desc Retrieve the per-thread temporary arena allocator that is reset on scope
|
|
// exit.
|
|
//
|
|
// The scratch arena must be deconflicted with any existing arenas in the
|
|
// function to avoid trampling over each other's memory. Consider the situation
|
|
// where the scratch arena is passed into the function. Inside the function, if
|
|
// the same arena is reused then, if both arenas allocate, when the inner arena
|
|
// is reset, this will undo the passed in arena's allocations in the function.
|
|
//
|
|
// @param[in] conflict_arena A pointer to the arena currently being used in the
|
|
// function
|
|
|
|
#if !defined(DQN_THREAD_CONTEXT_ARENAS)
|
|
#define DQN_THREAD_CONTEXT_ARENAS 2
|
|
#endif
|
|
|
|
struct Dqn_ThreadContext
|
|
{
|
|
Dqn_b32 init;
|
|
|
|
Dqn_Arena *arena; ///< Per thread arena
|
|
Dqn_Allocator allocator; ///< Allocator that uses the arena
|
|
|
|
/// Temp memory arena's for the calling thread
|
|
Dqn_Arena *temp_arenas[DQN_THREAD_CONTEXT_ARENAS];
|
|
|
|
/// Allocators that use the corresponding arena from the thread context.
|
|
/// Provided for convenience when interfacing with allocator interfaces.
|
|
Dqn_Allocator temp_allocators[DQN_THREAD_CONTEXT_ARENAS];
|
|
|
|
#if defined(DQN_DEBUG_THREAD_CONTEXT)
|
|
Dqn_ArenaStat temp_arenas_stat[DQN_THREAD_CONTEXT_ARENAS];
|
|
#endif
|
|
};
|
|
|
|
struct Dqn_ThreadScratch
|
|
{
|
|
Dqn_ThreadScratch(Dqn_ThreadContext *context, uint8_t context_index);
|
|
~Dqn_ThreadScratch();
|
|
|
|
/// Index into the arena/allocator/stat array in the thread context
|
|
/// specifying what arena was assigned.
|
|
uint8_t index;
|
|
Dqn_Allocator allocator;
|
|
Dqn_Arena *arena;
|
|
Dqn_b32 destructed = false; /// Detect copies of the scratch
|
|
Dqn_ArenaTempMemory temp_memory;
|
|
#if defined(DQN_LEAK_TRACING)
|
|
Dqn_CallSite leak_site__;
|
|
#endif
|
|
};
|
|
|
|
// NOTE: Context ===================================================================================
|
|
DQN_API uint32_t Dqn_Thread_GetID();
|
|
DQN_API Dqn_ThreadContext *Dqn_Thread_GetContext();
|
|
DQN_API Dqn_ThreadScratch Dqn_Thread_GetScratch(void const *conflict_arena);
|