From 38c0e7dda058f266ecb137825c4dbcd8bb658cd4 Mon Sep 17 00:00:00 2001 From: doylet Date: Thu, 20 Nov 2025 22:39:46 +1100 Subject: [PATCH] Port changes from SolidPP --- Single-Header/dn_single_header.cpp | 456 +++++++++++++++++------------ Single-Header/dn_single_header.h | 228 +++++++-------- Source/Base/dn_base.cpp | 129 +++++++- Source/Base/dn_base.h | 16 + Source/OS/dn_os.cpp | 75 ++--- Source/OS/dn_os.h | 43 +-- Source/OS/dn_os_posix.cpp | 62 ++-- Source/OS/dn_os_w32.cpp | 75 ++--- Source/OS/dn_os_windows.h | 27 +- single_header_generator.cpp | 2 +- 10 files changed, 621 insertions(+), 492 deletions(-) diff --git a/Single-Header/dn_single_header.cpp b/Single-Header/dn_single_header.cpp index 1296670..6e1e02a 100644 --- a/Single-Header/dn_single_header.cpp +++ b/Single-Header/dn_single_header.cpp @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-11-16 21:35:27 +// Generated by the DN single header generator 2025-11-20 22:39:16 #define DN_BASE_INC_CPP @@ -2828,61 +2828,72 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64(DN_U64 duration_ms, DN_AgeUnit units) units &= ~DN_AgeUnit_Ms; } + DN_Str8 unit_suffix = {}; if (units & DN_AgeUnit_Year) { + unit_suffix = DN_Str8Lit("y"); DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000); remainder_ms -= DN_SecFromYears(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuyr", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Week) { + unit_suffix = DN_Str8Lit("w"); DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000); remainder_ms -= DN_SecFromWeeks(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuw", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Day) { + unit_suffix = DN_Str8Lit("d"); DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000); remainder_ms -= DN_SecFromDays(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zud", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Hr) { + unit_suffix = DN_Str8Lit("h"); DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000); remainder_ms -= DN_SecFromHours(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuh", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Min) { + unit_suffix = DN_Str8Lit("m"); DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000); remainder_ms -= DN_SecFromMins(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zum", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Sec) { + unit_suffix = DN_Str8Lit("s"); if (units & DN_AgeUnit_FractionalSec) { - DN_F64 remainder_s = remainder_ms / 1000.0; - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3fs", result.size ? " " : "", remainder_s); - remainder_ms = 0; + DN_F64 remainder_s = remainder_ms / 1000.0; + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3f%.*s", result.size ? " " : "", remainder_s, DN_Str8PrintFmt(unit_suffix)); + remainder_ms = 0; } else { DN_USize value_usize = remainder_ms / 1000; remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000); if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zus", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } } if (units & DN_AgeUnit_Ms) { + unit_suffix = DN_Str8Lit("ms"); DN_Assert((units & DN_AgeUnit_FractionalSec) == 0); DN_USize value_usize = remainder_ms; remainder_ms -= value_usize; if (value_usize || result.size == 0) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zums", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } + + if (result.size == 0) + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "0%.*s", DN_Str8PrintFmt(unit_suffix)); return result; } @@ -2900,6 +2911,104 @@ DN_API DN_Str8x128 DN_AgeStr8FromSecF64(DN_F64 duration_s, DN_AgeUnit units) return result; } +DN_API int DN_IsLeapYear(int year) +{ + if (year % 4 != 0) + return 0; + if (year % 100 != 0) + return 1; + return (year % 400 == 0); +} + +DN_API bool DN_DateIsValid(DN_Date date) +{ + if (date.year < 1970) + return false; + if (date.month <= 0 || date.month >= 13) + return false; + if (date.day <= 0 || date.day >= 32) + return false; + if (date.hour >= 24) + return false; + if (date.minutes >= 60) + return false; + if (date.seconds >= 60) + return false; + return true; +} + +DN_API DN_Date DN_DateFromUnixTimeMs(DN_USize unix_ts_ms) +{ + DN_Date result = {}; + DN_USize ms = unix_ts_ms % 1000; + DN_USize total_seconds = unix_ts_ms / 1000; + result.milliseconds = (DN_U16)ms; + + DN_USize secs_in_day = total_seconds % 86400; + DN_USize days = total_seconds / 86400; + + result.hour = (DN_U8)(secs_in_day / 3600); + result.minutes = (DN_U8)((secs_in_day % 3600) / 60); + result.seconds = (DN_U8)(secs_in_day % 60); + + DN_U16 days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + DN_USize days_left = days; + DN_U16 year = 1970; + + while (days_left >= (DN_IsLeapYear(year) ? 366 : 365)) { + DN_USize days_in_year = DN_IsLeapYear(year) ? 366 : 365; + days_left -= days_in_year; + year++; + } + + DN_U8 month = 1; + for (;;) { + DN_U16 day_count = days_in_month[month]; + if (month == 2 && DN_IsLeapYear(year)) + day_count = 29; + if (days_left < day_count) + break; + days_left -= day_count; + month++; + } + + result.year = year; + result.month = month; + result.day = (DN_U8)days_left + 1; + return result; +} + +DN_API DN_U64 DN_UnixTimeMsFromDate(DN_Date date) +{ + DN_Assert(DN_DateIsValid(date)); + + // Precomputed cumulative days before each month (non-leap year) + const DN_U16 days_before_month[13] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; + + DN_U16 y = date.year; + DN_U8 m = date.month; + DN_U8 d = date.day; + + DN_U32 days = d - 1; // day of month starts at 0 internally + days += days_before_month[m - 1]; // Add days from previous months this year + + if (m > 2 && DN_IsLeapYear(y)) // Add February 29 if leap year and month > 2 + days += 1; + + // Add full years from 1970 to y-1 + for (DN_U16 year = 1970; year < y; ++year) + days += DN_IsLeapYear(year) ? 366 : 365; + + // Convert to seconds + DN_U64 seconds = DN_Cast(DN_U64)days * 86400ULL; + seconds += DN_Cast(DN_U64)date.hour * 3600ULL; + seconds += DN_Cast(DN_U64)date.minutes * 60ULL; + seconds += DN_Cast(DN_U64)date.seconds; + DN_U64 result = seconds * 1000ULL + date.milliseconds; + return result; +} + DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type) { DN_Str8 result = DN_Str8Lit(""); @@ -5457,14 +5566,14 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, } } - DN_OSDateTime os_date = DN_OS_DateLocalTimeNow(); - DN_LOGDate log_date = {}; - log_date.year = os_date.year; - log_date.month = os_date.month; - log_date.day = os_date.day; - log_date.hour = os_date.hour; - log_date.minute = os_date.minutes; - log_date.second = os_date.seconds; + DN_Date os_date = DN_OS_DateLocalTimeNow(); + DN_LOGDate log_date = {}; + log_date.year = os_date.year; + log_date.month = os_date.month; + log_date.day = os_date.day; + log_date.hour = os_date.hour; + log_date.minute = os_date.minutes; + log_date.second = os_date.seconds; char prefix_buffer[128] = {}; DN_LOGPrefixSize prefix_size = DN_LOG_MakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer)); @@ -5586,57 +5695,30 @@ DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS(void const *bytes, DN_USize bytes_c return result; } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator) +// NOTE: Date +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8(DN_Date time, char date_separator, char hms_separator) { - DN_OSDateTimeStr8 result = {}; - result.hms_size = DN_Cast(uint8_t) DN_SNPrintF(result.hms, - DN_ArrayCountI(result.hms), - "%02hhu%c%02hhu%c%02hhu", - time.hour, - hms_separator, - time.minutes, - hms_separator, - time.seconds); - - result.date_size = DN_Cast(uint8_t) DN_SNPrintF(result.date, - DN_ArrayCountI(result.date), - "%hu%c%02hhu%c%02hhu", - time.year, - date_separator, - time.month, - date_separator, - time.day); - - DN_Assert(result.hms_size < DN_ArrayCountU(result.hms)); - DN_Assert(result.date_size < DN_ArrayCountU(result.date)); + DN_Str8x32 result = DN_Str8x32FromFmt("%hu%c%02hhu%c%02hhu %02hhu%c%02hhu%c%02hhu", + time.year, + date_separator, + time.month, + date_separator, + time.day, + time.hour, + hms_separator, + time.minutes, + hms_separator, + time.seconds); return result; } -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) { - DN_OSDateTime time = DN_OS_DateLocalTimeNow(); - DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); + DN_Date time = DN_OS_DateLocalTimeNow(); + DN_Str8x32 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); return result; } -DN_API bool DN_OS_DateIsValid(DN_OSDateTime date) -{ - if (date.year < 1970) - return false; - if (date.month <= 0 || date.month >= 13) - return false; - if (date.day <= 0 || date.day >= 32) - return false; - if (date.hour >= 24) - return false; - if (date.minutes >= 60) - return false; - if (date.seconds >= 60) - return false; - return true; -} - // NOTE: Other DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) { @@ -7005,10 +7087,10 @@ DN_API void DN_OS_MemDealloc(void *ptr) free(ptr); } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() +// NOTE: Date +DN_API DN_Date DN_OS_DateLocalTimeNow() { - DN_OSDateTime result = {}; + DN_Date result = {}; struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); @@ -7023,50 +7105,60 @@ DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() struct tm time = {}; localtime_r(&ts.tv_sec, &time); - result.hour = time.tm_hour; - result.minutes = time.tm_min; - result.seconds = time.tm_sec; + result.hour = time.tm_hour; + result.minutes = time.tm_min; + result.seconds = time.tm_sec; + result.milliseconds = ts.tv_nsec / (1000 * 1000); // TODO: Verify that getting the milliseconds like this is correct - result.day = DN_Cast(uint8_t) time.tm_mday; - result.month = DN_Cast(uint8_t) time.tm_mon + 1; - result.year = 1900 + DN_Cast(int16_t) time.tm_year; + result.day = DN_Cast(DN_U8) time.tm_mday; + result.month = DN_Cast(DN_U8) time.tm_mon + 1; + result.year = 1900 + DN_Cast(DN_U16) time.tm_year; return result; } -DN_API uint64_t DN_OS_DateUnixTimeNs() +DN_API DN_U64 DN_OS_DateUnixTimeNs() { struct timespec ts = {}; clock_gettime(CLOCK_REALTIME, &ts); - uint64_t result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; + DN_U64 result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; return result; } -DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime) +DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date) { - DN_AssertOnce(!"Unimplemented"); - uint64_t result = 0; + struct tm tm_time = {0}; + tm_time.tm_year = (int)date.year - 1900; + tm_time.tm_mon = (int)date.month - 1; // month is 1-12 in your struct + tm_time.tm_mday = (int)date.day; // day of month 1-31 + tm_time.tm_hour = (int)date.hour; + tm_time.tm_min = (int)date.minutes; + tm_time.tm_sec = (int)date.seconds; + tm_time.tm_isdst = -1; // tm_isdst = -1 lets mktime() determine whether DST is in effect + time_t unix_time = mktime(&tm_time); + DN_U64 result = DN_Cast(DN_U64) unix_time; return result; } -DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s) { - DN_Assert(DN_OS_DateIsValid(date)); - struct tm timeinfo = {}; - timeinfo.tm_year = date.year - 1900; - timeinfo.tm_mon = date.month - 1; - timeinfo.tm_mday = date.day; - timeinfo.tm_hour = date.hour; - timeinfo.tm_min = date.minutes; - timeinfo.tm_sec = date.seconds; - uint64_t result = mktime(&timeinfo); + struct tm tm_local; + void *ret = localtime_r(&unix_ts_s, &tm_local); + DN_Assert(ret); + + long local_offset_seconds = tm_local.tm_gmtoff; + DN_U64 result = unix_ts_s; + if (local_offset_seconds > 0) + result += local_offset_seconds; + else + result -= local_offset_seconds; return result; } -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) +DN_API DN_Date DN_OS_DateUnixTimeSToDate(DN_U64 time) { time_t posix_time = DN_Cast(time_t) time; struct tm posix_date = *gmtime(&posix_time); - DN_OSDateTime result = {}; + DN_Date result = {}; result.year = posix_date.tm_year + 1900; result.month = posix_date.tm_mon + 1; result.day = posix_date.tm_mday; @@ -8558,19 +8650,20 @@ DN_API void DN_OS_MemDealloc(void *ptr) HeapFree(GetProcessHeap(), 0, ptr); } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() +// NOTE: Date +DN_API DN_Date DN_OS_DateLocalTimeNow() { SYSTEMTIME sys_time; GetLocalTime(&sys_time); - DN_OSDateTime result = {}; - result.hour = DN_Cast(uint8_t) sys_time.wHour; - result.minutes = DN_Cast(uint8_t) sys_time.wMinute; - result.seconds = DN_Cast(uint8_t) sys_time.wSecond; - result.day = DN_Cast(uint8_t) sys_time.wDay; - result.month = DN_Cast(uint8_t) sys_time.wMonth; - result.year = DN_Cast(int16_t) sys_time.wYear; + DN_Date result = {}; + result.hour = DN_Cast(DN_U8) sys_time.wHour; + result.milliseconds = DN_Cast(DN_U8) sys_time.wMilliseconds; + result.minutes = DN_Cast(DN_U8) sys_time.wMinute; + result.seconds = DN_Cast(DN_U8) sys_time.wSecond; + result.day = DN_Cast(DN_U8) sys_time.wDay; + result.month = DN_Cast(DN_U8) sys_time.wMonth; + result.year = DN_Cast(DN_U16) sys_time.wYear; return result; } @@ -8591,15 +8684,16 @@ DN_API DN_U64 DN_OS_DateUnixTimeNs() return result; } -static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date) +static SYSTEMTIME DN_OS_DateToSystemTime_(DN_Date date) { - SYSTEMTIME result = {}; - result.wYear = date.year; - result.wMonth = date.month; - result.wDay = date.day; - result.wHour = date.hour; - result.wMinute = date.minutes; - result.wSecond = date.seconds; + SYSTEMTIME result = {}; + result.wYear = date.year; + result.wMonth = date.month; + result.wDay = date.day; + result.wHour = date.hour; + result.wMinute = date.minutes; + result.wSecond = date.seconds; + result.wMilliseconds = date.milliseconds; return result; } @@ -8615,7 +8709,7 @@ static DN_U64 DN_OS_SystemTimeToUnixTimeS_(SYSTEMTIME *sys_time) return result; } -DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date) { SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date); SYSTEMTIME sys_time = {}; @@ -8624,36 +8718,17 @@ DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) return result; } -DN_API DN_U64 DN_OS_DateToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s) { - DN_Assert(DN_OS_DateIsValid(date)); + DN_U64 unix_time = DN_Cast(DN_U64) unix_ts_s * 10000000LL; // seconds -> 100ns units + DN_U64 filetime_utc = unix_time + 116444736000000000LL; // Unix epoch -> Windows epoch + FILETIME ft_utc = {DN_Cast(DWORD) filetime_utc, DN_Cast(DWORD)(filetime_utc >> 32)}; + FILETIME ft_local; + bool converted = FileTimeToLocalFileTime(&ft_utc, &ft_local); + DN_Assert(converted); - SYSTEMTIME sys_time = DN_OS_DateToSystemTime_(date); - DN_U64 result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); - return result; -} - -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(DN_U64 time) -{ - // NOTE: Windows epoch time starts from Jan 1, 1601 and counts in - // 100-nanoseconds intervals. - // - // See: https://devblogs.microsoft.com/oldnewthing/20090306-00/?p=18913 - - DN_U64 w32_time = 116'444'736'000'000'000 + (time * 10'000'000); - SYSTEMTIME sys_time = {}; - FILETIME file_time = {}; - file_time.dwLowDateTime = (DWORD)w32_time; - file_time.dwHighDateTime = w32_time >> 32; - FileTimeToSystemTime(&file_time, &sys_time); - - DN_OSDateTime result = {}; - result.year = DN_Cast(uint16_t) sys_time.wYear; - result.month = DN_Cast(uint8_t) sys_time.wMonth; - result.day = DN_Cast(uint8_t) sys_time.wDay; - result.hour = DN_Cast(uint8_t) sys_time.wHour; - result.minutes = DN_Cast(uint8_t) sys_time.wMinute; - result.seconds = DN_Cast(uint8_t) sys_time.wSecond; + DN_U64 filetime_local = (DN_Cast(DN_U64) ft_local.dwHighDateTime << 32) | ft_local.dwLowDateTime; + DN_U64 result = (filetime_local - 116444736000000000LL) / 10000000LL; return result; } @@ -11479,6 +11554,17 @@ struct DN_ByteCountResult DN_F64 bytes; }; +struct DN_Date +{ + DN_U8 day; + DN_U8 month; + DN_U16 year; + DN_U8 hour; + DN_U8 minutes; + DN_U8 seconds; + DN_U16 milliseconds; +}; + struct DN_FmtAppendResult { DN_USize size_req; @@ -13763,6 +13849,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); +DN_API int DN_IsLeapYear (int year); +DN_API bool DN_DateIsValid (DN_Date date); +DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); +DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); + DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); @@ -15078,20 +15169,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -16426,20 +16518,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -17579,33 +17672,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -struct DN_OSDateTimeStr8 -{ - char date[DN_ArrayCountU("YYYY-MM-SS")]; - DN_U8 date_size; - char hms[DN_ArrayCountU("HH:MM:SS")]; - DN_U8 hms_size; -}; - -struct DN_OSDateTime -{ - DN_U8 day; - DN_U8 month; - DN_U16 year; - DN_U8 hour; - DN_U8 minutes; - DN_U8 seconds; -}; - struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. { DN_U64 start; DN_U64 end; }; -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSFile ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSFile enum DN_OSPathInfoType { DN_OSPathInfoType_Unknown, @@ -17630,7 +17703,7 @@ struct DN_OSDirIterator char buffer[512]; }; -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// +// NOTE: R/W Stream API struct DN_OSFileRead { bool success; @@ -17661,9 +17734,8 @@ enum DN_OSFileAccess_ DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, }; -#endif // DN_NO_OS_FILE_API -// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSPath #if !defined(DN_OSPathSeperator) #if defined(DN_OS_WIN32) #define DN_OSPathSeperator "\\" @@ -17689,7 +17761,7 @@ struct DN_OSPath DN_U16 links_size; }; -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSExec typedef DN_U32 DN_OSExecFlags; enum DN_OSExecFlags_ @@ -17729,7 +17801,7 @@ struct DN_OSExecArgs DN_Slice environment; }; -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; struct DN_OSSemaphore @@ -17860,17 +17932,15 @@ DN_API int DN_OS_MemProtect (v DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void DN_OS_MemDealloc (void *ptr); -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_Date DN_OS_DateLocalTimeNow (); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date 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_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date); +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); diff --git a/Single-Header/dn_single_header.h b/Single-Header/dn_single_header.h index 49bb169..e49c3c1 100644 --- a/Single-Header/dn_single_header.h +++ b/Single-Header/dn_single_header.h @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-11-16 21:35:27 +// Generated by the DN single header generator 2025-11-20 22:39:16 #if !defined(DN_BASE_INC_H) #define DN_BASE_INC_H @@ -978,6 +978,17 @@ struct DN_ByteCountResult DN_F64 bytes; }; +struct DN_Date +{ + DN_U8 day; + DN_U8 month; + DN_U16 year; + DN_U8 hour; + DN_U8 minutes; + DN_U8 seconds; + DN_U16 milliseconds; +}; + struct DN_FmtAppendResult { DN_USize size_req; @@ -3262,6 +3273,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); +DN_API int DN_IsLeapYear (int year); +DN_API bool DN_DateIsValid (DN_Date date); +DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); +DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); + DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); @@ -4576,20 +4592,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -5924,20 +5941,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -7077,33 +7095,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -struct DN_OSDateTimeStr8 -{ - char date[DN_ArrayCountU("YYYY-MM-SS")]; - DN_U8 date_size; - char hms[DN_ArrayCountU("HH:MM:SS")]; - DN_U8 hms_size; -}; - -struct DN_OSDateTime -{ - DN_U8 day; - DN_U8 month; - DN_U16 year; - DN_U8 hour; - DN_U8 minutes; - DN_U8 seconds; -}; - struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. { DN_U64 start; DN_U64 end; }; -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSFile ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSFile enum DN_OSPathInfoType { DN_OSPathInfoType_Unknown, @@ -7128,7 +7126,7 @@ struct DN_OSDirIterator char buffer[512]; }; -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// +// NOTE: R/W Stream API struct DN_OSFileRead { bool success; @@ -7159,9 +7157,8 @@ enum DN_OSFileAccess_ DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, }; -#endif // DN_NO_OS_FILE_API -// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSPath #if !defined(DN_OSPathSeperator) #if defined(DN_OS_WIN32) #define DN_OSPathSeperator "\\" @@ -7187,7 +7184,7 @@ struct DN_OSPath DN_U16 links_size; }; -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSExec typedef DN_U32 DN_OSExecFlags; enum DN_OSExecFlags_ @@ -7227,7 +7224,7 @@ struct DN_OSExecArgs DN_Slice environment; }; -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; struct DN_OSSemaphore @@ -7358,17 +7355,15 @@ DN_API int DN_OS_MemProtect (v DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void DN_OS_MemDealloc (void *ptr); -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_Date DN_OS_DateLocalTimeNow (); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date 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_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date); +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); @@ -8676,6 +8671,17 @@ struct DN_ByteCountResult DN_F64 bytes; }; +struct DN_Date +{ + DN_U8 day; + DN_U8 month; + DN_U16 year; + DN_U8 hour; + DN_U8 minutes; + DN_U8 seconds; + DN_U16 milliseconds; +}; + struct DN_FmtAppendResult { DN_USize size_req; @@ -10960,6 +10966,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); +DN_API int DN_IsLeapYear (int year); +DN_API bool DN_DateIsValid (DN_Date date); +DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); +DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); + DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); @@ -12275,20 +12286,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -13623,20 +13635,21 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak); extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// @@ -14776,33 +14789,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -struct DN_OSDateTimeStr8 -{ - char date[DN_ArrayCountU("YYYY-MM-SS")]; - DN_U8 date_size; - char hms[DN_ArrayCountU("HH:MM:SS")]; - DN_U8 hms_size; -}; - -struct DN_OSDateTime -{ - DN_U8 day; - DN_U8 month; - DN_U16 year; - DN_U8 hour; - DN_U8 minutes; - DN_U8 seconds; -}; - struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. { DN_U64 start; DN_U64 end; }; -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSFile ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSFile enum DN_OSPathInfoType { DN_OSPathInfoType_Unknown, @@ -14827,7 +14820,7 @@ struct DN_OSDirIterator char buffer[512]; }; -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// +// NOTE: R/W Stream API struct DN_OSFileRead { bool success; @@ -14858,9 +14851,8 @@ enum DN_OSFileAccess_ DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, }; -#endif // DN_NO_OS_FILE_API -// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSPath #if !defined(DN_OSPathSeperator) #if defined(DN_OS_WIN32) #define DN_OSPathSeperator "\\" @@ -14886,7 +14878,7 @@ struct DN_OSPath DN_U16 links_size; }; -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSExec typedef DN_U32 DN_OSExecFlags; enum DN_OSExecFlags_ @@ -14926,7 +14918,7 @@ struct DN_OSExecArgs DN_Slice environment; }; -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; struct DN_OSSemaphore @@ -15057,17 +15049,15 @@ DN_API int DN_OS_MemProtect (v DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void DN_OS_MemDealloc (void *ptr); -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_Date DN_OS_DateLocalTimeNow (); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date 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_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date); +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); diff --git a/Source/Base/dn_base.cpp b/Source/Base/dn_base.cpp index aea3bd6..f974e7f 100644 --- a/Source/Base/dn_base.cpp +++ b/Source/Base/dn_base.cpp @@ -2823,61 +2823,72 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64(DN_U64 duration_ms, DN_AgeUnit units) units &= ~DN_AgeUnit_Ms; } + DN_Str8 unit_suffix = {}; if (units & DN_AgeUnit_Year) { + unit_suffix = DN_Str8Lit("y"); DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000); remainder_ms -= DN_SecFromYears(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuyr", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Week) { + unit_suffix = DN_Str8Lit("w"); DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000); remainder_ms -= DN_SecFromWeeks(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuw", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Day) { + unit_suffix = DN_Str8Lit("d"); DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000); remainder_ms -= DN_SecFromDays(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zud", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Hr) { + unit_suffix = DN_Str8Lit("h"); DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000); remainder_ms -= DN_SecFromHours(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuh", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Min) { + unit_suffix = DN_Str8Lit("m"); DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000); remainder_ms -= DN_SecFromMins(value_usize) * 1000; if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zum", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } if (units & DN_AgeUnit_Sec) { + unit_suffix = DN_Str8Lit("s"); if (units & DN_AgeUnit_FractionalSec) { - DN_F64 remainder_s = remainder_ms / 1000.0; - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3fs", result.size ? " " : "", remainder_s); - remainder_ms = 0; + DN_F64 remainder_s = remainder_ms / 1000.0; + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3f%.*s", result.size ? " " : "", remainder_s, DN_Str8PrintFmt(unit_suffix)); + remainder_ms = 0; } else { DN_USize value_usize = remainder_ms / 1000; remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000); if (value_usize) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zus", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } } if (units & DN_AgeUnit_Ms) { + unit_suffix = DN_Str8Lit("ms"); DN_Assert((units & DN_AgeUnit_FractionalSec) == 0); DN_USize value_usize = remainder_ms; remainder_ms -= value_usize; if (value_usize || result.size == 0) - DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zums", result.size ? " " : "", value_usize); + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix)); } + + if (result.size == 0) + DN_FmtAppend(result.data, &result.size, sizeof(result.data), "0%.*s", DN_Str8PrintFmt(unit_suffix)); return result; } @@ -2895,6 +2906,104 @@ DN_API DN_Str8x128 DN_AgeStr8FromSecF64(DN_F64 duration_s, DN_AgeUnit units) return result; } +DN_API int DN_IsLeapYear(int year) +{ + if (year % 4 != 0) + return 0; + if (year % 100 != 0) + return 1; + return (year % 400 == 0); +} + +DN_API bool DN_DateIsValid(DN_Date date) +{ + if (date.year < 1970) + return false; + if (date.month <= 0 || date.month >= 13) + return false; + if (date.day <= 0 || date.day >= 32) + return false; + if (date.hour >= 24) + return false; + if (date.minutes >= 60) + return false; + if (date.seconds >= 60) + return false; + return true; +} + +DN_API DN_Date DN_DateFromUnixTimeMs(DN_USize unix_ts_ms) +{ + DN_Date result = {}; + DN_USize ms = unix_ts_ms % 1000; + DN_USize total_seconds = unix_ts_ms / 1000; + result.milliseconds = (DN_U16)ms; + + DN_USize secs_in_day = total_seconds % 86400; + DN_USize days = total_seconds / 86400; + + result.hour = (DN_U8)(secs_in_day / 3600); + result.minutes = (DN_U8)((secs_in_day % 3600) / 60); + result.seconds = (DN_U8)(secs_in_day % 60); + + DN_U16 days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + DN_USize days_left = days; + DN_U16 year = 1970; + + while (days_left >= (DN_IsLeapYear(year) ? 366 : 365)) { + DN_USize days_in_year = DN_IsLeapYear(year) ? 366 : 365; + days_left -= days_in_year; + year++; + } + + DN_U8 month = 1; + for (;;) { + DN_U16 day_count = days_in_month[month]; + if (month == 2 && DN_IsLeapYear(year)) + day_count = 29; + if (days_left < day_count) + break; + days_left -= day_count; + month++; + } + + result.year = year; + result.month = month; + result.day = (DN_U8)days_left + 1; + return result; +} + +DN_API DN_U64 DN_UnixTimeMsFromDate(DN_Date date) +{ + DN_Assert(DN_DateIsValid(date)); + + // Precomputed cumulative days before each month (non-leap year) + const DN_U16 days_before_month[13] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; + + DN_U16 y = date.year; + DN_U8 m = date.month; + DN_U8 d = date.day; + + DN_U32 days = d - 1; // day of month starts at 0 internally + days += days_before_month[m - 1]; // Add days from previous months this year + + if (m > 2 && DN_IsLeapYear(y)) // Add February 29 if leap year and month > 2 + days += 1; + + // Add full years from 1970 to y-1 + for (DN_U16 year = 1970; year < y; ++year) + days += DN_IsLeapYear(year) ? 366 : 365; + + // Convert to seconds + DN_U64 seconds = DN_Cast(DN_U64)days * 86400ULL; + seconds += DN_Cast(DN_U64)date.hour * 3600ULL; + seconds += DN_Cast(DN_U64)date.minutes * 60ULL; + seconds += DN_Cast(DN_U64)date.seconds; + DN_U64 result = seconds * 1000ULL + date.milliseconds; + return result; +} + DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type) { DN_Str8 result = DN_Str8Lit(""); diff --git a/Source/Base/dn_base.h b/Source/Base/dn_base.h index d125305..b45fb2d 100644 --- a/Source/Base/dn_base.h +++ b/Source/Base/dn_base.h @@ -760,6 +760,17 @@ struct DN_ByteCountResult DN_F64 bytes; }; +struct DN_Date +{ + DN_U8 day; + DN_U8 month; + DN_U16 year; + DN_U8 hour; + DN_U8 minutes; + DN_U8 seconds; + DN_U16 milliseconds; +}; + struct DN_FmtAppendResult { DN_USize size_req; @@ -1116,6 +1127,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); +DN_API int DN_IsLeapYear (int year); +DN_API bool DN_DateIsValid (DN_Date date); +DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); +DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); + DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); diff --git a/Source/OS/dn_os.cpp b/Source/OS/dn_os.cpp index afff392..f3dd014 100644 --- a/Source/OS/dn_os.cpp +++ b/Source/OS/dn_os.cpp @@ -55,14 +55,14 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, } } - DN_OSDateTime os_date = DN_OS_DateLocalTimeNow(); - DN_LOGDate log_date = {}; - log_date.year = os_date.year; - log_date.month = os_date.month; - log_date.day = os_date.day; - log_date.hour = os_date.hour; - log_date.minute = os_date.minutes; - log_date.second = os_date.seconds; + DN_Date os_date = DN_OS_DateLocalTimeNow(); + DN_LOGDate log_date = {}; + log_date.year = os_date.year; + log_date.month = os_date.month; + log_date.day = os_date.day; + log_date.hour = os_date.hour; + log_date.minute = os_date.minutes; + log_date.second = os_date.seconds; char prefix_buffer[128] = {}; DN_LOGPrefixSize prefix_size = DN_LOG_MakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer)); @@ -184,57 +184,30 @@ DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS(void const *bytes, DN_USize bytes_c return result; } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator) +// NOTE: Date +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8(DN_Date time, char date_separator, char hms_separator) { - DN_OSDateTimeStr8 result = {}; - result.hms_size = DN_Cast(uint8_t) DN_SNPrintF(result.hms, - DN_ArrayCountI(result.hms), - "%02hhu%c%02hhu%c%02hhu", - time.hour, - hms_separator, - time.minutes, - hms_separator, - time.seconds); - - result.date_size = DN_Cast(uint8_t) DN_SNPrintF(result.date, - DN_ArrayCountI(result.date), - "%hu%c%02hhu%c%02hhu", - time.year, - date_separator, - time.month, - date_separator, - time.day); - - DN_Assert(result.hms_size < DN_ArrayCountU(result.hms)); - DN_Assert(result.date_size < DN_ArrayCountU(result.date)); + DN_Str8x32 result = DN_Str8x32FromFmt("%hu%c%02hhu%c%02hhu %02hhu%c%02hhu%c%02hhu", + time.year, + date_separator, + time.month, + date_separator, + time.day, + time.hour, + hms_separator, + time.minutes, + hms_separator, + time.seconds); return result; } -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) { - DN_OSDateTime time = DN_OS_DateLocalTimeNow(); - DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); + DN_Date time = DN_OS_DateLocalTimeNow(); + DN_Str8x32 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); return result; } -DN_API bool DN_OS_DateIsValid(DN_OSDateTime date) -{ - if (date.year < 1970) - return false; - if (date.month <= 0 || date.month >= 13) - return false; - if (date.day <= 0 || date.day >= 32) - return false; - if (date.hour >= 24) - return false; - if (date.minutes >= 60) - return false; - if (date.seconds >= 60) - return false; - return true; -} - // NOTE: Other DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) { diff --git a/Source/OS/dn_os.h b/Source/OS/dn_os.h index 9dae43d..d77f1f6 100644 --- a/Source/OS/dn_os.h +++ b/Source/OS/dn_os.h @@ -37,33 +37,13 @@ extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -struct DN_OSDateTimeStr8 -{ - char date[DN_ArrayCountU("YYYY-MM-SS")]; - DN_U8 date_size; - char hms[DN_ArrayCountU("HH:MM:SS")]; - DN_U8 hms_size; -}; - -struct DN_OSDateTime -{ - DN_U8 day; - DN_U8 month; - DN_U16 year; - DN_U8 hour; - DN_U8 minutes; - DN_U8 seconds; -}; - struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. { DN_U64 start; DN_U64 end; }; -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSFile ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSFile enum DN_OSPathInfoType { DN_OSPathInfoType_Unknown, @@ -88,7 +68,7 @@ struct DN_OSDirIterator char buffer[512]; }; -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// +// NOTE: R/W Stream API struct DN_OSFileRead { bool success; @@ -119,9 +99,8 @@ enum DN_OSFileAccess_ DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, }; -#endif // DN_NO_OS_FILE_API -// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSPath #if !defined(DN_OSPathSeperator) #if defined(DN_OS_WIN32) #define DN_OSPathSeperator "\\" @@ -147,7 +126,7 @@ struct DN_OSPath DN_U16 links_size; }; -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSExec typedef DN_U32 DN_OSExecFlags; enum DN_OSExecFlags_ @@ -187,7 +166,7 @@ struct DN_OSExecArgs DN_Slice environment; }; -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; struct DN_OSSemaphore @@ -318,17 +297,15 @@ DN_API int DN_OS_MemProtect (v DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void DN_OS_MemDealloc (void *ptr); -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_Date DN_OS_DateLocalTimeNow (); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date 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_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date); +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); diff --git a/Source/OS/dn_os_posix.cpp b/Source/OS/dn_os_posix.cpp index 360665e..6ae9f59 100644 --- a/Source/OS/dn_os_posix.cpp +++ b/Source/OS/dn_os_posix.cpp @@ -96,10 +96,10 @@ DN_API void DN_OS_MemDealloc(void *ptr) free(ptr); } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() +// NOTE: Date +DN_API DN_Date DN_OS_DateLocalTimeNow() { - DN_OSDateTime result = {}; + DN_Date result = {}; struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); @@ -114,50 +114,60 @@ DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() struct tm time = {}; localtime_r(&ts.tv_sec, &time); - result.hour = time.tm_hour; - result.minutes = time.tm_min; - result.seconds = time.tm_sec; + result.hour = time.tm_hour; + result.minutes = time.tm_min; + result.seconds = time.tm_sec; + result.milliseconds = ts.tv_nsec / (1000 * 1000); // TODO: Verify that getting the milliseconds like this is correct - result.day = DN_Cast(uint8_t) time.tm_mday; - result.month = DN_Cast(uint8_t) time.tm_mon + 1; - result.year = 1900 + DN_Cast(int16_t) time.tm_year; + result.day = DN_Cast(DN_U8) time.tm_mday; + result.month = DN_Cast(DN_U8) time.tm_mon + 1; + result.year = 1900 + DN_Cast(DN_U16) time.tm_year; return result; } -DN_API uint64_t DN_OS_DateUnixTimeNs() +DN_API DN_U64 DN_OS_DateUnixTimeNs() { struct timespec ts = {}; clock_gettime(CLOCK_REALTIME, &ts); - uint64_t result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; + DN_U64 result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; return result; } -DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime) +DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date) { - DN_AssertOnce(!"Unimplemented"); - uint64_t result = 0; + struct tm tm_time = {0}; + tm_time.tm_year = (int)date.year - 1900; + tm_time.tm_mon = (int)date.month - 1; // month is 1-12 in your struct + tm_time.tm_mday = (int)date.day; // day of month 1-31 + tm_time.tm_hour = (int)date.hour; + tm_time.tm_min = (int)date.minutes; + tm_time.tm_sec = (int)date.seconds; + tm_time.tm_isdst = -1; // tm_isdst = -1 lets mktime() determine whether DST is in effect + time_t unix_time = mktime(&tm_time); + DN_U64 result = DN_Cast(DN_U64) unix_time; return result; } -DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s) { - DN_Assert(DN_OS_DateIsValid(date)); - struct tm timeinfo = {}; - timeinfo.tm_year = date.year - 1900; - timeinfo.tm_mon = date.month - 1; - timeinfo.tm_mday = date.day; - timeinfo.tm_hour = date.hour; - timeinfo.tm_min = date.minutes; - timeinfo.tm_sec = date.seconds; - uint64_t result = mktime(&timeinfo); + struct tm tm_local; + void *ret = localtime_r(&unix_ts_s, &tm_local); + DN_Assert(ret); + + long local_offset_seconds = tm_local.tm_gmtoff; + DN_U64 result = unix_ts_s; + if (local_offset_seconds > 0) + result += local_offset_seconds; + else + result -= local_offset_seconds; return result; } -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) +DN_API DN_Date DN_OS_DateUnixTimeSToDate(DN_U64 time) { time_t posix_time = DN_Cast(time_t) time; struct tm posix_date = *gmtime(&posix_time); - DN_OSDateTime result = {}; + DN_Date result = {}; result.year = posix_date.tm_year + 1900; result.month = posix_date.tm_mon + 1; result.day = posix_date.tm_mday; diff --git a/Source/OS/dn_os_w32.cpp b/Source/OS/dn_os_w32.cpp index 6185f52..cb492aa 100644 --- a/Source/OS/dn_os_w32.cpp +++ b/Source/OS/dn_os_w32.cpp @@ -125,19 +125,20 @@ DN_API void DN_OS_MemDealloc(void *ptr) HeapFree(GetProcessHeap(), 0, ptr); } -// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() +// NOTE: Date +DN_API DN_Date DN_OS_DateLocalTimeNow() { SYSTEMTIME sys_time; GetLocalTime(&sys_time); - DN_OSDateTime result = {}; - result.hour = DN_Cast(uint8_t) sys_time.wHour; - result.minutes = DN_Cast(uint8_t) sys_time.wMinute; - result.seconds = DN_Cast(uint8_t) sys_time.wSecond; - result.day = DN_Cast(uint8_t) sys_time.wDay; - result.month = DN_Cast(uint8_t) sys_time.wMonth; - result.year = DN_Cast(int16_t) sys_time.wYear; + DN_Date result = {}; + result.hour = DN_Cast(DN_U8) sys_time.wHour; + result.milliseconds = DN_Cast(DN_U8) sys_time.wMilliseconds; + result.minutes = DN_Cast(DN_U8) sys_time.wMinute; + result.seconds = DN_Cast(DN_U8) sys_time.wSecond; + result.day = DN_Cast(DN_U8) sys_time.wDay; + result.month = DN_Cast(DN_U8) sys_time.wMonth; + result.year = DN_Cast(DN_U16) sys_time.wYear; return result; } @@ -158,15 +159,16 @@ DN_API DN_U64 DN_OS_DateUnixTimeNs() return result; } -static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date) +static SYSTEMTIME DN_OS_DateToSystemTime_(DN_Date date) { - SYSTEMTIME result = {}; - result.wYear = date.year; - result.wMonth = date.month; - result.wDay = date.day; - result.wHour = date.hour; - result.wMinute = date.minutes; - result.wSecond = date.seconds; + SYSTEMTIME result = {}; + result.wYear = date.year; + result.wMonth = date.month; + result.wDay = date.day; + result.wHour = date.hour; + result.wMinute = date.minutes; + result.wSecond = date.seconds; + result.wMilliseconds = date.milliseconds; return result; } @@ -182,7 +184,7 @@ static DN_U64 DN_OS_SystemTimeToUnixTimeS_(SYSTEMTIME *sys_time) return result; } -DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date) { SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date); SYSTEMTIME sys_time = {}; @@ -191,36 +193,17 @@ DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) return result; } -DN_API DN_U64 DN_OS_DateToUnixTimeS(DN_OSDateTime date) +DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s) { - DN_Assert(DN_OS_DateIsValid(date)); + DN_U64 unix_time = DN_Cast(DN_U64) unix_ts_s * 10000000LL; // seconds -> 100ns units + DN_U64 filetime_utc = unix_time + 116444736000000000LL; // Unix epoch -> Windows epoch + FILETIME ft_utc = {DN_Cast(DWORD) filetime_utc, DN_Cast(DWORD)(filetime_utc >> 32)}; + FILETIME ft_local; + bool converted = FileTimeToLocalFileTime(&ft_utc, &ft_local); + DN_Assert(converted); - SYSTEMTIME sys_time = DN_OS_DateToSystemTime_(date); - DN_U64 result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); - return result; -} - -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(DN_U64 time) -{ - // NOTE: Windows epoch time starts from Jan 1, 1601 and counts in - // 100-nanoseconds intervals. - // - // See: https://devblogs.microsoft.com/oldnewthing/20090306-00/?p=18913 - - DN_U64 w32_time = 116'444'736'000'000'000 + (time * 10'000'000); - SYSTEMTIME sys_time = {}; - FILETIME file_time = {}; - file_time.dwLowDateTime = (DWORD)w32_time; - file_time.dwHighDateTime = w32_time >> 32; - FileTimeToSystemTime(&file_time, &sys_time); - - DN_OSDateTime result = {}; - result.year = DN_Cast(uint16_t) sys_time.wYear; - result.month = DN_Cast(uint8_t) sys_time.wMonth; - result.day = DN_Cast(uint8_t) sys_time.wDay; - result.hour = DN_Cast(uint8_t) sys_time.wHour; - result.minutes = DN_Cast(uint8_t) sys_time.wMinute; - result.seconds = DN_Cast(uint8_t) sys_time.wSecond; + DN_U64 filetime_local = (DN_Cast(DN_U64) ft_local.dwHighDateTime << 32) | ft_local.dwLowDateTime; + DN_U64 result = (filetime_local - 116444736000000000LL) / 10000000LL; return result; } diff --git a/Source/OS/dn_os_windows.h b/Source/OS/dn_os_windows.h index 0b2a871..3ed69fc 100644 --- a/Source/OS/dn_os_windows.h +++ b/Source/OS/dn_os_windows.h @@ -529,20 +529,21 @@ extern "C" { - __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); - __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); - __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); - __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); - __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); + __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); + __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); + __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime); - __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); - __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); - __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); - __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); - __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); + __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); + __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); + __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); + __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); + __declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes); } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// diff --git a/single_header_generator.cpp b/single_header_generator.cpp index f9fe5a2..70221a7 100644 --- a/single_header_generator.cpp +++ b/single_header_generator.cpp @@ -165,7 +165,7 @@ int main(int argc, char **argv) AppendCppFileLineByLine(&builder, extra_path); } - DN_OSDateTime date = DN_OS_DateLocalTimeNow(); + DN_Date date = DN_OS_DateLocalTimeNow(); DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds); DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuildFromTLS(&builder));