diff options
Diffstat (limited to 'zen')
-rw-r--r-- | zen/globals.h | 10 | ||||
-rw-r--r-- | zen/legacy_compiler.cpp | 22 | ||||
-rw-r--r-- | zen/stl_tools.h | 22 | ||||
-rw-r--r-- | zen/sys_info.cpp | 43 | ||||
-rw-r--r-- | zen/sys_info.h | 2 | ||||
-rw-r--r-- | zen/time.h | 112 |
6 files changed, 168 insertions, 43 deletions
diff --git a/zen/globals.h b/zen/globals.h index 47da2ac4..6a50a497 100644 --- a/zen/globals.h +++ b/zen/globals.h @@ -211,10 +211,6 @@ void registerGlobalForDestruction(CleanUpEntry& entry) } //------------------------------------------------------------------------------------------ - #ifdef __cpp_lib_atomic_wait - #error implement + rewiew improvements - #endif - inline bool PodSpinMutex::tryLock() @@ -227,11 +223,7 @@ inline void PodSpinMutex::lock() { while (!tryLock()) -#ifdef __cpp_lib_atomic_wait flag_.wait(true, std::memory_order_relaxed); -#else - ; -#endif } @@ -239,9 +231,7 @@ inline void PodSpinMutex::unlock() { flag_.clear(std::memory_order_release); -#ifdef __cpp_lib_atomic_wait flag_.notify_one(); -#endif } diff --git a/zen/legacy_compiler.cpp b/zen/legacy_compiler.cpp index 81efb4dd..6c5489d5 100644 --- a/zen/legacy_compiler.cpp +++ b/zen/legacy_compiler.cpp @@ -5,22 +5,24 @@ // ***************************************************************************** #include "legacy_compiler.h" -#ifdef __cpp_lib_to_chars - #error get rid of workarounds -#endif +#include <charconv> +/* 1. including <charconv> in header file blows up VC++: + - string_tools.h: "An internal error has occurred in the compiler. (compiler file 'd:\agent\_work\1\s\src\vctools\Compiler\Utc\src\p2\p2symtab.c', line 2618)" + - PCH: "fatal error C1076: compiler limit: internal heap limit reached" + => include in separate compilation unit + 2. Disable "C/C++ -> Code Generation -> Smaller Type Check" (and PCH usage!), at least for this compilation unit: https://github.com/microsoft/STL/pull/171 */ double zen::fromChars(const char* first, const char* last) { - return std::strtod(std::string(first, last).c_str(), nullptr); + double num = 0; + [[maybe_unused]] const std::from_chars_result rv = std::from_chars(first, last, num); + return num; } const char* zen::toChars(char* first, char* last, double num) { - const size_t bufSize = last - first; - const int charsWritten = std::snprintf(first, bufSize, "%g", num); - //C99: returns number of chars written if successful, < 0 or >= bufferSize on failure - - return 0 <= charsWritten && charsWritten < static_cast<int>(bufSize) ? - first + charsWritten : first; + const std::to_chars_result rv = std::to_chars(first, last, num); + return rv.ec == std::errc{} ? rv.ptr : first; } + diff --git a/zen/stl_tools.h b/zen/stl_tools.h index 53b95241..a1c5b7b1 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -36,6 +36,12 @@ void removeDuplicates(std::vector<T, Alloc>& v); template <class T, class Alloc, class CompLess> void removeDuplicates(std::vector<T, Alloc>& v, CompLess less); +template <class T, class Alloc, class CompLess> +void removeDuplicatesStable(std::vector<T, Alloc>& v, CompLess less); + +template <class T, class Alloc> +void removeDuplicatesStable(std::vector<T, Alloc>& v); + //searching STL containers template <class BidirectionalIterator, class T> BidirectionalIterator findLast(BidirectionalIterator first, BidirectionalIterator last, const T& value); @@ -132,6 +138,22 @@ void removeDuplicates(std::vector<T, Alloc>& v) } +template <class T, class Alloc, class CompLess> inline +void removeDuplicatesStable(std::vector<T, Alloc>& v, CompLess less) +{ + std::set<T, CompLess> usedItems(less); + v.erase(std::remove_if(v.begin(), v.end(), + [&usedItems](const T& e) { return !usedItems.insert(e).second; }), v.end()); +} + + +template <class T, class Alloc> inline +void removeDuplicatesStable(std::vector<T, Alloc>& v) +{ + removeDuplicatesStable(v, std::less()); +} + + template <class Iterator, class T, class CompLess> inline Iterator binarySearch(Iterator first, Iterator last, const T& value, CompLess less) { diff --git a/zen/sys_info.cpp b/zen/sys_info.cpp index 6eeab276..edb8dd9d 100644 --- a/zen/sys_info.cpp +++ b/zen/sys_info.cpp @@ -24,7 +24,7 @@ using namespace zen; -Zstring zen::getUserName() //throw FileError +Zstring zen::getLoginUser() //throw FileError { const uid_t userIdNo = ::getuid(); //never fails @@ -66,7 +66,8 @@ Zstring zen::getUserName() //throw FileError if (const char* userName = tryGetNonRootUser("SUDO_USER")) return userName; if (const char* userName = tryGetNonRootUser("LOGNAME")) return userName; - throw FileError(_("Cannot get process information."), L"Failed to determine non-root user name"); //should not happen? + //apparently the current user really IS root: https://freefilesync.org/forum/viewtopic.php?t=8405 + return "root"; } @@ -152,6 +153,19 @@ Zstring zen::getRealProcessPath() //throw FileError } +namespace +{ +Zstring getUserDir() //throw FileError +{ + const Zstring loginUser = getLoginUser(); //throw FileError + if (loginUser == "root") + return "/root"; + else + return "/home/" + loginUser; +} +} + + Zstring zen::getUserDataPath() //throw FileError { if (::getuid() != 0) //nofail; root(0) => consider as request for elevation, NOT impersonation @@ -159,7 +173,7 @@ Zstring zen::getUserDataPath() //throw FileError xdgCfgPath && xdgCfgPath[0] != 0) return xdgCfgPath; - return "/home/" + getUserName() + "/.config"; //throw FileError + return getUserDir() + "/.config"; //throw FileError } @@ -167,18 +181,17 @@ Zstring zen::getUserDownloadsPath() //throw FileError { try { - const Zstring cmdLine = ::getuid() == 0 ? //nofail; root(0) => consider as request for elevation, NOT impersonation - //sudo better be installed :> - "sudo -u " + getUserName() + " xdg-user-dir DOWNLOAD" : //throw FileError - "xdg-user-dir DOWNLOAD"; - - const auto& [exitCode, output] = consoleExecute(cmdLine, std::nullopt /*timeoutMs*/); //throw SysError - if (exitCode != 0) //fallback: probably correct 99.9% of the time anyway... - return "/home/" + getUserName() + "/Downloads"; //throw FileError - - const Zstring& downloadsPath = trimCpy(output); - ASSERT_SYSERROR(!downloadsPath.empty()); - return downloadsPath; + if (::getuid() != 0) //nofail; root(0) => consider as request for elevation, NOT impersonation + if (const auto& [exitCode, output] = consoleExecute("xdg-user-dir DOWNLOAD", std::nullopt /*timeoutMs*/); //throw SysError + exitCode == 0) + { + const Zstring& downloadsPath = trimCpy(output); + ASSERT_SYSERROR(!downloadsPath.empty()); + return downloadsPath; + } + + //fallback: probably correct 99.9% of the time anyway... + return getUserDir() + "/Downloads"; //throw FileError } catch (const SysError& e) { throw FileError(_("Cannot get process information."), e.toString()); } } diff --git a/zen/sys_info.h b/zen/sys_info.h index 54dc1aca..0126ad2f 100644 --- a/zen/sys_info.h +++ b/zen/sys_info.h @@ -14,7 +14,7 @@ namespace zen { //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize -Zstring getUserName(); //throw FileError +Zstring getLoginUser(); //throw FileError struct ComputerModel { @@ -152,20 +152,116 @@ TimeComp getLocalTime(time_t utc) constexpr auto fileTimeTimetOffset = 11'644'473'600; -warn_static("remove after test") #if 0 +warn_static("remove after test") inline TimeComp getUtcTime2(time_t utc) { - utc += year100UnixOffset; //first century not divisible by 400 + //1. convert: seconds since year 1: + //... + + //TODO: what if < 0? + long long remDays = utc / (24 * 3600); + long long remSecs = utc % (24 * 3600); + + const int daysPer4Years = 4 * 365 /*usual days per year*/ + 1 /*including leap day*/; + const int daysPerYear = 365; //non-leap + const int daysPer100Years = 25 * daysPer4Years - 1; + const int daysPer400Years = 100 * daysPer4Years - 3 /*no leap days for centuries, except if divisible by 400 */; + + const lldiv_t cycles400 = std::lldiv(remDays, daysPer400Years); + remDays = cycles400.rem; + + + int cycles100 = (remDays / daysPer100Years); + if (cycles100 == 4) + --cycles100; + + remDays -= cycles100 * daysPer100Years; + + + int cycles4 = (remDays / daysPer4Years); + if (cycles4 == 25) + --cycles4; + + remDays -= cycles4 * daysPer4Years; + + + int cycles1 = remDays / daysPerYear; + if (cycles1 == 4) + --cycles1; - long long remSecs = year100UnixOffset % (24 * 3600); - long long remDays = year100UnixOffset / (24 * 3600); + remDays -= cycles1 * daysPerYears; + + const int year = 1 + cycles400.quot * 400 + cycles100 * 100; + cycles4 * 4 + cycles1;; + + + + + + //first four years of century: + if (skipCenturyLeapDay) + { + if (remDays < 4 * daysPerYear) + { + year += remDays / daysPerYear; + remDays %= daysPerYear; + } + else + { + remDays -= 4 * daysPerYear; + year += 4; + => go to if block; + } + } + else + { + year += (remDays / daysPer4Years) * 4; + remDays %= daysPer4Years; + + if (remDays < daysPerYear + 1 /*including leap day*/) + isLeapYear = true; + else + { + remDays -= daysPerYear + 1; + ++year; + + year += remDays / daysPerYear; + remDays %= daysPerYear; + } + } + + + + + + + + + const int daysPer100Years = 25 * (4 * 365 /*usual days per year*/ + 1)/*leap days */; + + + const int daysPer100Years = 100 * 365 /*usual days per year*/ + 25 /*leap days */; + const int daysPer200Years = 200 * 365 /*usual days per year*/ + 50 /*leap days */ - 1 /*no leap days for centuries, except if divisible by 400 */; + const int daysPer300Years = 300 * 365 /*usual days per year*/ + 75 /*leap days */ - 2 /*no leap days for centuries, except if divisible by 400 */; + + if (remDays >= daysPer300Years) + { + year += 300; + remDays -= daysPer300Years; + } + else if (remDays >= daysPer200Years) + { + year += 200; + remDays -= daysPer200Years; + } + else if (remDays >= daysPer100Years) + { + year += 100; + remDays -= daysPer100Years; + } - constexpr int daysPer400Years = 400 * 365 /*usual days per year*/ + 100 /*leap days */ - 3 /*no leap days for centuries not divisible by 400 */; - int year = 100 + (remDays / daysPer400Years) * 400; - remDays %= 400; constexpr int daysPer100Years = 100 * 365 /*usual days per year*/ + 25 /*leap days */ - 1 /*no leap days for centuries not divisible by 400 */; @@ -188,6 +284,8 @@ TimeComp getUtcTime2(time_t utc) } + +warn_static("get rid of fileTimeTimetOffset!") #endif |