summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2017-01-08 18:21:23 +0100
committerDaniel Wilhelm <shieldwed@outlook.com>2017-01-08 18:21:23 +0100
commitfe660cdff59aa3a939479ed60172e5c0803552b2 (patch)
tree045cf295b79de10f75ed6362c5836db25c9fc63a /zen
parent8.6 (diff)
downloadFreeFileSync-fe660cdff59aa3a939479ed60172e5c0803552b2.tar.gz
FreeFileSync-fe660cdff59aa3a939479ed60172e5c0803552b2.tar.bz2
FreeFileSync-fe660cdff59aa3a939479ed60172e5c0803552b2.zip
8.7
Diffstat (limited to 'zen')
-rw-r--r--zen/basic_math.h4
-rw-r--r--zen/crc.h13
-rw-r--r--zen/dir_watcher.cpp6
-rw-r--r--zen/file_traverser.cpp10
-rw-r--r--zen/fixed_list.h30
-rw-r--r--zen/format_unit.cpp55
-rw-r--r--zen/i18n.h6
-rw-r--r--zen/perf.h63
-rw-r--r--zen/serialize.h27
-rw-r--r--zen/shell_execute.h4
-rw-r--r--zen/stl_tools.h2
-rw-r--r--zen/string_tools.h52
-rw-r--r--zen/thread.h6
-rw-r--r--zen/tick_count.h141
14 files changed, 166 insertions, 253 deletions
diff --git a/zen/basic_math.h b/zen/basic_math.h
index e9e17466..eed23477 100644
--- a/zen/basic_math.h
+++ b/zen/basic_math.h
@@ -18,7 +18,7 @@
namespace numeric
{
template <class T> T abs(T value);
-template <class T> T dist(T a, T b);
+template <class T> auto dist(T a, T b);
template <class T> int sign(T value); //returns one of {-1, 0, 1}
template <class T> T min(T a, T b, T c);
template <class T> T max(T a, T b, T c);
@@ -90,7 +90,7 @@ T abs(T value)
}
template <class T> inline
-T dist(T a, T b)
+auto dist(T a, T b) //return type might be different than T, e.g. std::chrono::duration instead of std::chrono::time_point
{
return a > b ? a - b : b - a;
}
diff --git a/zen/crc.h b/zen/crc.h
index b617bdd0..5c950efc 100644
--- a/zen/crc.h
+++ b/zen/crc.h
@@ -19,6 +19,19 @@
namespace zen
{
+uint16_t getCrc16(const std::string& str);
+uint32_t getCrc32(const std::string& str);
+template <class ByteIterator> uint16_t getCrc16(ByteIterator first, ByteIterator last);
+template <class ByteIterator> uint32_t getCrc32(ByteIterator first, ByteIterator last);
+
+
+
+
+//------------------------- implementation -------------------------------
+inline uint16_t getCrc16(const std::string& str) { return getCrc16(str.begin(), str.end()); }
+inline uint32_t getCrc32(const std::string& str) { return getCrc32(str.begin(), str.end()); }
+
+
template <class ByteIterator> inline
uint16_t getCrc16(ByteIterator first, ByteIterator last)
{
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index 12a6a9f4..98190bba 100644
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -9,6 +9,7 @@
#include <set>
#include "thread.h"
#include "scope_guard.h"
+#include "basic_math.h"
#ifdef ZEN_WIN
#include "device_notify.h"
@@ -358,10 +359,11 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()
//wait until device removal is confirmed, to prevent locking hDir again by some new watch!
if (pimpl_->volRemoval->requestReceived())
{
- const std::chrono::steady_clock::time_point stopTime = std::chrono::steady_clock::now() + std::chrono::seconds(15);
+ const auto startTime = std::chrono::steady_clock::now();
//HandleVolumeRemoval::finished() not guaranteed! note: Windows gives unresponsive applications ca. 10 seconds until unmounting the usb stick in worst case
- while (!pimpl_->volRemoval->finished() && std::chrono::steady_clock::now() < stopTime)
+ while (!pimpl_->volRemoval->finished() &&
+ numeric::dist(std::chrono::steady_clock::now(), startTime) < std::chrono::seconds(15)) //handle potential chrono wrap-around!
{
processGuiMessages(); //DBT_DEVICEREMOVECOMPLETE message is sent here!
std::this_thread::sleep_for(std::chrono::milliseconds(50));
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index b4599d03..3eb284e1 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -62,7 +62,7 @@ void zen::traverseFolder(const Zstring& dirPath,
if (ec == ERROR_NO_MORE_FILES) //not an error situation
return;
//else we have a problem... report it:
- throw FileError(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)), formatSystemError(L"FindNextFile", ec));
+ throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), formatSystemError(L"FindNextFile", ec));
}
//skip "." and ".."
@@ -73,7 +73,7 @@ void zen::traverseFolder(const Zstring& dirPath,
continue;
if (itemNameRaw[0] == 0)
- throw FileError(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)), L"FindNextFile: Data corruption; item with empty name.");
+ throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"FindNextFile: Data corruption; item with empty name.");
const Zstring& itemPath = appendSeparator(dirPath) + itemNameRaw;
@@ -112,7 +112,7 @@ void zen::traverseFolder(const Zstring& dirPath,
{
struct ::dirent* dirEntry = nullptr;
if (::readdir_r(folder, reinterpret_cast< ::dirent*>(&buffer[0]), &dirEntry) != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)), L"readdir_r");
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"readdir_r");
//don't retry but restart dir traversal on error! https://blogs.msdn.microsoft.com/oldnewthing/20140612-00/?p=753/
if (!dirEntry) //no more items
@@ -133,14 +133,14 @@ void zen::traverseFolder(const Zstring& dirPath,
}
catch (const SysError& e) //failure is not an item-level error since we don't know the normalized name yet!!!
{
- throw FileError(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)),
+ throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)),
L"Failed to generate normalized file name: " + fmtPath(itemNameRaw) + L"\n" + e.toString()); //too obscure to warrant translation
}
#else
const Zstring& itemName = itemNameRaw;
#endif
if (itemName.empty()) //checks result of osx::normalizeUtfForPosix, too!
- throw FileError(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)), L"readdir_r: Data corruption; item with empty name.");
+ throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"readdir_r: Data corruption; item with empty name.");
const Zstring& itemPath = appendSeparator(dirPath) + itemName;
diff --git a/zen/fixed_list.h b/zen/fixed_list.h
index 4376c13f..81197eb4 100644
--- a/zen/fixed_list.h
+++ b/zen/fixed_list.h
@@ -15,7 +15,7 @@ namespace zen
{
//std::list(C++11)-like class for inplace element construction supporting non-copyable/non-movable types
//-> no iterator invalidation after emplace_back()
-
+
template <class T>
class FixedList
{
@@ -69,7 +69,7 @@ public:
const_reference& back() const { return lastInsert_->val; }
template <class... Args>
- void emplace_back(Args&&... args)
+ void emplace_back(Args&& ... args)
{
Node* newNode = new Node(std::forward<Args>(args)...);
@@ -160,10 +160,10 @@ class FixedVector
public:
FixedVector() {}
- /*
- class EndIterator {}; //just like FixedList: no iterator invalidation after emplace_back()
+ /*
+ class EndIterator {}; //just like FixedList: no iterator invalidation after emplace_back()
- template <class V>
+ template <class V>
class FixedIterator : public std::iterator<std::forward_iterator_tag, V> //could make this random-access if needed
{
public:
@@ -174,10 +174,10 @@ public:
V& operator* () const { return *cont_[pos_]; }
V* operator->() const { return &*cont_[pos_]; }
private:
- std::vector<std::unique_ptr<T>>& cont_;
- size_t pos_ = 0;
+ std::vector<std::unique_ptr<T>>& cont_;
+ size_t pos_ = 0;
};
- */
+ */
template <class IterImpl, class V>
class FixedIterator : public std::iterator<std::forward_iterator_tag, V> //could make this bidirectional if needed
@@ -188,7 +188,7 @@ public:
inline friend bool operator==(const FixedIterator& lhs, const FixedIterator& rhs) { return lhs.it_ == rhs.it_; }
inline friend bool operator!=(const FixedIterator& lhs, const FixedIterator& rhs) { return !(lhs == rhs); }
V& operator* () const { return **it_; }
- V* operator->() const { return &**it_; }
+ V* operator->() const { return &** it_; }
private:
IterImpl it_; //TODO: avoid iterator invalidation after emplace_back(); caveat: end() must not store old length!
};
@@ -199,10 +199,10 @@ public:
using reference = T&;
using const_reference = const T&;
- iterator begin() { return items_.begin(); }
+ iterator begin() { return items_.begin(); }
iterator end () { return items_.end (); }
- const_iterator begin() const { return items_.begin(); }
+ const_iterator begin() const { return items_.begin(); }
const_iterator end () const { return items_.end (); }
reference front() { return *items_.front(); }
@@ -212,15 +212,15 @@ public:
const_reference& back() const { return *items_.back(); }
template <class... Args>
- void emplace_back(Args&&... args)
+ void emplace_back(Args&& ... args)
{
- items_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
+ items_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
}
template <class Predicate>
void remove_if(Predicate pred)
{
- erase_if(items_, [&](const std::unique_ptr<T>& p){ return pred(*p); });
+ erase_if(items_, [&](const std::unique_ptr<T>& p) { return pred(*p); });
}
void clear() { items_.clear(); }
@@ -232,7 +232,7 @@ private:
FixedVector (const FixedVector&) = delete;
FixedVector& operator=(const FixedVector&) = delete;
- std::vector<std::unique_ptr<T>> items_;
+ std::vector<std::unique_ptr<T>> items_;
};
}
diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp
index d87a1643..08463778 100644
--- a/zen/format_unit.cpp
+++ b/zen/format_unit.cpp
@@ -16,7 +16,7 @@
#ifdef ZEN_WIN
#include "int64.h"
#include "win.h" //includes "windows.h"
- #include "win_ver.h"
+ // #include "win_ver.h"
#elif defined ZEN_LINUX || defined ZEN_MAC
#include <clocale> //thousands separator
@@ -155,6 +155,12 @@ std::wstring zen::remainingTimeToString(double timeInSec)
}
+//std::wstring zen::fractionToString1Dec(double fraction)
+//{
+// return printNumber<std::wstring>(L"%.1f", fraction * 100.0) + L'%'; //no need to internationalize fraction!?
+//}
+
+
std::wstring zen::fractionToString(double fraction)
{
return printNumber<std::wstring>(L"%.2f", fraction * 100.0) + L'%'; //no need to internationalize fraction!?
@@ -299,32 +305,29 @@ std::wstring zen::utcToLocalTimeString(std::int64_t utcTime)
SYSTEMTIME systemTimeLocal = {};
- static const bool useNewLocalTimeCalculation = zen::vistaOrLater();
-
//https://msdn.microsoft.com/en-us/library/ms724277
- if (useNewLocalTimeCalculation) //DST conversion like in Windows 7: NTFS stays fixed, but FAT jumps by one hour
- {
- SYSTEMTIME systemTimeUtc = {};
- if (!::FileTimeToSystemTime(&lastWriteTimeUtc, //__in const FILETIME *lpFileTime,
- &systemTimeUtc)) //__out LPSYSTEMTIME lpSystemTime
- return errorMsg();
-
- if (!::SystemTimeToTzSpecificLocalTime(nullptr, //__in_opt LPTIME_ZONE_INFORMATION lpTimeZone,
- &systemTimeUtc, //__in LPSYSTEMTIME lpUniversalTime,
- &systemTimeLocal)) //__out LPSYSTEMTIME lpLocalTime
- return errorMsg();
- }
- else //DST conversion like in Windows 2000 and XP: FAT times stay fixed, while NTFS jumps
- {
- FILETIME fileTimeLocal = {};
- if (!::FileTimeToLocalFileTime(&lastWriteTimeUtc, //_In_ const FILETIME *lpFileTime,
- &fileTimeLocal)) //_Out_ LPFILETIME lpLocalFileTime
- return errorMsg();
-
- if (!::FileTimeToSystemTime(&fileTimeLocal, //__in const FILETIME *lpFileTime,
- &systemTimeLocal)) //__out LPSYSTEMTIME lpSystemTime
- return errorMsg();
- }
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ //DST conversion like in Vista and later: NTFS stays fixed, but FAT jumps by one hour
+ SYSTEMTIME systemTimeUtc = {};
+ if (!::FileTimeToSystemTime(&lastWriteTimeUtc, //__in const FILETIME *lpFileTime,
+ &systemTimeUtc)) //__out LPSYSTEMTIME lpSystemTime
+ return errorMsg();
+
+ if (!::SystemTimeToTzSpecificLocalTime(nullptr, //__in_opt LPTIME_ZONE_INFORMATION lpTimeZone,
+ &systemTimeUtc, //__in LPSYSTEMTIME lpUniversalTime,
+ &systemTimeLocal)) //__out LPSYSTEMTIME lpLocalTime
+ return errorMsg();
+#else
+ //DST conversion like in Windows 2000 and XP: FAT times stay fixed, while NTFS jumps
+ FILETIME fileTimeLocal = {};
+ if (!::FileTimeToLocalFileTime(&lastWriteTimeUtc, //_In_ const FILETIME *lpFileTime,
+ &fileTimeLocal)) //_Out_ LPFILETIME lpLocalFileTime
+ return errorMsg();
+
+ if (!::FileTimeToSystemTime(&fileTimeLocal, //__in const FILETIME *lpFileTime,
+ &systemTimeLocal)) //__out LPSYSTEMTIME lpSystemTime
+ return errorMsg();
+#endif
zen::TimeComp loc;
loc.year = systemTimeLocal.wYear;
diff --git a/zen/i18n.h b/zen/i18n.h
index 4f62fd4c..e5b0ab2c 100644
--- a/zen/i18n.h
+++ b/zen/i18n.h
@@ -98,7 +98,7 @@ std::wstring translate(const std::wstring& singular, const std::wstring& plural,
inline
-Global<const TranslationHandler>& getGlobalTranslationHandler()
+Global<const TranslationHandler>& refGlobalTranslationHandler()
{
//getTranslator() may be called even after static objects of this translation unit are destroyed!
static Global<const TranslationHandler> inst; //external linkage even in header!
@@ -110,14 +110,14 @@ Global<const TranslationHandler>& getGlobalTranslationHandler()
inline
void setTranslator(std::unique_ptr<const TranslationHandler>&& newHandler)
{
- implementation::getGlobalTranslationHandler().set(std::move(newHandler));
+ implementation::refGlobalTranslationHandler().set(std::move(newHandler));
}
inline
std::shared_ptr<const TranslationHandler> getTranslator()
{
- return implementation::getGlobalTranslationHandler().get();
+ return implementation::refGlobalTranslationHandler().get();
}
}
diff --git a/zen/perf.h b/zen/perf.h
index e3827fd1..6cd874b8 100644
--- a/zen/perf.h
+++ b/zen/perf.h
@@ -7,12 +7,13 @@
#ifndef PERF_H_83947184145342652456
#define PERF_H_83947184145342652456
+#include <chrono>
#include "deprecate.h"
-#include "tick_count.h"
#include "scope_guard.h"
#ifdef ZEN_WIN
#include <sstream>
+ #include "win.h"
#else
#include <iostream>
#endif
@@ -28,54 +29,47 @@ namespace zen
class PerfTimer
{
public:
- class TimerError {};
+ ZEN_DEPRECATE PerfTimer() {}
- ZEN_DEPRECATE
- PerfTimer() : startTime(getTicksNow()) //throw TimerError
- {
- //std::clock() - "counts CPU time in Linux GCC and wall time in VC++" - WTF!???
- if (ticksPerSec_ == 0)
- throw TimerError();
- }
-
- ~PerfTimer() { if (!resultShown) try { showResult(); } catch (TimerError&) { assert(false); } }
+ ~PerfTimer() { if (!resultShown_) showResult(); }
void pause()
{
- if (!paused)
+ if (!paused_)
{
- paused = true;
- elapsedUntilPause += dist(startTime, getTicksNow());
+ paused_ = true;
+ elapsedUntilPause_ += std::chrono::steady_clock::now() - startTime_; //ignore potential ::QueryPerformanceCounter() wrap-around!
}
}
void resume()
{
- if (paused)
+ if (paused_)
{
- paused = false;
- startTime = getTicksNow();
+ paused_ = false;
+ startTime_ = std::chrono::steady_clock::now();
}
}
void restart()
{
- startTime = getTicksNow();
- paused = false;
- elapsedUntilPause = 0;
+ paused_ = false;
+ startTime_ = std::chrono::steady_clock::now();
+ elapsedUntilPause_ = std::chrono::nanoseconds::zero();
}
int64_t timeMs() const
{
- int64_t ticksTotal = elapsedUntilPause;
- if (!paused)
- ticksTotal += dist(startTime, getTicksNow());
- return 1000 * ticksTotal / ticksPerSec_;
+ auto elapsedTotal = elapsedUntilPause_;
+ if (!paused_)
+ elapsedTotal += std::chrono::steady_clock::now() - startTime_;
+
+ return std::chrono::duration_cast<std::chrono::milliseconds>(elapsedTotal).count();
}
void showResult()
{
- const bool wasRunning = !paused;
+ const bool wasRunning = !paused_;
if (wasRunning) pause(); //don't include call to MessageBox()!
ZEN_ON_SCOPE_EXIT(if (wasRunning) resume());
@@ -86,23 +80,14 @@ public:
#else
std::clog << "Perf: duration: " << timeMs() << " ms\n";
#endif
- resultShown = true;
+ resultShown_ = true;
}
private:
- TickVal getTicksNow() const
- {
- const TickVal now = getTicks();
- if (!now.isValid())
- throw TimerError();
- return now;
- }
-
- const std::int64_t ticksPerSec_ = ticksPerSec(); //return 0 on error
- bool resultShown = false;
- TickVal startTime;
- bool paused = false;
- int64_t elapsedUntilPause = 0;
+ bool resultShown_ = false;
+ bool paused_ = false;
+ std::chrono::steady_clock::time_point startTime_ = std::chrono::steady_clock::now(); //uses ::QueryPerformanceCounter()
+ std::chrono::nanoseconds elapsedUntilPause_{}; //std::chrono::duration is uninitialized by default! WTF! When will this stupidity end???
};
}
diff --git a/zen/serialize.h b/zen/serialize.h
index bc047fee..7322cb07 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -72,8 +72,8 @@ struct UnbufferedOutputStream
size_t tryWrite(const void* buffer, size_t bytesToWrite); //may return short! CONTRACT: bytesToWrite > 0
};
*/
-//functions based on unbuffered stream abstraction
+//functions based on unbuffered stream abstraction
template <class UnbufferedInputStream, class UnbufferedOutputStream>
void unbufferedStreamCopy(UnbufferedInputStream& streamIn, UnbufferedOutputStream& streamOut, const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //throw X
@@ -104,7 +104,6 @@ struct BufferedOutputStream
template <class N, class BufferedOutputStream> void writeNumber (BufferedOutputStream& stream, const N& num); //
template <class C, class BufferedOutputStream> void writeContainer(BufferedOutputStream& stream, const C& str); //throw ()
template < class BufferedOutputStream> void writeArray (BufferedOutputStream& stream, const void* data, size_t len); //
-
//----------------------------------------------------------------------
class UnexpectedEndOfStreamError {};
template <class N, class BufferedInputStream> N readNumber (BufferedInputStream& stream); //throw UnexpectedEndOfStreamError (corrupted data)
@@ -115,21 +114,23 @@ template < class BufferedInputStream> void readArray (BufferedInputSt
template <class BinContainer>
struct MemoryStreamIn
{
- MemoryStreamIn(const BinContainer& cont) : buffer(cont) {} //this better be cheap!
+ MemoryStreamIn(const BinContainer& cont) : buffer_(cont) {} //this better be cheap!
size_t read(void* data, size_t len) //return "len" bytes unless end of stream!
{
static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes
- const size_t bytesRead = std::min(len, buffer.size() - pos);
- auto itFirst = buffer.begin() + pos;
+ const size_t bytesRead = std::min(len, buffer_.size() - pos_);
+ auto itFirst = buffer_.begin() + pos_;
std::copy(itFirst, itFirst + bytesRead, static_cast<char*>(data));
- pos += bytesRead;
+ pos_ += bytesRead;
return bytesRead;
}
+ size_t pos() const { return pos_; }
+
private:
- const BinContainer buffer;
- size_t pos = 0;
+ const BinContainer buffer_;
+ size_t pos_ = 0;
};
template <class BinContainer>
@@ -138,15 +139,15 @@ struct MemoryStreamOut
void write(const void* data, size_t len)
{
static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes
- const size_t oldSize = buffer.size();
- buffer.resize(oldSize + len);
- std::copy(static_cast<const char*>(data), static_cast<const char*>(data) + len, buffer.begin() + oldSize);
+ const size_t oldSize = buffer_.size();
+ buffer_.resize(oldSize + len);
+ std::copy(static_cast<const char*>(data), static_cast<const char*>(data) + len, buffer_.begin() + oldSize);
}
- const BinContainer& ref() const { return buffer; }
+ const BinContainer& ref() const { return buffer_; }
private:
- BinContainer buffer;
+ BinContainer buffer_;
};
diff --git a/zen/shell_execute.h b/zen/shell_execute.h
index ee8203c3..2f73fc38 100644
--- a/zen/shell_execute.h
+++ b/zen/shell_execute.h
@@ -38,7 +38,7 @@ bool shellExecuteImpl(Function fillExecInfo, ExecutionType type)
SHELLEXECUTEINFO execInfo = {};
execInfo.cbSize = sizeof(execInfo);
execInfo.lpVerb = nullptr;
- execInfo.nShow = SW_SHOWNORMAL;
+ execInfo.nShow = SW_SHOW;
execInfo.fMask = type == EXEC_TYPE_SYNC ? (SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC) : 0;
//don't use SEE_MASK_ASYNCOK -> different async mode than the default which returns successful despite errors!
execInfo.fMask |= SEE_MASK_FLAG_NO_UI; //::ShellExecuteEx() shows a non-blocking pop-up dialog on errors -> we want a blocking one
@@ -98,7 +98,7 @@ void shellExecute(const Zstring& command, ExecutionType type) //throw FileError
{
filePath = argv[0];
for (auto it = argv.begin() + 1; it != argv.end(); ++it)
- arguments += (it != argv.begin() ? L" " : L"") +
+ arguments += (it == argv.begin() + 1 ? L"" : L" ") +
(it->empty() || std::any_of(it->begin(), it->end(), &isWhiteSpace<wchar_t>) ? L"\"" + *it + L"\"" : *it);
}
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index 064d5b51..48f475f3 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -235,7 +235,7 @@ size_t hashBytesAppend(size_t hashVal, ByteIterator first, ByteIterator last)
#endif
static_assert(sizeof(typename std::iterator_traits<ByteIterator>::value_type) == 1, "");
- for (; first != last; ++first)
+ for (; first != last; ++first)
{
hashVal ^= static_cast<size_t>(*first);
hashVal *= prime;
diff --git a/zen/string_tools.h b/zen/string_tools.h
index 9b8e7328..5292dfc6 100644
--- a/zen/string_tools.h
+++ b/zen/string_tools.h
@@ -24,6 +24,7 @@ namespace zen
{
template <class Char> bool isWhiteSpace(Char ch);
template <class Char> bool isDigit (Char ch); //not exactly the same as "std::isdigit" -> we consider '0'-'9' only!
+template <class Char> bool isHexDigit (Char ch);
template <class Char> bool isAlpha (Char ch);
template <class S, class T> bool startsWith(const S& str, const T& prefix); //
@@ -51,6 +52,9 @@ template <class S, class T, class U> S replaceCpy(const S& str, const T& oldT
template <class S, class Num> S numberTo(const Num& number);
template <class Num, class S > Num stringTo(const S& str);
+std::pair<char, char> hexify (unsigned char c, bool upperCase = true);
+char unhexify(char high, char low);
+
template <class S, class T, class Num> S printNumber(const T& format, const Num& number); //format a single number using std::snprintf()
//string to string conversion: converts string-like type into char-compatible target string class
@@ -101,6 +105,16 @@ bool isDigit(Char ch) //similar to implmenetation of std::::isdigit()!
}
+template <class Char> inline
+bool isHexDigit(Char c)
+{
+ static_assert(IsSameType<Char, char>::value || IsSameType<Char, wchar_t>::value, "");
+ return (static_cast<Char>('0') <= c && c <= static_cast<Char>('9')) ||
+ (static_cast<Char>('A') <= c && c <= static_cast<Char>('F')) ||
+ (static_cast<Char>('a') <= c && c <= static_cast<Char>('f'));
+}
+
+
template <> bool isAlpha(char ch) = delete; //probably not a good idea with UTF-8 anyway...
template <> inline bool isAlpha(wchar_t ch) { return std::iswalpha(ch) != 0; }
@@ -297,7 +311,7 @@ S replaceCpy(const S& str, const T& oldTerm, const U& newTerm, bool replaceAll)
return str;
const auto* const newBegin = strBegin(newTerm);
- const auto* const newEnd = newBegin + strLength(newTerm);
+ const auto* const newEnd = newBegin + strLength(newTerm);
S output;
for (;;)
@@ -658,6 +672,42 @@ Num stringTo(const S& str)
return impl::stringTo<Num>(str, TypeTag());
}
+
+
+inline //hexify beats "printNumber<std::string>("%02X", c)" by a nice factor of 3!
+std::pair<char, char> hexify(unsigned char c, bool upperCase)
+{
+ auto hexifyDigit = [upperCase](int num) -> char //input [0, 15], output 0-9, A-F
+ {
+ assert(0 <= num&& num <= 15); //guaranteed by design below!
+ if (num <= 9)
+ return static_cast<char>('0' + num); //no signed/unsigned char problem here!
+
+ if (upperCase)
+ return static_cast<char>('A' + (num - 10));
+ else
+ return static_cast<char>('a' + (num - 10));
+ };
+ return std::make_pair(hexifyDigit(c / 16), hexifyDigit(c % 16));
+}
+
+
+inline //unhexify beats "::sscanf(&it[3], "%02X", &tmp)" by a factor of 3000 for ~250000 calls!!!
+char unhexify(char high, char low)
+{
+ auto unhexifyDigit = [](char hex) -> int //input 0-9, a-f, A-F; output range: [0, 15]
+ {
+ if ('0' <= hex && hex <= '9') //no signed/unsigned char problem here!
+ return hex - '0';
+ else if ('A' <= hex && hex <= 'F')
+ return (hex - 'A') + 10;
+ else if ('a' <= hex && hex <= 'f')
+ return (hex - 'a') + 10;
+ assert(false);
+ return 0;
+ };
+ return static_cast<unsigned char>(16 * unhexifyDigit(high) + unhexifyDigit(low)); //[!] convert to unsigned char first, then to char (which may be signed)
+}
}
#endif //STRING_TOOLS_H_213458973046
diff --git a/zen/thread.h b/zen/thread.h
index ac94da6a..5bb02a0e 100644
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -460,9 +460,9 @@ std::uint64_t getThreadId()
return ::GetCurrentThreadId(); //no-fail
#elif defined ZEN_LINUX
- //obviously "gettid()" is not available on Ubuntu/Debian/Suse => use the OpenSSL approach:
- static_assert(sizeof(std::uint64_t) >= sizeof(void*), "");
- return reinterpret_cast<std::uint64_t>(static_cast<void*>(&errno));
+ //obviously "gettid()" is not available on Ubuntu/Debian/Suse => use the OpenSSL approach:
+ static_assert(sizeof(std::uint64_t) >= sizeof(void*), "");
+ return reinterpret_cast<std::uint64_t>(static_cast<void*>(&errno));
#elif defined ZEN_MAC
uint64_t tid = 0;
diff --git a/zen/tick_count.h b/zen/tick_count.h
deleted file mode 100644
index 5ba4fd1b..00000000
--- a/zen/tick_count.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// *****************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
-// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
-// *****************************************************************************
-
-#ifndef TICK_COUNT_H_3807326223463457
-#define TICK_COUNT_H_3807326223463457
-
-#include <cstdint>
-#include "type_traits.h"
-#include "basic_math.h"
-
-#ifdef ZEN_WIN
- #include "win.h" //includes "windows.h"
-#elif defined ZEN_LINUX
- #include <time.h> //Posix ::clock_gettime()
-#elif defined ZEN_MAC
- #include <mach/mach_time.h>
-#endif
-
-
-namespace zen
-{
-//a portable "GetTickCount()" using "wall time equivalent" - e.g. no jumps due to ntp time corrections
-class TickVal;
-int64_t dist(const TickVal& lhs, const TickVal& rhs); //use absolute difference for paranoid security: even QueryPerformanceCounter "wraps-around" at *some* time
-
-int64_t ticksPerSec(); //return 0 on error
-TickVal getTicks(); //return invalid value on error: !TickVal::isValid()
-
-
-
-
-
-
-
-
-
-//############################ implementation ##############################
-class TickVal
-{
-public:
-#ifdef ZEN_WIN
- using NativeVal = LARGE_INTEGER;
-#elif defined ZEN_LINUX
- using NativeVal = timespec;
-#elif defined ZEN_MAC
- using NativeVal = uint64_t;
-#endif
-
- TickVal() {}
- explicit TickVal(const NativeVal& val) : val_(val) {}
-
- inline friend
- int64_t dist(const TickVal& lhs, const TickVal& rhs)
- {
-#ifdef ZEN_WIN
- return numeric::dist(lhs.val_.QuadPart, rhs.val_.QuadPart); //std::abs(a - b) can lead to overflow!
-#elif defined ZEN_LINUX
- //structure timespec documented with members:
- // time_t tv_sec seconds
- // long tv_nsec nanoseconds
- const int64_t deltaSec = lhs.val_.tv_sec - rhs.val_.tv_sec;
- const int64_t deltaNsec = lhs.val_.tv_nsec - rhs.val_.tv_nsec;
- return numeric::abs(deltaSec * 1000000000 + deltaNsec);
-#elif defined ZEN_MAC
- return numeric::dist(lhs.val_, rhs.val_);
-#endif
- }
-
- inline friend
- bool operator<(const TickVal& lhs, const TickVal& rhs)
- {
-#ifdef ZEN_WIN
- return lhs.val_.QuadPart < rhs.val_.QuadPart;
-#elif defined ZEN_LINUX
- if (lhs.val_.tv_sec != rhs.val_.tv_sec)
- return lhs.val_.tv_sec < rhs.val_.tv_sec;
- return lhs.val_.tv_nsec < rhs.val_.tv_nsec;
-#elif defined ZEN_MAC
- return lhs.val_ < rhs.val_;
-#endif
- }
-
- bool isValid() const { return dist(*this, TickVal()) != 0; }
-
-private:
- NativeVal val_ {};
-};
-
-
-inline
-int64_t ticksPerSec() //return 0 on error
-{
-#ifdef ZEN_WIN
- LARGE_INTEGER frequency = {};
- if (!::QueryPerformanceFrequency(&frequency)) //MSDN promises: "The frequency cannot change while the system is running."
- return 0; //MSDN: "This won't occur on any system that runs Windows XP or later."
- static_assert(sizeof(int64_t) >= sizeof(frequency.QuadPart), "");
- return frequency.QuadPart;
-
-#elif defined ZEN_LINUX
- return 1000000000; //precision: nanoseconds
-
-#elif defined ZEN_MAC
- mach_timebase_info_data_t tbi = {};
- if (::mach_timebase_info(&tbi) != KERN_SUCCESS)
- return 0;
- //structure mach_timebase_info_data_t documented with members:
- // uint32_t numer;
- // uint32_t denom;
- return static_cast<int64_t>(1000000000) * tbi.denom / tbi.numer;
-#endif
-}
-
-
-inline
-TickVal getTicks() //return !isValid() on error
-{
-#ifdef ZEN_WIN
- LARGE_INTEGER now = {};
- if (!::QueryPerformanceCounter(&now))
- return TickVal();
- //detailed info about QPC: https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408
- //- MSDN: "No need to set the thread affinity"
-
-#elif defined ZEN_LINUX
- //gettimeofday() seems fine but is deprecated
- timespec now = {};
- if (::clock_gettime(CLOCK_MONOTONIC_RAW, &now) != 0) //CLOCK_MONOTONIC measures time reliably across processors!
- return TickVal();
-
-#elif defined ZEN_MAC
- uint64_t now = ::mach_absolute_time(); //can this call fail???
-#endif
- return TickVal(now);
-}
-}
-
-#endif //TICK_COUNT_H_3807326223463457
bgstack15