From dbb46788aafdd0d55454a8be483743876c83b33e Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 2 Oct 2015 14:56:44 +0200 Subject: 7.4 --- zen/async_task.h | 1 + zen/dir_watcher.h | 1 + zen/error_log.h | 1 + zen/file_access.cpp | 31 ++++++++------- zen/file_access.h | 1 + zen/file_traverser.h | 1 + zen/format_unit.h | 1 + zen/long_path_prefix.h | 1 + zen/process_priority.h | 1 + zen/recycler.h | 1 + zen/serialize.h | 1 + zen/stl_tools.h | 100 ++++++++++++++++++++++++++----------------------- zen/symlink_target.h | 8 ++-- zen/time.h | 1 + zen/type_tools.h | 1 + 15 files changed, 87 insertions(+), 64 deletions(-) (limited to 'zen') diff --git a/zen/async_task.h b/zen/async_task.h index d8f489a3..76e7824f 100644 --- a/zen/async_task.h +++ b/zen/async_task.h @@ -12,6 +12,7 @@ #include "thread.h" #include "scope_guard.h" + namespace zen { //run a job in an async thread, but process result on GUI event loop diff --git a/zen/dir_watcher.h b/zen/dir_watcher.h index cdc80165..7a1ada96 100644 --- a/zen/dir_watcher.h +++ b/zen/dir_watcher.h @@ -12,6 +12,7 @@ #include #include "file_error.h" + namespace zen { //Windows: ReadDirectoryChangesW http://msdn.microsoft.com/en-us/library/aa365465(v=vs.85).aspx diff --git a/zen/error_log.h b/zen/error_log.h index 9814ec23..81892a25 100644 --- a/zen/error_log.h +++ b/zen/error_log.h @@ -15,6 +15,7 @@ #include "i18n.h" #include "string_base.h" + namespace zen { enum MessageType diff --git a/zen/file_access.cpp b/zen/file_access.cpp index 84d3b264..c898c5d2 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -435,29 +435,34 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro if (lastError == ERROR_NOT_SAME_DEVICE) throw ErrorDifferentVolume(errorMsg, errorDescr); if (lastError == ERROR_ALREADY_EXISTS || //-> used on Win7 x64 - lastError == ERROR_FILE_EXISTS) //-> used by XP??? + lastError == ERROR_FILE_EXISTS) //-> used by XP??? throw ErrorTargetExisting(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); } #elif defined ZEN_LINUX || defined ZEN_MAC //rename() will never fail with EEXIST, but always overwrite! - //=> OS X: no solution //=> Linux: renameat2() with RENAME_NOREPLACE -> still new, probably buggy - const bool alreadyExists = somethingExists(pathTarget); //we have to let go of atomicity! + //=> OS X: no solution - if (alreadyExists || ::rename(pathSource.c_str(), pathTarget.c_str()) != 0) - { - const int lastError = alreadyExists ? EEXIST : errno; //copy before directly or indirectly making other system calls! + auto throwException = [&](int ec) + { const std::wstring errorMsg = replaceCpy(replaceCpy(_("Cannot move file %x to %y."), L"%x", L"\n" + fmtPath(pathSource)), L"%y", L"\n" + fmtPath(pathTarget)); - const std::wstring errorDescr = formatSystemError(L"rename", lastError); + const std::wstring errorDescr = formatSystemError(L"rename", ec); - if (lastError == EXDEV) + if (ec == EXDEV) throw ErrorDifferentVolume(errorMsg, errorDescr); - if (lastError == EEXIST) + if (ec == EEXIST) throw ErrorTargetExisting(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); - } + }; + + if (!EqualFilePath()(pathSource, pathTarget)) //OS X: changing file name case is not an "already exists" error! + if (somethingExists(pathTarget)) + throwException(EEXIST); + + if (::rename(pathSource.c_str(), pathTarget.c_str()) != 0) + throwException(errno); #endif } @@ -1084,9 +1089,9 @@ void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, P //in contrast to ::SetSecurityInfo(), ::SetFileSecurity() seems to honor the "inherit DACL/SACL" flags //CAVEAT: if a file system does not support ACLs, GetFileSecurity() will return successfully with a *valid* security descriptor containing *no* ACL entries! - //NOTE: ::GetFileSecurity()/::SetFileSecurity() do NOT follow Symlinks! getResolvedFilePath() requires Vista or later! - const Zstring sourceResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(sourcePath) ? getResolvedFilePath(sourcePath) : sourcePath; //throw FileError - const Zstring targetResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(targetPath) ? getResolvedFilePath(targetPath) : targetPath; // + //NOTE: ::GetFileSecurity()/::SetFileSecurity() do NOT follow Symlinks! getResolvedSymlinkPath() requires Vista or later! + const Zstring sourceResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(sourcePath) ? getResolvedSymlinkPath(sourcePath) : sourcePath; //throw FileError + const Zstring targetResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(targetPath) ? getResolvedSymlinkPath(targetPath) : targetPath; // //setting privileges requires admin rights! try diff --git a/zen/file_access.h b/zen/file_access.h index 4b1c31dd..3588f79b 100644 --- a/zen/file_access.h +++ b/zen/file_access.h @@ -12,6 +12,7 @@ #include "file_error.h" #include "file_id_def.h" + namespace zen { bool fileExists (const Zstring& filePath); //noexcept; check whether file or file-symlink exists diff --git a/zen/file_traverser.h b/zen/file_traverser.h index 9cba9e58..3f8030d3 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -11,6 +11,7 @@ #include #include "zstring.h" + namespace zen { struct FileInfo diff --git a/zen/format_unit.h b/zen/format_unit.h index 009199f6..d50baa32 100644 --- a/zen/format_unit.h +++ b/zen/format_unit.h @@ -11,6 +11,7 @@ #include #include "string_tools.h" + namespace zen { std::wstring filesizeToShortString(std::int64_t filesize); diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h index 3db2722b..4b79e051 100644 --- a/zen/long_path_prefix.h +++ b/zen/long_path_prefix.h @@ -10,6 +10,7 @@ #include "win.h" #include "zstring.h" + namespace zen { //handle filepaths longer-equal 260 (== MAX_PATH) characters by applying \\?\-prefix; see: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath diff --git a/zen/process_priority.h b/zen/process_priority.h index 3e217776..72ce972c 100644 --- a/zen/process_priority.h +++ b/zen/process_priority.h @@ -9,6 +9,7 @@ #include #include "file_error.h" + namespace zen { //signal a "busy" state to the operating system diff --git a/zen/recycler.h b/zen/recycler.h index 61a721cd..7c63cf8a 100644 --- a/zen/recycler.h +++ b/zen/recycler.h @@ -11,6 +11,7 @@ #include #include "file_error.h" + namespace zen { /* diff --git a/zen/serialize.h b/zen/serialize.h index a41745e4..07d9362c 100644 --- a/zen/serialize.h +++ b/zen/serialize.h @@ -12,6 +12,7 @@ #include "string_base.h" #include "file_io.h" + namespace zen { //high-performance unformatted serialization (avoiding wxMemoryOutputStream/wxMemoryInputStream inefficiencies) diff --git a/zen/stl_tools.h b/zen/stl_tools.h index 685f5118..e949c5c9 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -7,36 +7,42 @@ #ifndef STL_TOOLS_HEADER_84567184321434 #define STL_TOOLS_HEADER_84567184321434 +#include +#include +#include #include #include #include "type_tools.h" - //enhancements for namespace zen { -//idomatic remove selected elements from container -template -void vector_remove_if(V& vec, Predicate p); +//erase selected elements from any container: +template +void erase_if(std::vector& v, Predicate p); -template -void vector_append(V& vec, const W& vec2); +template +void erase_if(std::set& s, Predicate p); -template -void removeDuplicates(V& v); +template +void erase_if(std::map& m, Predicate p); -template -void set_append(V& s, const W& s2); +//append STL containers +template +void append(std::vector& v, const C& c); -template -void set_remove_if(S& set, Predicate p); +template +void append(std::set& s, const C& c); -template -void map_remove_if(M& map, Predicate p); +template +void append(std::map& m, const C& c); template V& map_add_or_update(M& map, const K& key, const V& value); //efficient add or update without "default-constructible" requirement (Effective STL, item 24) +template +void removeDuplicates(std::vector& v); + //binary search returning an iterator template ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, CompLess less); @@ -67,52 +73,45 @@ std::unique_ptr make_unique(Args&& ... args) { return std::unique_ptr(new //######################## implementation ######################## -template inline -void vector_remove_if(V& vec, Predicate p) +template inline +void erase_if(std::vector& v, Predicate p) { - static_assert(IsSameType::iterator_category, std::random_access_iterator_tag>::value, "poor man's check for vector"); - vec.erase(std::remove_if(vec.begin(), vec.end(), p), vec.end()); + v.erase(std::remove_if(v.begin(), v.end(), p), v.end()); } -template inline -void removeDuplicates(V& v) +namespace impl { - std::sort(v.begin(), v.end()); - v.erase(std::unique(v.begin(), v.end()), v.end()); +template inline +void set_or_map_erase_if(S& s, Predicate p) +{ + for (auto iter = s.begin(); iter != s.end();) + if (p(*iter)) + s.erase(iter++); + else + ++iter; +} } -template inline -void vector_append(V& vec, const W& vec2) -{ - vec.insert(vec.end(), vec2.begin(), vec2.end()); -} +template inline +void erase_if(std::set& s, Predicate p) { impl::set_or_map_erase_if(s, p); } //don't make this any more generic! e.g. must not compile for std::vector!!! -template inline -void set_append(V& s, const W& s2) -{ - s.insert(s2.begin(), s2.end()); -} +template inline +void erase_if(std::map& m, Predicate p) { impl::set_or_map_erase_if(m, p); } -template inline -void set_remove_if(S& set, Predicate p) -{ - //function compiles and fails (if we're lucky) not before runtime for std::vector!!! - static_assert(!IsSameType::iterator_category, std::random_access_iterator_tag>::value, "poor man's check for non-vector"); +template inline +void append(std::vector& v, const C& c) { v.insert(v.end(), c.begin(), c.end()); } - for (auto iter = set.begin(); iter != set.end();) - if (p(*iter)) - set.erase(iter++); - else - ++iter; -} + +template inline +void append(std::set& s, const C& c) { s.insert(c.begin(), c.end()); } -template inline -void map_remove_if(M& map, Predicate p) { set_remove_if(map, p); } +template inline +void append(std::map& m, const C& c) { m.insert(c.begin(), c.end()); } template inline @@ -129,6 +128,14 @@ V& map_add_or_update(M& map, const K& key, const V& value) //efficient add or up } +template inline +void removeDuplicates(std::vector& v) +{ + std::sort(v.begin(), v.end()); + v.erase(std::unique(v.begin(), v.end()), v.end()); +} + + template inline ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, CompLess less) { @@ -190,8 +197,7 @@ bool equal(InputIterator1 first1, InputIterator1 last1, #if defined _MSC_VER && _MSC_VER <= 1600 - //VS2010 performance bug in std::unordered_set<>: http://drdobbs.com/blogs/cpp/232200410 -> should be fixed in VS11 - static_assert(false, ""); + static_assert(false, "VS2010 performance bug in std::unordered_set<>: http://drdobbs.com/blogs/cpp/232200410 -> should be fixed in VS11"); #endif } diff --git a/zen/symlink_target.h b/zen/symlink_target.h index aa320dfe..c4557559 100644 --- a/zen/symlink_target.h +++ b/zen/symlink_target.h @@ -29,8 +29,8 @@ namespace zen bool isSymlink(DWORD fileAttributes, DWORD reparseTag); #endif -Zstring getResolvedFilePath(const Zstring& linkPath); //throw FileError; Win: requires Vista or later! -Zstring getSymlinkTargetRaw(const Zstring& linkPath); //throw FileError +Zstring getResolvedSymlinkPath(const Zstring& linkPath); //throw FileError; Win: requires Vista or later! +Zstring getSymlinkTargetRaw (const Zstring& linkPath); //throw FileError } @@ -153,7 +153,7 @@ Zstring getSymlinkRawTargetString_impl(const Zstring& linkPath) //throw FileErro } -Zstring getResolvedFilePath_impl(const Zstring& linkPath) //throw FileError +Zstring getResolvedSymlinkPath_impl(const Zstring& linkPath) //throw FileError { using namespace zen; #ifdef ZEN_WIN @@ -211,7 +211,7 @@ inline Zstring getSymlinkTargetRaw(const Zstring& linkPath) { return getSymlinkRawTargetString_impl(linkPath); } inline -Zstring getResolvedFilePath(const Zstring& linkPath) { return getResolvedFilePath_impl(linkPath); } +Zstring getResolvedSymlinkPath(const Zstring& linkPath) { return getResolvedSymlinkPath_impl(linkPath); } #ifdef ZEN_WIN /* diff --git a/zen/time.h b/zen/time.h index 9d821a1f..df0f3a54 100644 --- a/zen/time.h +++ b/zen/time.h @@ -10,6 +10,7 @@ #include #include "string_tools.h" + namespace zen { struct TimeComp //replaces "struct std::tm" and SYSTEMTIME diff --git a/zen/type_tools.h b/zen/type_tools.h index ac365f05..31384d4c 100644 --- a/zen/type_tools.h +++ b/zen/type_tools.h @@ -9,6 +9,7 @@ #include "type_traits.h" + namespace zen { //########## Strawman Classes ########################## -- cgit