diff options
Diffstat (limited to 'zen')
-rw-r--r-- | zen/basic_math.h | 6 | ||||
-rw-r--r-- | zen/file_access.cpp | 35 | ||||
-rw-r--r-- | zen/file_io.cpp | 18 | ||||
-rw-r--r-- | zen/format_unit.cpp | 8 | ||||
-rw-r--r-- | zen/i18n.h | 6 | ||||
-rw-r--r-- | zen/scope_guard.h | 7 | ||||
-rw-r--r-- | zen/thread.h | 36 | ||||
-rw-r--r-- | zen/type_traits.h | 9 |
8 files changed, 71 insertions, 54 deletions
diff --git a/zen/basic_math.h b/zen/basic_math.h index 8b745caf..a15d811a 100644 --- a/zen/basic_math.h +++ b/zen/basic_math.h @@ -38,7 +38,7 @@ template <class T> T clampCpy(const T& val, const T& minVal, const T& maxVal); template <class T, class InputIterator> //precondition: range must be sorted! -auto nearMatch(const T& val, InputIterator first, InputIterator last) -> typename std::iterator_traits<InputIterator>::value_type; +auto nearMatch(const T& val, InputIterator first, InputIterator last); template <class T> bool isNull(T value); @@ -195,10 +195,10 @@ std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, Input */ template <class T, class InputIterator> inline -auto nearMatch(const T& val, InputIterator first, InputIterator last) -> typename std::iterator_traits<InputIterator>::value_type +auto nearMatch(const T& val, InputIterator first, InputIterator last) { if (first == last) - return 0; + return static_cast<decltype(*first)>(0); assert(std::is_sorted(first, last)); InputIterator it = std::lower_bound(first, last, val); diff --git a/zen/file_access.cpp b/zen/file_access.cpp index 2ca373aa..a66cbc6b 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -828,7 +828,7 @@ void setFileTimeRaw(const Zstring& filePath, throw FileError(errorMsg, formatSystemError(L"SetFileTime", ec)); } } -#ifndef NDEBUG //verify written data: mainly required to check consistency of DST hack +#ifndef NDEBUG //verify written data FILETIME creationTimeDbg = {}; FILETIME lastWriteTimeDbg = {}; @@ -1347,9 +1347,9 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, bool copyFilePermissions) { #ifdef ZEN_WIN -auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); }; + auto getErrorMsg = [](const Zstring& path) { return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); }; -//special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS! + //special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS! Zstring dirTmp = removeLongPathPrefix(endsWith(targetPath, FILE_NAME_SEPARATOR) ? beforeLast(targetPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) : targetPath); @@ -1359,7 +1359,7 @@ auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create d dirTmp += FILE_NAME_SEPARATOR; //we do not support "C:" to represent a relative path! const DWORD ec = somethingExists(dirTmp) ? ERROR_ALREADY_EXISTS : ERROR_PATH_NOT_FOUND; //don't use dirExists() => harmonize with ErrorTargetExisting! - const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec); + const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec); if (ec == ERROR_ALREADY_EXISTS) throw ErrorTargetExisting(getErrorMsg(dirTmp), errorDescr); @@ -1412,7 +1412,7 @@ auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create d if (!sourcePath.empty()) if (::stat(sourcePath.c_str(), &dirInfo) == 0) { - mode = dirInfo.st_mode; //analog to "cp" which copies "mode" (considering umask) by default + mode = dirInfo.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); //analog to "cp" which copies "mode" (considering umask) by default mode |= S_IRWXU; //FFS only: we need full access to copy child items! "cp" seems to apply permissions *after* copying child items } //=> need copyItemPermissions() only for "chown" and umask-agnostic permissions @@ -1783,8 +1783,8 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw //create targetFile and open it for writing HANDLE hFileTarget = ::CreateFile(applyLongPathPrefix(targetFile).c_str(), //_In_ LPCTSTR lpFileName, - GENERIC_READ | GENERIC_WRITE, //_In_ DWORD dwDesiredAccess, - //read access required for FSCTL_SET_COMPRESSION + GENERIC_READ | GENERIC_WRITE | DELETE, //_In_ DWORD dwDesiredAccess, + //GENERIC_READ required for FSCTL_SET_COMPRESSION, DELETE for ::SetFileInformationByHandle(),FileDispositionInfo FILE_SHARE_DELETE, //_In_ DWORD dwShareMode, //FILE_SHARE_DELETE is required to rename file while handle is open! nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, @@ -1808,10 +1808,27 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw throw FileError(errorMsg, errorDescr); } +#ifndef ZEN_WIN_VISTA_AND_LATER ZEN_ON_SCOPE_FAIL(try { removeFile(targetFile); } - catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget + catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget +#endif + ZEN_ON_SCOPE_EXIT(::CloseHandle(hFileTarget)); +#ifdef ZEN_WIN_VISTA_AND_LATER + //no need for ::DeleteFile(), we already have an open handle! Maybe this also prevents needless buffer-flushing in ::CloseHandle()??? Anyway, same behavior like ::CopyFileEx() + ZEN_ON_SCOPE_FAIL + ( + FILE_DISPOSITION_INFO di = {}; + di.DeleteFile = true; + if (!::SetFileInformationByHandle(hFileTarget, //_In_ HANDLE hFile, + FileDispositionInfo, //_In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + &di, //_In_ LPVOID lpFileInformation, + sizeof(di))) //_In_ DWORD dwBufferSize + assert(false); + ); +#endif + //---------------------------------------------------------------------- BY_HANDLE_FILE_INFORMATION fileInfoTarget = {}; if (!::GetFileInformationByHandle(hFileTarget, &fileInfoTarget)) @@ -1820,7 +1837,7 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw //return up-to-date file attributes InSyncAttributes newAttrib; newAttrib.fileSize = get64BitUInt(fileInfoSource.nFileSizeLow, fileInfoSource.nFileSizeHigh); - newAttrib.modificationTime = filetimeToTimeT(fileInfoSource.ftLastWriteTime); //no DST hack (yet) + newAttrib.modificationTime = filetimeToTimeT(fileInfoSource.ftLastWriteTime); newAttrib.sourceFileId = extractFileId(fileInfoSource); newAttrib.targetFileId = extractFileId(fileInfoTarget); diff --git a/zen/file_io.cpp b/zen/file_io.cpp index 5e8b7a1d..b385ce33 100644 --- a/zen/file_io.cpp +++ b/zen/file_io.cpp @@ -79,11 +79,11 @@ FileInput::FileInput(const Zstring& filepath) : //throw FileError, ErrorFileLock auto createHandle = [&](DWORD dwShareMode) { return ::CreateFile(applyLongPathPrefix(filepath).c_str(), //_In_ LPCTSTR lpFileName, - GENERIC_READ, //_In_ DWORD dwDesiredAccess, - dwShareMode, //_In_ DWORD dwShareMode, - nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, - OPEN_EXISTING, //_In_ DWORD dwCreationDisposition, - FILE_FLAG_SEQUENTIAL_SCAN //_In_ DWORD dwFlagsAndAttributes, + GENERIC_READ, //_In_ DWORD dwDesiredAccess, + dwShareMode, //_In_ DWORD dwShareMode, + nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + OPEN_EXISTING, //_In_ DWORD dwCreationDisposition, + FILE_FLAG_SEQUENTIAL_SCAN | //_In_ DWORD dwFlagsAndAttributes, /* possible values: (Reference http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx#caching_behavior) FILE_FLAG_NO_BUFFERING FILE_FLAG_RANDOM_ACCESS @@ -108,7 +108,7 @@ FileInput::FileInput(const Zstring& filepath) : //throw FileError, ErrorFileLock for FFS most comparisons are probably between different disks => let's use FILE_FLAG_SEQUENTIAL_SCAN */ - | FILE_FLAG_BACKUP_SEMANTICS, + FILE_FLAG_BACKUP_SEMANTICS, nullptr); //_In_opt_ HANDLE hTemplateFile }; fileHandle = createHandle(FILE_SHARE_READ | FILE_SHARE_DELETE); @@ -249,8 +249,8 @@ FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw Fil nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, dwCreationDisposition, //_In_ DWORD dwCreationDisposition, dwFlagsAndAttributes | - FILE_FLAG_SEQUENTIAL_SCAN //_In_ DWORD dwFlagsAndAttributes, - | FILE_FLAG_BACKUP_SEMANTICS, + FILE_FLAG_SEQUENTIAL_SCAN | //_In_ DWORD dwFlagsAndAttributes, + FILE_FLAG_BACKUP_SEMANTICS, nullptr); //_In_opt_ HANDLE hTemplateFile }; @@ -298,7 +298,7 @@ FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw Fil //checkForUnsupportedType(filepath); -> not needed, open() + O_WRONLY should fail fast fileHandle = ::open(filepath.c_str(), O_WRONLY | O_CREAT | (access == FileOutput::ACC_CREATE_NEW ? O_EXCL : O_TRUNC), - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); //0666 if (fileHandle == -1) { const int ec = errno; //copy before making other system calls! diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp index e9c686aa..cfaaa329 100644 --- a/zen/format_unit.cpp +++ b/zen/format_unit.cpp @@ -194,7 +194,7 @@ class IntegerFormat { public: static const NUMBERFMT& get() { return getInst().fmt; } - static bool isValid() { return getInst().valid_; } + static bool isValid() { return getInst().valid; } private: static const IntegerFormat& getInst() @@ -202,7 +202,7 @@ private: #if defined _MSC_VER && _MSC_VER < 1900 #error function scope static initialization is not yet thread-safe! #endif - static IntegerFormat inst; + static const IntegerFormat inst; return inst; } @@ -229,14 +229,14 @@ private: else grouping += L'0'; fmt.Grouping = stringTo<UINT>(grouping); - valid_ = true; + valid = true; } } NUMBERFMT fmt = {}; std::wstring thousandSep; std::wstring decimalSep; - bool valid_ = false; + bool valid = false; }; } #endif @@ -99,7 +99,7 @@ std::wstring translate(const std::wstring& singular, const std::wstring& plural, inline -std::unique_ptr<const TranslationHandler>& globalHandler() +std::unique_ptr<const TranslationHandler>& globalTranslationHandler() { static std::unique_ptr<const TranslationHandler> inst; //external linkage even in header! return inst; @@ -108,11 +108,11 @@ std::unique_ptr<const TranslationHandler>& globalHandler() inline -void setTranslator(std::unique_ptr<const TranslationHandler>&& newHandler) { implementation::globalHandler() = std::move(newHandler); } +void setTranslator(std::unique_ptr<const TranslationHandler>&& newHandler) { implementation::globalTranslationHandler() = std::move(newHandler); } inline -const TranslationHandler* getTranslator() { return implementation::globalHandler().get(); } +const TranslationHandler* getTranslator() { return implementation::globalTranslationHandler().get(); } } #endif //I18_N_H_3843489325044253425456 diff --git a/zen/scope_guard.h b/zen/scope_guard.h index 791764de..1345447e 100644 --- a/zen/scope_guard.h +++ b/zen/scope_guard.h @@ -73,11 +73,11 @@ public: ~ScopeGuard() noexcept(runMode != ScopeGuardRunMode::ON_SUCCESS) { + if (!dismissed) + { #ifdef _MSC_VER #pragma warning(suppress: 4127) //"conditional expression is constant" #endif - if (!dismissed) - { if (runMode != ScopeGuardRunMode::ON_EXIT) { const bool failed = getUncaughtExceptionCount() > exeptionCount; @@ -85,6 +85,9 @@ public: return; } +#ifdef _MSC_VER + #pragma warning(suppress: 4127) //"conditional expression is constant" +#endif if (runMode == ScopeGuardRunMode::ON_SUCCESS) fun_(); //throw X else diff --git a/zen/thread.h b/zen/thread.h index bb6e7901..700d42dc 100644 --- a/zen/thread.h +++ b/zen/thread.h @@ -13,7 +13,7 @@ #include "type_traits.h" #include "optional.h" #ifdef ZEN_WIN -#include "win.h" + #include "win.h" #endif @@ -63,7 +63,7 @@ template <class Rep, class Period> void interruptibleSleep(const std::chrono::duration<Rep, Period>& relTime); //throw ThreadInterruption #ifdef ZEN_WIN -void setCurrentThreadName(const char* threadName); + void setCurrentThreadName(const char* threadName); #endif //------------------------------------------------------------------------------------------ @@ -421,10 +421,10 @@ void InterruptibleThread::interrupt() { intStatus_->interrupt(); } #pragma pack(push,8) struct THREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. }; #pragma pack(pop) @@ -432,18 +432,18 @@ struct THREADNAME_INFO inline void setCurrentThreadName(const char* threadName) { -const DWORD MS_VC_EXCEPTION = 0x406D1388; - -THREADNAME_INFO info = {}; - info.dwType = 0x1000; - info.szName = threadName; - info.dwThreadID = GetCurrentThreadId(); - - __try - { - ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info)); - } - __except(EXCEPTION_EXECUTE_HANDLER){} + const DWORD MS_VC_EXCEPTION = 0x406D1388; + + THREADNAME_INFO info = {}; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = GetCurrentThreadId(); + + __try + { + ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info)); + } + __except (EXCEPTION_EXECUTE_HANDLER) {} } #endif } diff --git a/zen/type_traits.h b/zen/type_traits.h index ac7f1a42..c0da43ed 100644 --- a/zen/type_traits.h +++ b/zen/type_traits.h @@ -38,11 +38,8 @@ struct ResultType }; //Herb Sutter's signedness conversion helpers: http://herbsutter.com/2013/06/13/gotw-93-solution-auto-variables-part-2/ -template<class T> inline -typename std::make_signed<T>::type makeSigned(T t) { return static_cast<std::make_signed_t<T>>(t); } - -template<class T> inline -typename std::make_unsigned<T>::type makeUnsigned(T t) { return static_cast<std::make_unsigned_t<T>>(t); } +template<class T> inline auto makeSigned (T t) { return static_cast<std::make_signed_t <T>>(t); } +template<class T> inline auto makeUnsigned(T t) { return static_cast<std::make_unsigned_t<T>>(t); } //################# Built-in Types ######################## //Example: "IsSignedInt<int>::value" evaluates to "true" @@ -62,7 +59,7 @@ template <class T> struct IsArithmetic; //IsInteger or IsFloat /* Detect data or function members of a class by name: ZEN_INIT_DETECT_MEMBER + HasMember_ Example: 1. ZEN_INIT_DETECT_MEMBER(c_str); - 2. HasMember_c_str<T>::value -> use as boolean + 2. HasMember_c_str<T>::value -> use boolean */ /* Detect data or function members of a class by name *and* type: ZEN_INIT_DETECT_MEMBER2 + HasMember_ |