summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:26:50 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:26:50 +0200
commit669df123648aaa6aeccc70206b5417bc48b4e9ae (patch)
tree463c107a8d6405020bb304f7a7253e6b64afeee0 /zen
parent5.18 (diff)
downloadFreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.tar.gz
FreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.tar.bz2
FreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.zip
5.19
Diffstat (limited to 'zen')
-rw-r--r--zen/FindFilePlus/FindFilePlus.vcxproj4
-rw-r--r--zen/FindFilePlus/find_file_plus.cpp38
-rw-r--r--zen/basic_math.h9
-rw-r--r--zen/dir_watcher.cpp12
-rw-r--r--zen/dir_watcher.h4
-rw-r--r--zen/file_error.h1
-rw-r--r--zen/file_handling.cpp90
-rw-r--r--zen/file_handling.h9
-rw-r--r--zen/file_io.cpp26
-rw-r--r--zen/file_io.h4
-rw-r--r--zen/format_unit.cpp50
-rw-r--r--zen/format_unit.h13
-rw-r--r--zen/i18n.h1
-rw-r--r--zen/long_path_prefix.h5
-rw-r--r--zen/optional.h1
-rw-r--r--zen/serialize.h6
-rw-r--r--zen/stl_tools.h3
-rw-r--r--zen/string_base.h61
-rw-r--r--zen/sys_error.h18
-rw-r--r--zen/thread.h3
-rw-r--r--zen/type_tools.h4
-rw-r--r--zen/type_traits.h15
-rw-r--r--zen/win.h1
-rw-r--r--zen/zstring.cpp8
-rw-r--r--zen/zstring.h10
25 files changed, 195 insertions, 201 deletions
diff --git a/zen/FindFilePlus/FindFilePlus.vcxproj b/zen/FindFilePlus/FindFilePlus.vcxproj
index d7dfe219..73b7f70e 100644
--- a/zen/FindFilePlus/FindFilePlus.vcxproj
+++ b/zen/FindFilePlus/FindFilePlus.vcxproj
@@ -172,7 +172,7 @@
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -209,7 +209,7 @@
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
diff --git a/zen/FindFilePlus/find_file_plus.cpp b/zen/FindFilePlus/find_file_plus.cpp
index fdabc46f..ea58005e 100644
--- a/zen/FindFilePlus/find_file_plus.cpp
+++ b/zen/FindFilePlus/find_file_plus.cpp
@@ -113,10 +113,10 @@ public:
FileSearcher(const wchar_t* dirname); //throw NtFileError
~FileSearcher();
- void readDir(FileInformation& output); //throw NtFileError
+ bool readDir(FileInformation& output); //throw NtFileError; returns false if "no more files"
private:
- template <class QueryPolicy> void readDirImpl(FileInformation& output); //throw NtFileError
+ template <class QueryPolicy> bool readDirImpl(FileInformation& output); //throw NtFileError
UNICODE_STRING dirnameNt; //it seems hDir implicitly keeps a reference to this, at least ::FindFirstFile() does no cleanup before ::FindClose()!
HANDLE hDir;
@@ -271,11 +271,11 @@ struct DirQueryFileId
inline
-void FileSearcher::readDir(FileInformation& output) { readDirImpl<DirQueryFileId>(output); } //throw NtFileError
+bool FileSearcher::readDir(FileInformation& output) { return readDirImpl<DirQueryFileId>(output); } //throw NtFileError
template <class QueryPolicy>
-void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
+bool FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError; returns false if "no more files"
{
//although FILE_ID_FULL_DIR_INFORMATION should suffice for our purposes, there are problems on Windows XP for certain directories, e.g. "\\Vboxsvr\build"
//making NtQueryDirectoryFile() return with STATUS_INVALID_PARAMETER while other directories, e.g. "C:\" work fine for some reason
@@ -337,25 +337,30 @@ void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
STATUS_NO_SUCH_FILE is abused by some citrix shares instead of "STATUS_INVALID_PARAMETER" so we treat it as such!
=> since the directory is "truly empty" a fallback won't hurt
*/
- if (rv == STATUS_INVALID_LEVEL ||
- rv == STATUS_NOT_SUPPORTED ||
+ if (rv == STATUS_NO_MORE_FILES) //perf: don't throw an exception in this common case! => 8% perf boost for FFS comparison phase!
+ return false;
+
+ if (rv == STATUS_NOT_SUPPORTED ||
+ rv == STATUS_INVALID_LEVEL ||
+ rv == STATUS_NO_SUCH_FILE || //[!]
rv == STATUS_UNEXPECTED_NETWORK_ERROR ||
rv == STATUS_INVALID_PARAMETER ||
rv == STATUS_INVALID_NETWORK_RESPONSE ||
rv == STATUS_INVALID_INFO_CLASS ||
+ //rv == STATUS_NOT_IMPLEMENTED || -> first confirm that these codes
+ //rv == STATUS_INVALID_DEVICE_REQUEST || -> are in fact used!
rv == STATUS_UNSUCCESSFUL ||
- rv == STATUS_ACCESS_VIOLATION ||
- rv == STATUS_NO_SUCH_FILE) //[!]
+ rv == STATUS_ACCESS_VIOLATION)
rv = STATUS_NOT_SUPPORTED;
throw NtFileError(rv); //throws STATUS_NO_MORE_FILES when finished
}
- //for (NTSTATUS i = 0xC0000000L; i != -1; ++i)
- //{
- // if (rtlNtStatusToDosError(i) == 59) //ERROR_UNEXP_NET_ERR
- // __asm int 3;
- //}
+ // for (NTSTATUS i = 0xC0000000L; i != -1; ++i)
+ // {
+ // if (rtlNtStatusToDosError(i) == 59) //ERROR_UNEXP_NET_ERR
+ // __debugbreak(); //__asm int 3;
+ // }
if (status.Information == 0) //except for the first call to call ::NtQueryDirectoryFile():
throw NtFileError(STATUS_BUFFER_OVERFLOW); //if buffer size is too small, return value is STATUS_SUCCESS and Information == 0 -> we don't expect this!
@@ -399,6 +404,7 @@ void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
static_assert(sizeof(output.lastWriteTime) == sizeof(dirInfo.LastWriteTime), "dang!");
static_assert(sizeof(output.fileSize) == sizeof(dirInfo.EndOfFile), "dang!");
static_assert(sizeof(output.fileAttributes) == sizeof(dirInfo.FileAttributes), "dang!");
+ return true;
}
@@ -425,7 +431,11 @@ bool findplus::readDir(FindHandle hnd, FileInformation& output)
{
try
{
- hnd->readDir(output); //throw NtFileError
+ if (!hnd->readDir(output)) //throw NtFileError
+ {
+ setWin32Error(rtlNtStatusToDosError(STATUS_NO_MORE_FILES));
+ return false;
+ }
return true;
}
catch (const NtFileError& e)
diff --git a/zen/basic_math.h b/zen/basic_math.h
index f01421c7..05d892ee 100644
--- a/zen/basic_math.h
+++ b/zen/basic_math.h
@@ -36,11 +36,6 @@ void confine(T& val, const T& minVal, const T& maxVal); //make sure minVal <= va
template <class T>
T confineCpy(const T& val, const T& minVal, const T& maxVal);
-template <class InputIterator>
-std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, InputIterator last);
-template <class InputIterator, class Compare>
-std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, InputIterator last, Compare comp);
-
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;
@@ -160,6 +155,8 @@ void confine(T& val, const T& minVal, const T& maxVal) //name trim, clamp?
}
+/*
+part of C++11 now!
template <class InputIterator, class Compare> inline
std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, InputIterator last, Compare compLess)
{
@@ -200,7 +197,7 @@ std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, Input
{
return minMaxElement(first, last, std::less<typename std::iterator_traits<InputIterator>::value_type>());
}
-
+*/
template <class T, class InputIterator> inline
auto nearMatch(const T& val, InputIterator first, InputIterator last) -> typename std::iterator_traits<InputIterator>::value_type
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index a800fb80..e53b63e2 100644
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -96,7 +96,7 @@ public:
//context of main thread
- void getChanges(std::vector<DirWatcher::Entry>& output) //throw FileError, ErrorNotExisting
+ void getChanges(std::vector<DirWatcher::Entry>& output) //throw FileError
{
boost::lock_guard<boost::mutex> dummy(lockAccess);
@@ -105,9 +105,6 @@ public:
{
const std::wstring msg = copyStringTo<std::wstring>(errorInfo->msg);
const std::wstring descr = copyStringTo<std::wstring>(errorInfo->descr);
-
- if (errorCodeForNotExisting(errorInfo->errorCode))
- throw ErrorNotExisting(msg, descr);
throw FileError(msg, descr);
}
@@ -163,9 +160,6 @@ public:
const DWORD lastError = ::GetLastError(); //copy before making other system calls!
const std::wstring errorMsg = replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(directory));
const std::wstring errorDescr = formatSystemError(L"CreateFile", lastError);
-
- if (errorCodeForNotExisting(lastError))
- throw ErrorNotExisting(errorMsg, errorDescr);
throw FileError(errorMsg, errorDescr);
}
@@ -199,7 +193,6 @@ public:
const DWORD lastError = ::GetLastError(); //copy before making other system calls!
return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirnamePf)), formatSystemError(L"CreateEvent", lastError), lastError);
}
-
ZEN_ON_SCOPE_EXIT(::CloseHandle(overlapped.hEvent));
DWORD bytesReturned = 0; //should not be needed for async calls, still pass it to help broken drivers
@@ -465,9 +458,6 @@ DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError
const ErrorCode lastError = getLastError(); //copy before making other system calls!
const std::wstring errorMsg = replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(subdir));
const std::wstring errorDescr = formatSystemError(L"inotify_add_watch", lastError);
-
- if (errorCodeForNotExisting(lastError))
- throw ErrorNotExisting(errorMsg, errorDescr);
throw FileError(errorMsg, errorDescr);
}
diff --git a/zen/dir_watcher.h b/zen/dir_watcher.h
index b0df48bd..eaee5aab 100644
--- a/zen/dir_watcher.h
+++ b/zen/dir_watcher.h
@@ -27,12 +27,12 @@ namespace zen
Renaming of top watched directory handled incorrectly: Not notified(!) + additional changes in subfolders
now do report FILE_ACTION_MODIFIED for directory (check that should prevent this fails!)
- Overcome all issues portably: check existence of top watched directory externally + reinstall watch after changes in directory structure (added directories) are possible
+ Overcome all issues portably: check existence of top watched directory externally + reinstall watch after changes in directory structure (added directories) are detected
*/
class DirWatcher
{
public:
- DirWatcher(const Zstring& directory); //throw FileError, ErrorNotExisting
+ DirWatcher(const Zstring& directory); //throw FileError
~DirWatcher();
enum ActionType
diff --git a/zen/file_error.h b/zen/file_error.h
index 71619834..db8b371d 100644
--- a/zen/file_error.h
+++ b/zen/file_error.h
@@ -30,7 +30,6 @@ private:
#define DEFINE_NEW_FILE_ERROR(X) struct X : public FileError { X(const std::wstring& msg) : FileError(msg) {} X(const std::wstring& msg, const std::wstring& descr) : FileError(msg, descr) {} };
-DEFINE_NEW_FILE_ERROR(ErrorNotExisting);
DEFINE_NEW_FILE_ERROR(ErrorTargetExisting);
DEFINE_NEW_FILE_ERROR(ErrorTargetPathMissing);
DEFINE_NEW_FILE_ERROR(ErrorFileLocked);
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp
index 398e88e8..103a39f7 100644
--- a/zen/file_handling.cpp
+++ b/zen/file_handling.cpp
@@ -45,67 +45,111 @@
using namespace zen;
+warn_static("remove after test")
-bool zen::fileExists(const Zstring& filename)
+namespace
+{
+void writeSysErrorIfNeeded(std::wstring* sysErrorMsg, const wchar_t* functionName, ErrorCode lastError)
+{
+ if (sysErrorMsg)
+ {
+ //skip uninteresting error codes:
+#ifdef ZEN_WIN
+ if (lastError == ERROR_FILE_NOT_FOUND ||
+ lastError == ERROR_PATH_NOT_FOUND) return;
+ //lastError == ERROR_BAD_NETPATH || //e.g. for a path like: \\192.168.1.1\test
+ //lastError == ERROR_NETNAME_DELETED;
+
+#elif defined ZEN_LINUX || defined ZEN_MAC
+ if (lastError == ENOENT) return;
+#endif
+ *sysErrorMsg = formatSystemError(functionName, lastError);
+ }
+}
+}
+
+
+bool zen::fileExists(const Zstring& filename, std::wstring* sysErrorMsg)
{
//symbolic links (broken or not) are also treated as existing files!
#ifdef ZEN_WIN
+ const wchar_t functionName[] = L"GetFileAttributes";
const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(filename).c_str());
- return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0; //returns true for (file-)symlinks also
+ if (attr != INVALID_FILE_ATTRIBUTES)
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0; //returns true for (file-)symlinks also
#elif defined ZEN_LINUX || defined ZEN_MAC
+ const wchar_t functionName[] = L"lstat";
struct ::stat fileInfo = {};
- return ::lstat(filename.c_str(), &fileInfo) == 0 &&
- (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode)); //in Linux a symbolic link is neither file nor directory
+ if (::lstat(filename.c_str(), &fileInfo) == 0)
+ return S_ISREG(fileInfo.st_mode) || S_ISLNK(fileInfo.st_mode); //in Linux a symbolic link is neither file nor directory
#endif
+ writeSysErrorIfNeeded(sysErrorMsg, functionName, getLastError());
+ return false;
}
-bool zen::dirExists(const Zstring& dirname)
+bool zen::dirExists(const Zstring& dirname, std::wstring* sysErrorMsg)
{
//symbolic links (broken or not) are also treated as existing directories!
#ifdef ZEN_WIN
+ const wchar_t functionName[] = L"GetFileAttributes";
const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(dirname).c_str());
- return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; //returns true for (dir-)symlinks also
+ if (attr != INVALID_FILE_ATTRIBUTES)
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; //returns true for (dir-)symlinks also
#elif defined ZEN_LINUX || defined ZEN_MAC
+ const wchar_t functionName[] = L"lstat";
struct ::stat dirInfo = {};
- return ::lstat(dirname.c_str(), &dirInfo) == 0 &&
- (S_ISLNK(dirInfo.st_mode) || S_ISDIR(dirInfo.st_mode)); //in Linux a symbolic link is neither file nor directory
+ if (::lstat(dirname.c_str(), &dirInfo) == 0)
+ return S_ISDIR(dirInfo.st_mode) || S_ISLNK(dirInfo.st_mode); //in Linux a symbolic link is neither file nor directory
#endif
+ writeSysErrorIfNeeded(sysErrorMsg, functionName, getLastError());
+ return false;
}
-bool zen::symlinkExists(const Zstring& linkname)
+bool zen::symlinkExists(const Zstring& linkname, std::wstring* sysErrorMsg)
{
#ifdef ZEN_WIN
- WIN32_FIND_DATA fileInfo = {};
+ const wchar_t functionName[] = L"FindFirstFile";
+ WIN32_FIND_DATA linkInfo = {};
+ const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(linkname).c_str(), &linkInfo);
+ if (searchHandle != INVALID_HANDLE_VALUE)
{
- const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(linkname).c_str(), &fileInfo);
- if (searchHandle == INVALID_HANDLE_VALUE)
- return false;
::FindClose(searchHandle);
+ return isSymlink(linkInfo);
}
- return isSymlink(fileInfo);
#elif defined ZEN_LINUX || defined ZEN_MAC
- struct ::stat fileInfo = {};
- return ::lstat(linkname.c_str(), &fileInfo) == 0 &&
- S_ISLNK(fileInfo.st_mode); //symbolic link
+ const wchar_t functionName[] = L"lstat";
+ struct ::stat linkInfo = {};
+ if (::lstat(linkname.c_str(), &linkInfo) == 0)
+ return S_ISLNK(linkInfo.st_mode);
#endif
+ writeSysErrorIfNeeded(sysErrorMsg, functionName, getLastError());
+ return false;
}
-bool zen::somethingExists(const Zstring& objname)
+bool zen::somethingExists(const Zstring& objname, std::wstring* sysErrorMsg)
{
#ifdef ZEN_WIN
+ const wchar_t functionName[] = L"GetFileAttributes";
const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(objname).c_str());
- return attr != INVALID_FILE_ATTRIBUTES || ::GetLastError() == ERROR_SHARING_VIOLATION; //"C:\pagefile.sys"
+ if (attr != INVALID_FILE_ATTRIBUTES)
+ return true;
+ if (::GetLastError() == ERROR_SHARING_VIOLATION) //"C:\pagefile.sys"
+ return true;
#elif defined ZEN_LINUX || defined ZEN_MAC
+ const wchar_t functionName[] = L"lstat";
struct ::stat fileInfo = {};
- return ::lstat(objname.c_str(), &fileInfo) == 0;
+ if (::lstat(objname.c_str(), &fileInfo) == 0)
+ return true;
#endif
+ writeSysErrorIfNeeded(sysErrorMsg, functionName, getLastError());
+ return false;
}
@@ -275,9 +319,6 @@ bool zen::removeFile(const Zstring& filename) //throw FileError
#endif
{
ErrorCode lastError = getLastError();
- if (errorCodeForNotExisting(lastError)) //no error situation if file is not existing! manual deletion relies on it!
- return false;
-
#ifdef ZEN_WIN
if (lastError == ERROR_ACCESS_DENIED) //function fails if file is read-only
{
@@ -288,7 +329,6 @@ bool zen::removeFile(const Zstring& filename) //throw FileError
lastError = ::GetLastError();
}
#endif
- //after "lastError" evaluation it *may* be redundant to check existence again, but better be safe than sorry:
if (!somethingExists(filename)) //warning: changes global error code!!
return false; //neither file nor any other object (e.g. broken symlink) with that name existing
@@ -2119,7 +2159,7 @@ void copyFileLinuxMac(const Zstring& sourceFile,
FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
{
//open sourceFile for reading
- FileInputUnbuffered fileIn(sourceFile); //throw FileError, ErrorNotExisting
+ FileInputUnbuffered fileIn(sourceFile); //throw FileError
struct ::stat sourceInfo = {};
if (::fstat(fileIn.getDescriptor(), &sourceInfo) != 0) //read file attributes from source
diff --git a/zen/file_handling.h b/zen/file_handling.h
index f677358b..3cb8a68c 100644
--- a/zen/file_handling.h
+++ b/zen/file_handling.h
@@ -18,10 +18,11 @@ struct CallbackRemoveDir;
struct CallbackCopyFile;
-bool fileExists (const Zstring& filename); //noexcept; check whether file *or* (file) symlink exists
-bool dirExists (const Zstring& dirname); //noexcept; check whether directory *or* (dir) symlink exists
-bool symlinkExists (const Zstring& linkname); //noexcept; check whether a symbolic link exists
-bool somethingExists(const Zstring& objname); //noexcept; check whether any object with this name exists
+bool fileExists (const Zstring& filename, std::wstring* sysErrorMsg = nullptr); //noexcept; check whether file *or* (file) symlink exists
+bool dirExists (const Zstring& dirname , std::wstring* sysErrorMsg = nullptr); //noexcept; check whether directory *or* (dir) symlink exists
+bool symlinkExists (const Zstring& linkname, std::wstring* sysErrorMsg = nullptr); //noexcept; check whether a symbolic link exists
+bool somethingExists(const Zstring& objname , std::wstring* sysErrorMsg = nullptr); //noexcept; check whether any object with this name exists
+//sysErrorMsg: optional in + optional out! written only for non-expected errors other than ERROR_FILE_NOT_FOUND/ENOENT, ect...
enum SymLinkType
{
diff --git a/zen/file_io.cpp b/zen/file_io.cpp
index e0f8c12e..45cbd028 100644
--- a/zen/file_io.cpp
+++ b/zen/file_io.cpp
@@ -77,8 +77,7 @@ void checkForUnsupportedType(const Zstring& filename) //throw FileError
FileInput::FileInput(FileHandle handle, const Zstring& filename) : FileInputBase(filename), fileHandle(handle) {}
-FileInput::FileInput(const Zstring& filename) : //throw FileError, ErrorNotExisting
- FileInputBase(filename)
+FileInput::FileInput(const Zstring& filename) : FileInputBase(filename) //throw FileError
{
#ifdef ZEN_WIN
const wchar_t functionName[] = L"CreateFile";
@@ -104,8 +103,8 @@ FileInput::FileInput(const Zstring& filename) : //throw FileError, ErrorNotExist
while FILE_FLAG_RANDOM_ACCESS offers best performance for
- same physical disk (HDD <-> HDD)
- Problem: bad XP implementation of prefetch makes flag FILE_FLAG_SEQUENTIAL_SCAN effectively load two files at once from one drive
- swapping every 64 kB (or similar). File access times explode!
+ Problem: bad XP implementation of prefetch makes flag FILE_FLAG_SEQUENTIAL_SCAN effectively load two files at the same time
+ from one drive, swapping every 64 kB (or similar). File access times explode!
=> For XP it is critical to use FILE_FLAG_RANDOM_ACCESS (to disable prefetch) if reading two files on same disk and
FILE_FLAG_SEQUENTIAL_SCAN when reading from different disk (e.g. massive performance improvement compared to random access for DVD <-> HDD!)
=> there is no compromise that satisfies all cases! (on XP)
@@ -122,9 +121,7 @@ FileInput::FileInput(const Zstring& filename) : //throw FileError, ErrorNotExist
#endif
{
const ErrorCode lastError = getLastError(); //copy before making other system calls!
- const std::wstring errorMsg = errorCodeForNotExisting(lastError) ?
- replaceCpy(_("Cannot find file %x."), L"%x", fmtFileName(filename)) :
- replaceCpy(_("Cannot read file %x."), L"%x", fmtFileName(filename));
+ const std::wstring errorMsg = replaceCpy(_("Cannot open file %x."), L"%x", fmtFileName(filename));
std::wstring errorDescr = formatSystemError(functionName, lastError);
#ifdef ZEN_WIN
@@ -136,10 +133,6 @@ FileInput::FileInput(const Zstring& filename) : //throw FileError, ErrorNotExist
errorDescr = _("The file is locked by another process:") + L"\n" + procList;
}
#endif
-
- if (errorCodeForNotExisting(lastError))
- throw ErrorNotExisting(errorMsg, errorDescr);
-
throw FileError(errorMsg, errorDescr);
}
}
@@ -319,7 +312,7 @@ void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw FileErro
#if defined ZEN_LINUX || defined ZEN_MAC
//Compare copy_reg() in copy.c: ftp://ftp.gnu.org/gnu/coreutils/coreutils-5.0.tar.gz
-FileInputUnbuffered::FileInputUnbuffered(const Zstring& filename) : FileInputBase(filename) //throw FileError, ErrorNotExisting
+FileInputUnbuffered::FileInputUnbuffered(const Zstring& filename) : FileInputBase(filename) //throw FileError
{
checkForUnsupportedType(filename); //throw FileError; reading a named pipe would block forever!
@@ -327,15 +320,8 @@ FileInputUnbuffered::FileInputUnbuffered(const Zstring& filename) : FileInputBas
if (fdFile == -1) //don't check "< 0" -> docu seems to allow "-2" to be a valid file handle
{
const ErrorCode lastError = getLastError(); //copy before making other system calls!
-
- const std::wstring errorMsg = errorCodeForNotExisting(lastError) ?
- replaceCpy(_("Cannot find file %x."), L"%x", fmtFileName(filename)) :
- replaceCpy(_("Cannot read file %x."), L"%x", fmtFileName(filename));
+ const std::wstring errorMsg = replaceCpy(_("Cannot open file %x."), L"%x", fmtFileName(filename));
const std::wstring errorDescr = formatSystemError(L"open", lastError);
-
- if (errorCodeForNotExisting(lastError))
- throw ErrorNotExisting(errorMsg, errorDescr);
-
throw FileError(errorMsg, errorDescr);
}
}
diff --git a/zen/file_io.h b/zen/file_io.h
index 93267a39..0c7506a1 100644
--- a/zen/file_io.h
+++ b/zen/file_io.h
@@ -39,7 +39,7 @@ typedef FILE* FileHandle;
class FileInput : public FileInputBase
{
public:
- FileInput(const Zstring& filename); //throw FileError, ErrorNotExisting
+ FileInput(const Zstring& filename); //throw FileError
FileInput(FileHandle handle, const Zstring& filename); //takes ownership!
~FileInput();
@@ -68,7 +68,7 @@ private:
class FileInputUnbuffered : public FileInputBase
{
public:
- FileInputUnbuffered(const Zstring& filename); //throw FileError, ErrorNotExisting
+ FileInputUnbuffered(const Zstring& filename); //throw FileError
~FileInputUnbuffered();
//considering safe-read.c it seems buffer size should be a multiple of 8192
diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp
index 9e5975d9..4f16e3e1 100644
--- a/zen/format_unit.cpp
+++ b/zen/format_unit.cpp
@@ -24,47 +24,45 @@
using namespace zen;
+std::wstring zen::formatThreeDigitPrecision(double value)
+{
+ //print at least three digits: 0,01 | 0,11 | 1,11 | 11,1 | 111
+ if (numeric::abs(value) < 9.995) //9.999 must not be formatted as "10.00"
+ return printNumber<std::wstring>(L"%.2f", value);
+ if (numeric::abs(value) < 99.95) //99.99 must not be formatted as "100.0"
+ return printNumber<std::wstring>(L"%.1f", value);
+ return numberTo<std::wstring>(numeric::round(value));
+}
+
+
std::wstring zen::filesizeToShortString(Int64 size)
{
//if (size < 0) return _("Error"); -> really?
if (numeric::abs(size) <= 999)
- return replaceCpy(_P("1 Byte", "%x Bytes", to<int>(size)), L"%x", numberTo<std::wstring>(size));
-
- auto formatUnitSize = [](double sizeInUnit, const std::wstring& unitTxt) -> std::wstring
- {
- //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111
- const size_t fullunits = static_cast<size_t>(numeric::abs(sizeInUnit));
- const int precisionDigits = fullunits < 10 ? 2 : fullunits < 100 ? 1 : 0; //sprintf requires "int"
-
- wchar_t buffer[50];
-#ifdef __MINGW32__
- int charsWritten = ::_snwprintf(buffer, 50, L"%.*f", precisionDigits, sizeInUnit); //MinGW does not comply to the C standard here
-#else
- int charsWritten = std::swprintf(buffer, 50, L"%.*f", precisionDigits, sizeInUnit);
-#endif
- return charsWritten > 0 ? replaceCpy(unitTxt, L"%x", std::wstring(buffer, charsWritten)) : _("Error");
- };
+ return replaceCpy(_P("1 byte", "%x bytes", to<int>(size)), L"%x", numberTo<std::wstring>(size));
double sizeInUnit = to<double>(size);
+ auto formatUnit = [&](const std::wstring& unitTxt) { return replaceCpy(unitTxt, L"%x", formatThreeDigitPrecision(sizeInUnit)); };
+
sizeInUnit /= 1024;
- if (numeric::abs(sizeInUnit) <= 999)
- return formatUnitSize(sizeInUnit, _("%x KB"));
+ if (numeric::abs(sizeInUnit) < 999.5)
+ return formatUnit(_("%x KB"));
sizeInUnit /= 1024;
- if (numeric::abs(sizeInUnit) <= 999)
- return formatUnitSize(sizeInUnit, _("%x MB"));
+ if (numeric::abs(sizeInUnit) < 999.5)
+ return formatUnit(_("%x MB"));
sizeInUnit /= 1024;
- if (numeric::abs(sizeInUnit) <= 999)
- return formatUnitSize(sizeInUnit, _("%x GB"));
+ if (numeric::abs(sizeInUnit) < 999.5)
+ return formatUnit(_("%x GB"));
sizeInUnit /= 1024;
- if (numeric::abs(sizeInUnit) <= 999)
- return formatUnitSize(sizeInUnit, _("%x TB"));
+ if (numeric::abs(sizeInUnit) < 999.5)
+ return formatUnit(_("%x TB"));
sizeInUnit /= 1024;
- return formatUnitSize(sizeInUnit, _("%x PB"));
+ return formatUnit(_("%x PB"));
}
@@ -148,7 +146,7 @@ std::wstring zen::remainingTimeToString(double timeInSec)
std::wstring zen::fractionToString(double fraction)
{
- return printNumber<std::wstring>(L"%3.2f", fraction * 100.0) + L'%'; //no need to internationalize fraction!?
+ return printNumber<std::wstring>(L"%.2f", fraction * 100.0) + L'%'; //no need to internationalize fraction!?
}
diff --git a/zen/format_unit.h b/zen/format_unit.h
index 86477999..e3e2d107 100644
--- a/zen/format_unit.h
+++ b/zen/format_unit.h
@@ -16,19 +16,12 @@ namespace zen
std::wstring filesizeToShortString(Int64 filesize);
std::wstring remainingTimeToString(double timeInSec);
std::wstring fractionToString(double fraction); //within [0, 1]
-
-template <class NumberType>
-std::wstring toGuiString(NumberType number); //format integer number including thousands separator
-
std::wstring utcToLocalTimeString(Int64 utcTime); //like Windows Explorer would...
+std::wstring formatThreeDigitPrecision(double value); //= *at least* three digits
-
-
-
-
-
-
+template <class NumberType>
+std::wstring toGuiString(NumberType number); //format integer number including thousands separator
diff --git a/zen/i18n.h b/zen/i18n.h
index 66e5fa53..b7d10d3c 100644
--- a/zen/i18n.h
+++ b/zen/i18n.h
@@ -68,6 +68,7 @@ std::wstring translate(const std::wstring& text)
inline
std::wstring translate(const std::wstring& singular, const std::wstring& plural, int n)
{
+ if (n < 0) n = -n;
return getTranslator() ? getTranslator()->translate(singular, plural, n) : n == 1 ? singular : plural;
}
diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h
index db1fbdca..cdff09fa 100644
--- a/zen/long_path_prefix.h
+++ b/zen/long_path_prefix.h
@@ -57,6 +57,11 @@ Zstring applyLongPathPrefixImpl(const Zstring& path)
assert(!path.empty()); //nicely check almost all WinAPI accesses!
assert(!zen::isWhiteSpace(path[0]));
+ //http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#naming_conventions))
+ /*
+ - special names like ".NUL" create all kinds of trouble (e.g. CreateDirectory() reports success, but does nothing)
+ unless prefix is supplied => accept as limitation
+ */
if (path.length() >= maxPath || //maximum allowed path length without prefix is (MAX_PATH - 1)
endsWith(path, L' ') || //by default all Win32 APIs trim trailing spaces and period, unless long path prefix is supplied!
endsWith(path, L'.')) //note: adding long path prefix might screw up relative paths "." and ".."!
diff --git a/zen/optional.h b/zen/optional.h
index a6a53103..6e54408a 100644
--- a/zen/optional.h
+++ b/zen/optional.h
@@ -45,6 +45,7 @@ public:
if (tmp.valid)
value = tmp.value;
valid = tmp.valid;
+ return *this;
}
////rvalue optimization: only basic exception safety:
diff --git a/zen/serialize.h b/zen/serialize.h
index 415bd430..64c07213 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -56,7 +56,7 @@ private:
//----------------------------------------------------------------------
//functions based on binary container abstraction
template <class BinContainer> void saveBinStream(const Zstring& filename, const BinContainer& cont); //throw FileError
-template <class BinContainer> BinContainer loadBinStream(const Zstring& filename); //throw FileError, ErrorNotExisting
+template <class BinContainer> BinContainer loadBinStream(const Zstring& filename); //throw FileError
/*
@@ -157,11 +157,11 @@ void saveBinStream(const Zstring& filename, const BinContainer& cont) //throw Fi
template <class BinContainer> inline
-BinContainer loadBinStream(const Zstring& filename) //throw FileError, ErrorNotExisting
+BinContainer loadBinStream(const Zstring& filename) //throw FileError
{
assert_static(sizeof(typename BinContainer::value_type) == 1); //expect: bytes (until further)
- FileInput fileIn(filename); //throw FileError, ErrorNotExisting
+ FileInput fileIn(filename); //throw FileError
BinContainer contOut;
const size_t blockSize = 128 * 1024;
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index c93f2d61..bf47bb1c 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -183,6 +183,9 @@ template <class K, class V> class hash_map : public std::map<K, V> {};
#else
template <class T> class hash_set : public std::unordered_set<T> {};
template <class K, class V> class hash_map : public std::unordered_map<K, V> {};
+//C++11:
+//template <class T> using hash_set = std::unordered_set<T>;
+//template <class K, class V> using hash_map = std::unordered_map<K, V>;
#endif
//as long as variadic templates are not available in MSVC
diff --git a/zen/string_base.h b/zen/string_base.h
index 591ed62b..31a09e63 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -21,7 +21,7 @@ namespace zen
Allocator Policy:
-----------------
void* allocate(size_t size) //throw std::bad_alloc
- void deallocate(void* ptr)
+ void deallocate(void* ptr) //must handle deallocate(nullptr)!
size_t calcCapacity(size_t length)
*/
class AllocatorOptimalSpeed //exponential growth + min size
@@ -30,8 +30,9 @@ public:
//::operator new/ ::operator delete show same performance characterisics like malloc()/free()!
static void* allocate(size_t size) { return ::operator new(size); } //throw std::bad_alloc
static void deallocate(void* ptr) { ::operator delete(ptr); }
- static size_t calcCapacity(size_t length) { return std::max<size_t>(std::max<size_t>(16, length), length + length / 2); } //size_t might overflow!
- //any growth rate should not exceed golden ratio: 1.618033989
+ static size_t calcCapacity(size_t length) { return std::max<size_t>(16, std::max(length + length / 2, length)); }
+ //- size_t might overflow! => better catch here than return a too small size covering up the real error: a way too large length!
+ //- any growth rate should not exceed golden ratio: 1.618033989
};
@@ -52,7 +53,7 @@ template <typename Char, //Character Type
Char* create(size_t size)
Char* create(size_t size, size_t minCapacity)
Char* clone(Char* ptr)
- void destroy(Char* ptr)
+ void destroy(Char* ptr) //must handle destroy(nullptr)!
bool canWrite(const Char* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
size_t length(const Char* ptr)
void setLength(Char* ptr, size_t newLength)
@@ -87,7 +88,7 @@ protected:
return newData;
}
- static void destroy(Char* ptr) { AP::deallocate(descr(ptr)); }
+ static void destroy(Char* ptr) { AP::deallocate(descr(ptr)); } //should support destroy(nullptr)!
//this needs to be checked before writing to "ptr"
static bool canWrite(const Char* ptr, size_t minCapacity) { return minCapacity <= descr(ptr)->capacity; }
@@ -141,6 +142,7 @@ protected:
static void destroy(Char* ptr)
{
+ if (!ptr) return; //support destroy(nullptr)
assert(descr(ptr)->refCount > 0);
if (--descr(ptr)->refCount == 0) //operator--() is overloaded to decrement and evaluate in a single atomic operation!
{
@@ -251,7 +253,7 @@ public:
private:
Zbase(int); //
- Zbase& operator=(int); //detect usage errors
+ Zbase& operator=(int); //detect usage errors by creating an intentional ambiguity with "Char"
Zbase& operator+=(int); //
void push_back(int); //
@@ -294,15 +296,6 @@ template <class Char, template <class, class> class SP, class AP> inline Zbase<C
-
-
-
-
-
-
-
-
-
//################################# implementation ########################################
template <class Char, template <class, class> class SP, class AP> inline
Zbase<Char, SP, AP>::Zbase()
@@ -361,16 +354,9 @@ Zbase<Char, SP, AP>::Zbase(const Zbase<Char, SP, AP>& source)
template <class Char, template <class, class> class SP, class AP> inline
Zbase<Char, SP, AP>::Zbase(Zbase<Char, SP, AP>&& tmp)
{
- if (this->canWrite(tmp.rawStr, 0)) //perf: following optimization saves about 4%
- {
- //do not increment ref-count of an unshared string! We'd lose optimization opportunity of reusing its memory!
- //instead create a dummy string and swap:
- rawStr = this->create(0); //no perf issue! see comment in default constructor
- rawStr[0] = 0;
- swap(tmp);
- }
- else //shared representation: yet another "add ref" won't hurt
- rawStr = this->clone(tmp.rawStr);
+ rawStr = tmp.rawStr;
+ tmp.rawStr = nullptr; //usually nullptr would violate the class invarants, but it is good enough for the destructor!
+ //caveat: do not increment ref-count of an unshared string! We'd lose optimization opportunity of reusing its memory!
}
@@ -388,7 +374,7 @@ Zbase<Char, SP, AP>::Zbase(const S& other, typename S::value_type)
template <class Char, template <class, class> class SP, class AP> inline
Zbase<Char, SP, AP>::~Zbase()
{
- this->destroy(rawStr);
+ this->destroy(rawStr); //rawStr may be nullptr; see move constructor!
}
@@ -499,25 +485,25 @@ Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::replace(size_t pos1, size_t n1, const
template <class Char, template <class, class> class SP, class AP> inline
void Zbase<Char, SP, AP>::resize(size_t newSize, Char fillChar)
{
+ const size_t oldSize = length();
if (this->canWrite(rawStr, newSize))
{
- if (length() < newSize)
- std::fill(rawStr + length(), rawStr + newSize, fillChar);
+ if (oldSize < newSize)
+ std::fill(rawStr + oldSize, rawStr + newSize, fillChar);
rawStr[newSize] = 0;
- this->setLength(rawStr, newSize); //keep after call to length()
+ this->setLength(rawStr, newSize);
}
else
{
Char* newStr = this->create(newSize);
- newStr[newSize] = 0;
-
- if (length() < newSize)
+ if (oldSize < newSize)
{
- std::copy(rawStr, rawStr + length(), newStr);
- std::fill(newStr + length(), newStr + newSize, fillChar);
+ std::copy(rawStr, rawStr + oldSize, newStr);
+ std::fill(newStr + oldSize, newStr + newSize, fillChar);
}
else
std::copy(rawStr, rawStr + newSize, newStr);
+ newStr[newSize] = 0;
this->destroy(rawStr);
rawStr = newStr;
@@ -614,7 +600,7 @@ void Zbase<Char, SP, AP>::clear()
{
if (this->canWrite(rawStr, 0))
{
- rawStr[0] = 0; //keep allocated memory
+ rawStr[0] = 0; //keep allocated memory
this->setLength(rawStr, 0); //
}
else
@@ -636,8 +622,9 @@ void Zbase<Char, SP, AP>::reserve(size_t minCapacity) //make unshared and check
if (!this->canWrite(rawStr, minCapacity))
{
//allocate a new string
- Char* newStr = this->create(length(), std::max(minCapacity, length())); //reserve() must NEVER shrink the string: logical const!
- std::copy(rawStr, rawStr + length() + 1, newStr); //include 0-termination
+ const size_t len = length();
+ Char* newStr = this->create(len, std::max(len, minCapacity)); //reserve() must NEVER shrink the string: logical const!
+ std::copy(rawStr, rawStr + len + 1, newStr); //include 0-termination
this->destroy(rawStr);
rawStr = newStr;
diff --git a/zen/sys_error.h b/zen/sys_error.h
index bbac2eaa..cea2f5f9 100644
--- a/zen/sys_error.h
+++ b/zen/sys_error.h
@@ -28,14 +28,14 @@ namespace zen
typedef DWORD ErrorCode;
#elif defined ZEN_LINUX || defined ZEN_MAC
typedef int ErrorCode;
+#else
+#error define a platform!
#endif
ErrorCode getLastError();
std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastError);
-bool errorCodeForNotExisting(ErrorCode lastError); //check for "not existing" aliases
-
//A low-level exception class giving (non-translated) detail information only - same conceptional level like "GetLastError()"!
class SysError
@@ -105,20 +105,6 @@ std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastE
return output;
}
-
-
-inline
-bool errorCodeForNotExisting(ErrorCode lastError)
-{
-#ifdef ZEN_WIN
- return lastError == ERROR_FILE_NOT_FOUND ||
- lastError == ERROR_PATH_NOT_FOUND ||
- lastError == ERROR_BAD_NETPATH ||
- lastError == ERROR_NETNAME_DELETED;
-#elif defined ZEN_LINUX || defined ZEN_MAC
- return lastError == ENOENT;
-#endif
-}
}
#endif //LAST_ERROR_H_3284791347018951324534
diff --git a/zen/thread.h b/zen/thread.h
index 638d9474..76596513 100644
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -128,7 +128,7 @@ public:
void reportFinished(std::unique_ptr<T>&& result)
{
{
- boost::unique_lock<boost::mutex> dummy(lockResult);
+ boost::lock_guard<boost::mutex> dummy(lockResult);
++jobsFinished;
if (!result_)
result_ = std::move(result);
@@ -149,7 +149,6 @@ public:
std::unique_ptr<T> getResult(size_t jobsTotal)
{
boost::unique_lock<boost::mutex> dummy(lockResult);
-
while (!jobDone(jobsTotal))
conditionJobDone.timed_wait(dummy, boost::posix_time::milliseconds(50)); //interruption point!
diff --git a/zen/type_tools.h b/zen/type_tools.h
index e5ce29bd..76a12a5a 100644
--- a/zen/type_tools.h
+++ b/zen/type_tools.h
@@ -29,10 +29,10 @@ template <class T, class U>
struct SelectIf<false, T, U> : ResultType<U> {};
//------------------------------------------------------
template <class T, class U>
-struct IsSameType : StaticBool<false> {};
+struct IsSameType : FalseType {};
template <class T>
-struct IsSameType<T, T> : StaticBool<true> {};
+struct IsSameType<T, T> : TrueType {};
//------------------------------------------------------
template <bool, class T = void>
diff --git a/zen/type_traits.h b/zen/type_traits.h
index 4f71f961..a90b9793 100644
--- a/zen/type_traits.h
+++ b/zen/type_traits.h
@@ -21,6 +21,9 @@ struct StaticInt
template <bool b>
struct StaticBool : StaticInt<b> {};
+typedef StaticBool<true> TrueType;
+typedef StaticBool<false> FalseType;
+
template <class EnumType, EnumType val>
struct StaticEnum
{
@@ -45,7 +48,7 @@ template <class T> struct IsArithmetic; //IsInteger or IsFloat
//remaining non-arithmetic types: bool, char, wchar_t
//optional: specialize new types like:
-//template <> struct IsUnsignedInt<UInt64> : StaticBool<true> {};
+//template <> struct IsUnsignedInt<UInt64> : TrueType {};
//################# Class Members ########################
@@ -81,10 +84,10 @@ template <class T> struct IsArithmetic; //IsInteger or IsFloat
//################ implementation ######################
-#define ZEN_SPECIALIZE_TRAIT(X, Y) template <> struct X<Y> : StaticBool<true> {};
+#define ZEN_SPECIALIZE_TRAIT(X, Y) template <> struct X<Y> : TrueType {};
template <class T>
-struct IsUnsignedInt : StaticBool<false> {};
+struct IsUnsignedInt : FalseType {};
ZEN_SPECIALIZE_TRAIT(IsUnsignedInt, unsigned char);
ZEN_SPECIALIZE_TRAIT(IsUnsignedInt, unsigned short int);
@@ -94,7 +97,7 @@ ZEN_SPECIALIZE_TRAIT(IsUnsignedInt, unsigned long long int); //new with C++11 -
//------------------------------------------------------
template <class T>
-struct IsSignedInt : StaticBool<false> {};
+struct IsSignedInt : FalseType {};
ZEN_SPECIALIZE_TRAIT(IsSignedInt, signed char);
ZEN_SPECIALIZE_TRAIT(IsSignedInt, short int);
@@ -104,7 +107,7 @@ ZEN_SPECIALIZE_TRAIT(IsSignedInt, long long int); //new with C++11 - same type a
//------------------------------------------------------
template <class T>
-struct IsFloat : StaticBool<false> {};
+struct IsFloat : FalseType {};
ZEN_SPECIALIZE_TRAIT(IsFloat, float);
ZEN_SPECIALIZE_TRAIT(IsFloat, double);
@@ -143,7 +146,7 @@ struct IsArithmetic : StaticBool<IsInteger<T>::value || IsFloat<T>::value> {};
}; \
\
template<class T> \
- struct HasMemberImpl_##NAME<false, T> : StaticBool<false> {}; \
+ struct HasMemberImpl_##NAME<false, T> : FalseType {}; \
\
template<typename T> \
struct HasMember_##NAME : StaticBool<HasMemberImpl_##NAME<std::is_class<T>::value, T>::value> {};
diff --git a/zen/win.h b/zen/win.h
index 45487a09..40a157f5 100644
--- a/zen/win.h
+++ b/zen/win.h
@@ -23,7 +23,6 @@
#endif
#include <windows.h>
-
#endif
//------------------------------------------------------
diff --git a/zen/zstring.cpp b/zen/zstring.cpp
index a469ade2..1cc037e8 100644
--- a/zen/zstring.cpp
+++ b/zen/zstring.cpp
@@ -33,19 +33,15 @@ public:
void insert(const void* ptr, size_t size)
{
boost::lock_guard<boost::mutex> dummy(lockActStrings);
- if (activeStrings.find(ptr) != activeStrings.end())
+ if (!activeStrings.insert(std::make_pair(ptr, size)).second)
reportProblem("Fatal Error: New memory points into occupied space: " + rawMemToString(ptr, size));
-
- activeStrings[ptr] = size;
}
void remove(const void* ptr)
{
boost::lock_guard<boost::mutex> dummy(lockActStrings);
- if (activeStrings.find(ptr) == activeStrings.end())
+ if (activeStrings.erase(ptr) != 1)
reportProblem("Fatal Error: No memory available for deallocation at this location!");
-
- activeStrings.erase(ptr);
}
static LeakChecker& instance() { static LeakChecker inst; return inst; }
diff --git a/zen/zstring.h b/zen/zstring.h
index 80c267e3..f103faf7 100644
--- a/zen/zstring.h
+++ b/zen/zstring.h
@@ -28,11 +28,11 @@ class AllocatorFreeStoreChecked
public:
static void* allocate(size_t size) //throw std::bad_alloc
{
- void* newMem = ::operator new(size);
+ void* ptr = zen::AllocatorOptimalSpeed::allocate(size);
#ifndef NDEBUG
- z_impl::leakCheckerInsert(newMem, size); //test Zbase for memory leaks
+ z_impl::leakCheckerInsert(ptr, size); //test Zbase for memory leaks
#endif
- return newMem;
+ return ptr;
}
static void deallocate(void* ptr)
@@ -40,10 +40,10 @@ public:
#ifndef NDEBUG
z_impl::leakCheckerRemove(ptr); //check for memory leaks
#endif
- ::operator delete(ptr);
+ zen::AllocatorOptimalSpeed::deallocate(ptr);
}
- static size_t calcCapacity(size_t length) { return std::max<size_t>(16, length + length / 2); } //exponential growth + min size
+ static size_t calcCapacity(size_t length) { return zen::AllocatorOptimalSpeed::calcCapacity(length); }
};
bgstack15