More revising of the API from The Bar
This commit is contained in:
+76
-40
@@ -1,5 +1,8 @@
|
||||
#define DN_OS_CPP
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
|
||||
#if defined(DN_PLATFORM_POSIX)
|
||||
#include <sys/sysinfo.h> // get_nprocs
|
||||
#include <unistd.h> // getpagesize
|
||||
@@ -389,11 +392,9 @@ DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_fre
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
// NOTE: DN_OSPathInfo/File ////////////////////////////////////////////////////////////////////////
|
||||
DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against)
|
||||
DN_API bool DN_OS_PathIsOlderThan(DN_Str8 path, DN_Str8 check_against)
|
||||
{
|
||||
DN_OSPathInfo file_info = DN_OS_PathInfo(file);
|
||||
DN_OSPathInfo file_info = DN_OS_PathInfo(path);
|
||||
DN_OSPathInfo check_against_info = DN_OS_PathInfo(check_against);
|
||||
bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s;
|
||||
return result;
|
||||
@@ -445,44 +446,69 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: R/W Entire File ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str8 DN_OS_ReadAll(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *error)
|
||||
DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
// NOTE: Query file size + allocate buffer /////////////////////////////////////////////////////
|
||||
// NOTE: Query file size
|
||||
DN_Str8 result = {};
|
||||
DN_OSPathInfo path_info = DN_OS_PathInfo(path);
|
||||
if (!path_info.exists) {
|
||||
DN_OS_ErrSinkAppendF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path));
|
||||
DN_OS_ErrSinkAppendF(err, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path));
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena);
|
||||
result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No);
|
||||
if (!DN_Str8_HasData(result)) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 buffer_size_str8 = DN_CVT_BytesStr8FromU64AutoTLS(path_info.size);
|
||||
DN_OS_ErrSinkAppendF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(path));
|
||||
DN_Arena_TempMemEnd(temp_mem);
|
||||
result = {};
|
||||
// NOTE: Allocate
|
||||
DN_ArenaTempMem arena_tmp = {};
|
||||
if (alloc_type == DN_Allocator_Arena) {
|
||||
DN_Arena *arena = DN_CAST(DN_Arena *) allocator;
|
||||
arena_tmp = DN_Arena_TempMemBegin(arena);
|
||||
result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No);
|
||||
} else {
|
||||
DN_Pool *pool = DN_CAST(DN_Pool *) allocator;
|
||||
result = DN_Str8_AllocPool(pool, path_info.size);
|
||||
}
|
||||
|
||||
if (!result.data) {
|
||||
DN_CVTU64Bytes bytes_str = DN_CVT_BytesFromU64Auto(path_info.size);
|
||||
DN_OS_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.1f %.*s for reading file '%.*s'", bytes_str.bytes, DN_STR_FMT(bytes_str.suffix), DN_STR_FMT(path));
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Read the file from disk ///////////////////////////////////////////////////////////////
|
||||
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error);
|
||||
DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, error);
|
||||
// NOTE: Read all
|
||||
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, err);
|
||||
DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, err);
|
||||
if (file.error || !read.success) {
|
||||
DN_Arena_TempMemEnd(temp_mem);
|
||||
if (alloc_type == DN_Allocator_Arena) {
|
||||
DN_Arena_TempMemEnd(arena_tmp);
|
||||
} else {
|
||||
DN_Pool *pool = DN_CAST(DN_Pool *) allocator;
|
||||
DN_Pool_Dealloc(pool, result.data);
|
||||
}
|
||||
result = {};
|
||||
}
|
||||
DN_OS_FileClose(&file);
|
||||
|
||||
DN_OS_FileClose(&file);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error)
|
||||
DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err)
|
||||
{
|
||||
DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, arena, path, err);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err)
|
||||
{
|
||||
DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Pool, pool, path, err);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_OS_FileReadAllTLS(DN_Str8 path, DN_OSErrSink *err)
|
||||
{
|
||||
DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, DN_OS_TLSArena(), path, err);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error)
|
||||
{
|
||||
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error);
|
||||
bool result = DN_OS_FileWrite(&file, buffer, error);
|
||||
@@ -490,54 +516,52 @@ DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_WriteAll(file_path, buffer, error);
|
||||
DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_FileWriteAll(file_path, buffer, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = DN_OS_WriteAllFV(file_path, error, fmt, args);
|
||||
bool result = DN_OS_FileWriteAllFV(file_path, error, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error)
|
||||
DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 tmp_path = DN_Str8_FromF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path));
|
||||
if (!DN_OS_WriteAll(tmp_path, buffer, error))
|
||||
if (!DN_OS_FileWriteAll(tmp_path, buffer, error))
|
||||
return false;
|
||||
if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error))
|
||||
if (!DN_OS_FileCopy(tmp_path, path, true /*overwrite*/, error))
|
||||
return false;
|
||||
if (!DN_OS_PathDelete(tmp_path))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_WriteAllSafe(path, buffer, error);
|
||||
bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args);
|
||||
bool result = DN_OS_FileWriteAllSafeFV(path, error, fmt, args);
|
||||
return result;
|
||||
}
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
|
||||
// NOTE: DN_OSPath /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
if (!arena || !fs_path || !DN_Str8_HasData(path))
|
||||
@@ -581,6 +605,18 @@ DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
|
||||
return true;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathAddRefTLS(DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
bool result = DN_OS_PathAddRef(DN_OS_TLSTopArena(), fs_path, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathAddRefFrame(DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
bool result = DN_OS_PathAddRef(DN_OS_TLSFrameArena(), fs_path, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
DN_Str8 copy = DN_Str8_FromStr8(arena, path);
|
||||
|
||||
+106
-111
@@ -1,6 +1,9 @@
|
||||
#if !defined(DN_OS_H)
|
||||
#define DN_OS_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
|
||||
#include <new> // operator new
|
||||
|
||||
#if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS)
|
||||
@@ -302,94 +305,87 @@ struct DN_OSDiskSpace
|
||||
DN_U64 size;
|
||||
};
|
||||
|
||||
DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args);
|
||||
DN_API void DN_OS_EmitLogsWithOSPrintFunctions(DN_OSCore *os);
|
||||
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
|
||||
DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args);
|
||||
DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os);
|
||||
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
|
||||
|
||||
// NOTE: Memory ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
||||
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
|
||||
DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size);
|
||||
DN_API void DN_OS_MemRelease (void *ptr, DN_USize size);
|
||||
DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags);
|
||||
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
||||
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
|
||||
DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size);
|
||||
DN_API void DN_OS_MemRelease (void *ptr, DN_USize size);
|
||||
DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags);
|
||||
|
||||
// NOTE: Heap
|
||||
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem);
|
||||
DN_API void DN_OS_MemDealloc (void *ptr);
|
||||
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem);
|
||||
DN_API void DN_OS_MemDealloc (void *ptr);
|
||||
|
||||
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow ();
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_U64 DN_OS_DateUnixTimeNs ();
|
||||
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
|
||||
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
|
||||
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
|
||||
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time);
|
||||
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date);
|
||||
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
|
||||
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
|
||||
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow ();
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_U64 DN_OS_DateUnixTimeNs ();
|
||||
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
|
||||
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
|
||||
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
|
||||
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time);
|
||||
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date);
|
||||
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
|
||||
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
|
||||
|
||||
// NOTE: Other /////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
|
||||
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
|
||||
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
|
||||
#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena())
|
||||
DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
|
||||
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
|
||||
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
|
||||
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
|
||||
#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena())
|
||||
DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
|
||||
|
||||
// NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_U64 DN_OS_PerfCounterNow ();
|
||||
DN_API DN_U64 DN_OS_PerfCounterFrequency();
|
||||
DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_OSTimer DN_OS_TimerBegin ();
|
||||
DN_API void DN_OS_TimerEnd (DN_OSTimer *timer);
|
||||
DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
|
||||
DN_API DN_U64 DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency);
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
// NOTE: File system paths /////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
|
||||
DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against);
|
||||
DN_API bool DN_OS_PathDelete (DN_Str8 path);
|
||||
DN_API bool DN_OS_FileExists (DN_Str8 path);
|
||||
DN_API bool DN_OS_CopyFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_MoveFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_MakeDir (DN_Str8 path);
|
||||
DN_API bool DN_OS_DirExists (DN_Str8 path);
|
||||
DN_API bool DN_OS_DirIterate (DN_Str8 path, DN_OSDirIterator *it);
|
||||
DN_API DN_U64 DN_OS_PerfCounterNow ();
|
||||
DN_API DN_U64 DN_OS_PerfCounterFrequency ();
|
||||
DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end);
|
||||
DN_API DN_OSTimer DN_OS_TimerBegin ();
|
||||
DN_API void DN_OS_TimerEnd (DN_OSTimer *timer);
|
||||
DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
|
||||
DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency);
|
||||
|
||||
// NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err);
|
||||
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err);
|
||||
DN_API void DN_OS_FileClose (DN_OSFile *file);
|
||||
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
|
||||
// NOTE: R/W Entire File ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str8 DN_OS_ReadAll (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err);
|
||||
#define DN_OS_ReadAllFromTLS(...) DN_OS_ReadAll(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_WriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_WriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_WriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err);
|
||||
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err);
|
||||
DN_API void DN_OS_FileClose (DN_OSFile *file);
|
||||
|
||||
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
|
||||
DN_API bool DN_OS_PathDelete (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathIsFile (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathIsDir (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathMakeDir (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it);
|
||||
|
||||
// NOTE: File system paths /////////////////////////////////////////////////////////////////////////
|
||||
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
#define DN_OS_PathAddRefFromTLS(...) DN_OS_PathAddRef(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddRefFromFrame(...) DN_OS_PathAddRef(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path);
|
||||
DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path);
|
||||
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
#define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
@@ -417,41 +413,40 @@ DN_API DN_Str8 DN_OS_PathF (D
|
||||
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\"))
|
||||
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
|
||||
|
||||
// NOTE: DN_OSExec /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_Exit (int32_t exit_code);
|
||||
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
||||
#define DN_OS_ExecOrAbortFromTLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
|
||||
DN_API void DN_OS_Exit (int32_t exit_code);
|
||||
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
||||
#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
|
||||
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
|
||||
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount);
|
||||
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms);
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
|
||||
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreIncrement (DN_OSSemaphore *semaphore, DN_U32 amount);
|
||||
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms);
|
||||
|
||||
DN_API DN_OSMutex DN_OS_MutexInit ();
|
||||
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex);
|
||||
#define DN_OS_MutexScope(mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
||||
DN_API DN_OSMutex DN_OS_MutexInit ();
|
||||
DN_API void DN_OS_MutexDeinit (DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexUnlock (DN_OSMutex *mutex);
|
||||
#define DN_OS_MutexScope (mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
||||
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit ();
|
||||
DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv);
|
||||
DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms);
|
||||
DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms);
|
||||
DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv);
|
||||
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv);
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit ();
|
||||
DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv);
|
||||
DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms);
|
||||
DN_API bool DN_OS_ConditionVariableWaitUntil (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms);
|
||||
DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv);
|
||||
DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv);
|
||||
|
||||
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context);
|
||||
DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread);
|
||||
DN_API DN_U32 DN_OS_ThreadID ();
|
||||
DN_API void DN_OS_ThreadSetName(DN_Str8 name);
|
||||
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context);
|
||||
DN_API void DN_OS_ThreadDeinit (DN_OSThread *thread);
|
||||
DN_API DN_U32 DN_OS_ThreadID ();
|
||||
DN_API void DN_OS_ThreadSetName (DN_Str8 name);
|
||||
|
||||
DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
||||
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
||||
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
||||
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
||||
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
#endif // !defined(DN_OS_H)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#if !defined(DN_OS_ALLOCATOR_H)
|
||||
#define DN_OS_ALLOCATOR_H
|
||||
|
||||
DN_API DN_Arena DN_Arena_FromOSHeap(DN_U64 size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_FromHeap(DN_U64 size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_FromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
|
||||
|
||||
#endif // !defined(DN_OS_ALLOCATOR_H)
|
||||
|
||||
+153
-157
@@ -196,7 +196,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_OSDiskSpace result = {};
|
||||
DN_Str8 path_z_terminated = DN_Str8_Copy(tmem.arena, path);
|
||||
DN_Str8 path_z_terminated = DN_Str8_FromStr8(tmem.arena, path);
|
||||
|
||||
struct statvfs info = {};
|
||||
if (statvfs(path_z_terminated.data, &info) != 0)
|
||||
@@ -297,52 +297,7 @@ DN_API DN_U64 DN_OS_PerfCounterNow()
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
|
||||
{
|
||||
DN_OSPathInfo result = {};
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat file_stat;
|
||||
if (lstat(path.data, &file_stat) != -1) {
|
||||
result.exists = true;
|
||||
result.size = file_stat.st_size;
|
||||
result.last_access_time_in_s = file_stat.st_atime;
|
||||
result.last_write_time_in_s = file_stat.st_mtime;
|
||||
// TODO(dn): Seems linux does not support creation time via stat. We
|
||||
// shoddily deal with this.
|
||||
result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s);
|
||||
|
||||
if (S_ISDIR(file_stat.st_mode))
|
||||
result.type = DN_OSPathInfoType_Directory;
|
||||
else if (S_ISREG(file_stat.st_mode))
|
||||
result.type = DN_OSPathInfoType_File;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (DN_Str8_HasData(path))
|
||||
result = remove(path.data) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileExists(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat stat_result;
|
||||
if (lstat(path.data, &stat_result) != -1)
|
||||
result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
{
|
||||
bool result = false;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
@@ -417,7 +372,7 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
{
|
||||
// See: https://github.com/gingerBill/gb/blob/master/gb.h
|
||||
bool result = false;
|
||||
@@ -425,7 +380,7 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
if (link(src.data, dest.data) == -1) {
|
||||
// NOTE: Link can fail if we're trying to link across different volumes
|
||||
// so we fall back to a binary directory.
|
||||
file_moved |= DN_OS_CopyFile(src, dest, overwrite, error);
|
||||
file_moved |= DN_OS_FileCopy(src, dest, overwrite, error);
|
||||
}
|
||||
|
||||
if (file_moved) {
|
||||
@@ -445,108 +400,6 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_MakeDir(DN_Str8 path)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
bool result = true;
|
||||
|
||||
// TODO(doyle): Implement this without using the path indexes, it's not
|
||||
// necessary. See Windows implementation.
|
||||
DN_USize path_indexes_size = 0;
|
||||
uint16_t path_indexes[64] = {};
|
||||
|
||||
DN_Str8 copy = DN_Str8_Copy(tmem.arena, path);
|
||||
for (DN_USize index = copy.size - 1; index < copy.size; index--) {
|
||||
bool first_char = index == (copy.size - 1);
|
||||
char ch = copy.data[index];
|
||||
if (ch == '/' || first_char) {
|
||||
char temp = copy.data[index];
|
||||
|
||||
if (!first_char)
|
||||
copy.data[index] = 0; // Temporarily null terminate it
|
||||
|
||||
bool is_file = DN_OS_FileExists(copy);
|
||||
|
||||
if (!first_char)
|
||||
copy.data[index] = temp; // Undo null termination
|
||||
|
||||
if (is_file) {
|
||||
// NOTE: There's something that exists in at this path, but
|
||||
// it's not a directory. This request to make a directory is
|
||||
// invalid.
|
||||
return false;
|
||||
} else if (DN_OS_DirExists(copy)) {
|
||||
// NOTE: We found a directory, we can stop here and start
|
||||
// building up all the directories that didn't exist up to
|
||||
// this point.
|
||||
break;
|
||||
} else {
|
||||
// NOTE: There's nothing that exists at this path, we can
|
||||
// create a directory here
|
||||
path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) {
|
||||
uint16_t path_index = path_indexes[index];
|
||||
char temp = copy.data[path_index];
|
||||
|
||||
if (index != 0)
|
||||
copy.data[path_index] = 0;
|
||||
result |= mkdir(copy.data, 0774) == 0;
|
||||
if (index != 0)
|
||||
copy.data[path_index] = temp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_DirExists(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat stat_result;
|
||||
if (lstat(path.data, &stat_result) != -1)
|
||||
result = S_ISDIR(stat_result.st_mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it)
|
||||
{
|
||||
if (!it->handle) {
|
||||
it->handle = opendir(path.data);
|
||||
if (!it->handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
for (;;) {
|
||||
entry = readdir(DN_CAST(DIR *) it->handle);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
DN_USize name_size = DN_CStr8_Size(entry->d_name);
|
||||
DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size);
|
||||
DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size);
|
||||
DN_Memcpy(it->buffer, entry->d_name, clamped_size);
|
||||
it->buffer[clamped_size] = 0;
|
||||
it->file_name = DN_Str8_Init(it->buffer, clamped_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
closedir(DN_CAST(DIR *) it->handle);
|
||||
it->handle = NULL;
|
||||
it->file_name = {};
|
||||
it->buffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
|
||||
DN_OSFileOpen open_mode,
|
||||
DN_OSFileAccess access,
|
||||
@@ -678,9 +531,152 @@ DN_API void DN_OS_FileClose(DN_OSFile *file)
|
||||
fclose(DN_CAST(FILE *) file->handle);
|
||||
*file = {};
|
||||
}
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
|
||||
// NOTE: DN_OSExec /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
|
||||
{
|
||||
DN_OSPathInfo result = {};
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat file_stat;
|
||||
if (lstat(path.data, &file_stat) != -1) {
|
||||
result.exists = true;
|
||||
result.size = file_stat.st_size;
|
||||
result.last_access_time_in_s = file_stat.st_atime;
|
||||
result.last_write_time_in_s = file_stat.st_mtime;
|
||||
// TODO(dn): Seems linux does not support creation time via stat. We
|
||||
// shoddily deal with this.
|
||||
result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s);
|
||||
|
||||
if (S_ISDIR(file_stat.st_mode))
|
||||
result.type = DN_OSPathInfoType_Directory;
|
||||
else if (S_ISREG(file_stat.st_mode))
|
||||
result.type = DN_OSPathInfoType_File;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (DN_Str8_HasData(path))
|
||||
result = remove(path.data) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsFile(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat stat_result;
|
||||
if (lstat(path.data, &stat_result) != -1)
|
||||
result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsDir(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
struct stat stat_result;
|
||||
if (lstat(path.data, &stat_result) != -1)
|
||||
result = S_ISDIR(stat_result.st_mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
bool result = true;
|
||||
|
||||
// TODO(doyle): Implement this without using the path indexes, it's not
|
||||
// necessary. See Windows implementation.
|
||||
DN_USize path_indexes_size = 0;
|
||||
uint16_t path_indexes[64] = {};
|
||||
|
||||
DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, path);
|
||||
for (DN_USize index = copy.size - 1; index < copy.size; index--) {
|
||||
bool first_char = index == (copy.size - 1);
|
||||
char ch = copy.data[index];
|
||||
if (ch == '/' || first_char) {
|
||||
char temp = copy.data[index];
|
||||
|
||||
if (!first_char)
|
||||
copy.data[index] = 0; // Temporarily null terminate it
|
||||
|
||||
bool is_file = DN_OS_PathIsFile(copy);
|
||||
|
||||
if (!first_char)
|
||||
copy.data[index] = temp; // Undo null termination
|
||||
|
||||
if (is_file) {
|
||||
// NOTE: There's something that exists in at this path, but
|
||||
// it's not a directory. This request to make a directory is
|
||||
// invalid.
|
||||
return false;
|
||||
} else if (DN_OS_PathIsDir(copy)) {
|
||||
// NOTE: We found a directory, we can stop here and start
|
||||
// building up all the directories that didn't exist up to
|
||||
// this point.
|
||||
break;
|
||||
} else {
|
||||
// NOTE: There's nothing that exists at this path, we can
|
||||
// create a directory here
|
||||
path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) {
|
||||
uint16_t path_index = path_indexes[index];
|
||||
char temp = copy.data[path_index];
|
||||
|
||||
if (index != 0)
|
||||
copy.data[path_index] = 0;
|
||||
result |= mkdir(copy.data, 0774) == 0;
|
||||
if (index != 0)
|
||||
copy.data[path_index] = temp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
|
||||
{
|
||||
if (!it->handle) {
|
||||
it->handle = opendir(path.data);
|
||||
if (!it->handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
for (;;) {
|
||||
entry = readdir(DN_CAST(DIR *) it->handle);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
DN_USize name_size = DN_CStr8_Size(entry->d_name);
|
||||
DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size);
|
||||
DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size);
|
||||
DN_Memcpy(it->buffer, entry->d_name, clamped_size);
|
||||
it->buffer[clamped_size] = 0;
|
||||
it->file_name = DN_Str8_Init(it->buffer, clamped_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
closedir(DN_CAST(DIR *) it->handle);
|
||||
it->handle = NULL;
|
||||
it->file_name = {};
|
||||
it->buffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_Exit(int32_t exit_code)
|
||||
{
|
||||
exit(DN_CAST(int) exit_code);
|
||||
@@ -914,7 +910,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
|
||||
for (DN_ForIndexU(arg_index, cmd_line.size)) {
|
||||
DN_Str8 arg = cmd_line.data[arg_index];
|
||||
argv[arg_index] = DN_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
|
||||
argv[arg_index] = DN_Str8_FromStr8(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
|
||||
}
|
||||
|
||||
// NOTE: Change the working directory if there is one
|
||||
@@ -932,7 +928,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
|
||||
if (args->working_dir.size) {
|
||||
prev_working_dir = get_current_dir_name();
|
||||
DN_Str8 working_dir = DN_Str8_Copy(tmem.arena, args->working_dir);
|
||||
DN_Str8 working_dir = DN_Str8_FromStr8(tmem.arena, args->working_dir);
|
||||
if (chdir(working_dir.data) == -1) {
|
||||
result.os_error_code = errno;
|
||||
DN_OS_ErrSinkAppendF(
|
||||
@@ -1298,7 +1294,7 @@ DN_API void DN_Posix_ThreadSetName(DN_Str8 name)
|
||||
(void)name;
|
||||
#else
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_Str8 copy = DN_Str8_Copy(tmem.arena, name);
|
||||
DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, name);
|
||||
pthread_t thread = pthread_self();
|
||||
pthread_setname_np(thread, (char *)copy.data);
|
||||
#endif
|
||||
@@ -1322,7 +1318,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
|
||||
if (!file.error) {
|
||||
char buf[256];
|
||||
DN_Str8Builder builder = DN_Str8Builder_InitFromTLS();
|
||||
DN_Str8Builder builder = DN_Str8Builder_FromTLS();
|
||||
for (;;) {
|
||||
DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr);
|
||||
if (!read.success || read.bytes_read == 0)
|
||||
|
||||
+25
-24
@@ -1,6 +1,9 @@
|
||||
#if !defined(DN_OS_TLS_H)
|
||||
#define DN_OS_TLS_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
|
||||
// NOTE: DN_OSErrSink /////////////////////////////////////////////////////////////////////////////
|
||||
enum DN_OSErrSinkMode
|
||||
{
|
||||
@@ -87,7 +90,6 @@ struct DN_OSTLSInitArgs
|
||||
DN_U64 err_sink_commit;
|
||||
};
|
||||
|
||||
// NOTE: DN_OSTLS ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args);
|
||||
DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls);
|
||||
DN_API DN_OSTLS * DN_OS_TLSGet ();
|
||||
@@ -99,30 +101,29 @@ DN_API void DN_OS_TLSPopArena ();
|
||||
DN_API DN_Arena * DN_OS_TLSTopArena ();
|
||||
DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena);
|
||||
DN_API DN_Arena * DN_OS_TLSFrameArena ();
|
||||
#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0)
|
||||
#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No)
|
||||
#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes)
|
||||
#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0)
|
||||
#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No)
|
||||
#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes)
|
||||
|
||||
// NOTE: DN_OS_ErrSink ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site);
|
||||
#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE)
|
||||
#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil)
|
||||
DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err);
|
||||
DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
|
||||
DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site);
|
||||
#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE)
|
||||
#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil)
|
||||
DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err);
|
||||
DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \
|
||||
do { \
|
||||
|
||||
+189
-191
@@ -298,7 +298,6 @@ DN_API DN_U64 DN_OS_PerfCounterNow()
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time)
|
||||
{
|
||||
ULARGE_INTEGER time_large_int = {};
|
||||
@@ -308,73 +307,7 @@ static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
|
||||
{
|
||||
DN_OSPathInfo result = {};
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
return result;
|
||||
|
||||
result.exists = true;
|
||||
result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime);
|
||||
result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime);
|
||||
result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime);
|
||||
|
||||
LARGE_INTEGER large_int = {};
|
||||
large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh;
|
||||
large_int.u.LowPart = attrib_data.nFileSizeLow;
|
||||
result.size = (DN_U64)large_int.QuadPart;
|
||||
|
||||
if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
|
||||
if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
result.type = DN_OSPathInfoType_Directory;
|
||||
else
|
||||
result.type = DN_OSPathInfoType_File;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
result = DeleteFileW(path16.data);
|
||||
if (!result)
|
||||
result = RemoveDirectoryW(path16.data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileExists(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) &&
|
||||
!(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err)
|
||||
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err)
|
||||
{
|
||||
bool result = false;
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
@@ -397,12 +330,12 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err)
|
||||
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err)
|
||||
{
|
||||
bool result = false;
|
||||
bool result = false;
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src);
|
||||
DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest);
|
||||
DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src);
|
||||
DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest);
|
||||
|
||||
unsigned long flags = MOVEFILE_COPY_ALLOWED;
|
||||
if (overwrite)
|
||||
@@ -412,128 +345,16 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
if (!result) {
|
||||
DN_W32Error win_error = DN_W32_LastError(tmem.arena);
|
||||
DN_OS_ErrSinkAppendF(err,
|
||||
win_error.code,
|
||||
"Failed to move file '%.*s' to '%.*s': (%u) %.*s",
|
||||
DN_STR_FMT(src),
|
||||
DN_STR_FMT(dest),
|
||||
win_error.code,
|
||||
DN_STR_FMT(win_error.msg));
|
||||
win_error.code,
|
||||
"Failed to move file '%.*s' to '%.*s': (%u) %.*s",
|
||||
DN_STR_FMT(src),
|
||||
DN_STR_FMT(dest),
|
||||
win_error.code,
|
||||
DN_STR_FMT(win_error.msg));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_MakeDir(DN_Str8 path)
|
||||
{
|
||||
bool result = true;
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
|
||||
// NOTE: Go back from the end of the string to all the directories in the
|
||||
// string, and try to create them. Since Win32 API cannot create
|
||||
// intermediate directories that don't exist in a path we need to go back
|
||||
// and record all the directories until we encounter one that exists.
|
||||
//
|
||||
// From that point onwards go forwards and make all the directories
|
||||
// inbetween by null-terminating the string temporarily, creating the
|
||||
// directory and so forth until we reach the end.
|
||||
//
|
||||
// If we find a file at some point in the path we fail out because the
|
||||
// series of directories can not be made if a file exists with the same
|
||||
// name.
|
||||
for (DN_USize index = 0; index < path16.size; index++) {
|
||||
bool first_char = index == (path16.size - 1);
|
||||
wchar_t ch = path16.data[index];
|
||||
if (ch == '/' || ch == '\\' || first_char) {
|
||||
wchar_t temp = path16.data[index];
|
||||
if (!first_char)
|
||||
path16.data[index] = 0; // Temporarily null terminate it
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check
|
||||
|
||||
if (successful) {
|
||||
if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// NOTE: The directory exists, continue iterating the path
|
||||
} else {
|
||||
// NOTE: There's some kind of file that exists at the path
|
||||
// but it's not a directory. This request to make a
|
||||
// directory is invalid.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// NOTE: There's nothing that exists at this path, we can create
|
||||
// a directory here
|
||||
result |= (CreateDirectoryW(path16.data, nullptr) == 0);
|
||||
}
|
||||
|
||||
if (!first_char)
|
||||
path16.data[index] = temp; // Undo null termination
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_DirExists(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) &&
|
||||
(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it)
|
||||
{
|
||||
if (!DN_Str8_HasData(path) || !it || path.size <= 0)
|
||||
return false;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_W32FolderIteratorW wide_it = {};
|
||||
DN_Str16 path16 = {};
|
||||
if (it->handle) {
|
||||
wide_it.handle = it->handle;
|
||||
} else {
|
||||
bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) ||
|
||||
DN_Str8_EndsWith(path, DN_STR8("/"));
|
||||
bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) ||
|
||||
DN_Str8_EndsWith(path, DN_STR8("/*"));
|
||||
|
||||
DN_Str8 adjusted_path = path;
|
||||
if (!has_glob) {
|
||||
// NOTE: We are missing the glob for enumerating the files, we will
|
||||
// add those characters in this branch, so overwrite the null
|
||||
// character, add the glob and re-null terminate the buffer.
|
||||
if (needs_asterisks)
|
||||
adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path));
|
||||
else
|
||||
adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path));
|
||||
}
|
||||
|
||||
path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path);
|
||||
if (path16.size <= 0) // Conversion error
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = DN_W32_DirWIterate(path16, &wide_it);
|
||||
it->handle = wide_it.handle;
|
||||
if (result) {
|
||||
int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer));
|
||||
it->file_name = DN_Str8_Init(it->buffer, size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_OSErrSink *err)
|
||||
{
|
||||
DN_OSFile result = {};
|
||||
@@ -680,7 +501,184 @@ DN_API void DN_OS_FileClose(DN_OSFile *file)
|
||||
CloseHandle(file->handle);
|
||||
*file = {};
|
||||
}
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
|
||||
{
|
||||
DN_OSPathInfo result = {};
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
return result;
|
||||
|
||||
result.exists = true;
|
||||
result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime);
|
||||
result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime);
|
||||
result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime);
|
||||
|
||||
LARGE_INTEGER large_int = {};
|
||||
large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh;
|
||||
large_int.u.LowPart = attrib_data.nFileSizeLow;
|
||||
result.size = (DN_U64)large_int.QuadPart;
|
||||
|
||||
if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
|
||||
if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
result.type = DN_OSPathInfoType_Directory;
|
||||
else
|
||||
result.type = DN_OSPathInfoType_File;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
result = DeleteFileW(path16.data);
|
||||
if (!result)
|
||||
result = RemoveDirectoryW(path16.data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsFile(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) &&
|
||||
!(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsDir(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
if (!DN_Str8_HasData(path))
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) &&
|
||||
(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
{
|
||||
bool result = true;
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path);
|
||||
|
||||
// NOTE: Go back from the end of the string to all the directories in the
|
||||
// string, and try to create them. Since Win32 API cannot create
|
||||
// intermediate directories that don't exist in a path we need to go back
|
||||
// and record all the directories until we encounter one that exists.
|
||||
//
|
||||
// From that point onwards go forwards and make all the directories
|
||||
// inbetween by null-terminating the string temporarily, creating the
|
||||
// directory and so forth until we reach the end.
|
||||
//
|
||||
// If we find a file at some point in the path we fail out because the
|
||||
// series of directories can not be made if a file exists with the same
|
||||
// name.
|
||||
for (DN_USize index = 0; index < path16.size; index++) {
|
||||
bool first_char = index == (path16.size - 1);
|
||||
wchar_t ch = path16.data[index];
|
||||
if (ch == '/' || ch == '\\' || first_char) {
|
||||
wchar_t temp = path16.data[index];
|
||||
if (!first_char)
|
||||
path16.data[index] = 0; // Temporarily null terminate it
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check
|
||||
|
||||
if (successful) {
|
||||
if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// NOTE: The directory exists, continue iterating the path
|
||||
} else {
|
||||
// NOTE: There's some kind of file that exists at the path
|
||||
// but it's not a directory. This request to make a
|
||||
// directory is invalid.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// NOTE: There's nothing that exists at this path, we can create
|
||||
// a directory here
|
||||
result |= (CreateDirectoryW(path16.data, nullptr) == 0);
|
||||
}
|
||||
|
||||
if (!first_char)
|
||||
path16.data[index] = temp; // Undo null termination
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
|
||||
{
|
||||
if (!DN_Str8_HasData(path) || !it || path.size <= 0)
|
||||
return false;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_W32FolderIteratorW wide_it = {};
|
||||
DN_Str16 path16 = {};
|
||||
if (it->handle) {
|
||||
wide_it.handle = it->handle;
|
||||
} else {
|
||||
bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) ||
|
||||
DN_Str8_EndsWith(path, DN_STR8("/"));
|
||||
bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) ||
|
||||
DN_Str8_EndsWith(path, DN_STR8("/*"));
|
||||
|
||||
DN_Str8 adjusted_path = path;
|
||||
if (!has_glob) {
|
||||
// NOTE: We are missing the glob for enumerating the files, we will
|
||||
// add those characters in this branch, so overwrite the null
|
||||
// character, add the glob and re-null terminate the buffer.
|
||||
if (needs_asterisks)
|
||||
adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path));
|
||||
else
|
||||
adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path));
|
||||
}
|
||||
|
||||
path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path);
|
||||
if (path16.size <= 0) // Conversion error
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = DN_W32_DirWIterate(path16, &wide_it);
|
||||
it->handle = wide_it.handle;
|
||||
if (result) {
|
||||
int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer));
|
||||
it->file_name = DN_Str8_Init(it->buffer, size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: DN_OSExec /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_Exit(int32_t exit_code)
|
||||
|
||||
Reference in New Issue
Block a user