diff options
Diffstat (limited to 'zen')
-rw-r--r-- | zen/file_handling.cpp | 2 | ||||
-rw-r--r-- | zen/file_handling.h | 3 | ||||
-rw-r--r-- | zen/file_traverser.h | 4 | ||||
-rw-r--r-- | zen/format_unit.cpp | 16 | ||||
-rw-r--r-- | zen/serialize.h | 34 | ||||
-rw-r--r-- | zen/string_base.h | 6 | ||||
-rw-r--r-- | zen/string_traits.h | 1 | ||||
-rw-r--r-- | zen/tick_count.h | 41 | ||||
-rw-r--r-- | zen/type_traits.h | 7 | ||||
-rw-r--r-- | zen/utf.h | 19 |
10 files changed, 64 insertions, 69 deletions
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp index cf92f346..cecebff1 100644 --- a/zen/file_handling.cpp +++ b/zen/file_handling.cpp @@ -2285,7 +2285,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath 4. copy file from USB to local drive via explorer => NTFS <-> FAT, file exists on both sides; mod times match, DST hack on USB stick causes 1-hour offset when comparing in FFS. - When syncing modification time is copied correctly, but new DST hack fails to apply and old creation time is reused (see above). + When syncing, modification time is copied correctly, but new DST hack fails to apply and old creation time is reused (see above). Unfortunately, the old DST hash matches mod time! => On next comparison FFS will *still* see both sides as different!!!!!!!!! */ diff --git a/zen/file_handling.h b/zen/file_handling.h index d14ed27f..c3ce1d83 100644 --- a/zen/file_handling.h +++ b/zen/file_handling.h @@ -32,7 +32,6 @@ void setFileTime(const Zstring& filename, const Int64& modificationTime, ProcSym UInt64 getFilesize(const Zstring& filename); //throw FileError UInt64 getFreeDiskSpace(const Zstring& path); //throw FileError -//file handling bool removeFile(const Zstring& filename); //throw FileError; return "false" if file is not existing void removeDirectory(const Zstring& directory, //throw FileError const std::function<void (const Zstring& filename)>& onBeforeFileDeletion = nullptr, //optional; @@ -41,7 +40,7 @@ void removeDirectory(const Zstring& directory, //throw FileError //rename file or directory: no copying!!! void renameFile(const Zstring& oldName, const Zstring& newName); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting -bool supportsPermissions(const Zstring& dirname); //throw FileError, derefernces symlinks +bool supportsPermissions(const Zstring& dirname); //throw FileError, dereferences symlinks //if parent directory not existing: create recursively: void makeDirectory(const Zstring& directory, bool failIfExists = false); //throw FileError, ErrorTargetExisting diff --git a/zen/file_traverser.h b/zen/file_traverser.h index 2944c5ba..db93a688 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -67,8 +67,8 @@ struct DstHackCallback; //DST hack not required on Unix #endif //custom traverser with detail information about files -//Win: client needs to handle duplicate file notifications! (FilePlusTraverser fallback) -//directory may end with PATH_SEPARATOR +//- client needs to handle duplicate file reports! (FilePlusTraverser fallback, retrying to read directory contents, ...) +//- directory may end with PATH_SEPARATOR void traverseFolder(const Zstring& dirname, //throw() TraverseCallback& sink, DstHackCallback* dstCallback = nullptr); //apply DST hack if callback is supplied diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp index 1568b616..bcf318d9 100644 --- a/zen/format_unit.cpp +++ b/zen/format_unit.cpp @@ -96,22 +96,22 @@ std::wstring formatUnitTime(int val, UnitRemTime unit) template <int M, int N> -std::wstring roundToBlock(double timeHigh, +std::wstring roundToBlock(double timeInHigh, UnitRemTime unitHigh, const int (&stepsHigh)[M], int unitLowPerHigh, UnitRemTime unitLow, const int (&stepsLow)[N]) { assert(unitLowPerHigh > 0); const double granularity = 0.1; - const double timeLow = timeHigh * unitLowPerHigh; - const int blockSizeLow = granularity * timeHigh < 1 ? - numeric::nearMatch(granularity * timeLow, std::begin(stepsLow), std::end(stepsLow)): - numeric::nearMatch(granularity * timeHigh, std::begin(stepsHigh), std::end(stepsHigh)) * unitLowPerHigh; - const int roundedTimeLow = numeric::round(timeLow / blockSizeLow) * blockSizeLow; + const double timeInLow = timeInHigh * unitLowPerHigh; + const int blockSizeLow = granularity * timeInHigh < 1 ? + numeric::nearMatch(granularity * timeInLow, std::begin(stepsLow), std::end(stepsLow)): + numeric::nearMatch(granularity * timeInHigh, std::begin(stepsHigh), std::end(stepsHigh)) * unitLowPerHigh; + const int roundedtimeInLow = numeric::round(timeInLow / blockSizeLow) * blockSizeLow; - std::wstring output = formatUnitTime(roundedTimeLow / unitLowPerHigh, unitHigh); + std::wstring output = formatUnitTime(roundedtimeInLow / unitLowPerHigh, unitHigh); if (unitLowPerHigh > blockSizeLow) - output += L" " + formatUnitTime(roundedTimeLow % unitLowPerHigh, unitLow); + output += L" " + formatUnitTime(roundedtimeInLow % unitLowPerHigh, unitLow); return output; }; } diff --git a/zen/serialize.h b/zen/serialize.h index 14d0cdf7..9a14e6af 100644 --- a/zen/serialize.h +++ b/zen/serialize.h @@ -4,14 +4,13 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef SERIALIZE_H_INCLUDED -#define SERIALIZE_H_INCLUDED +#ifndef SERIALIZE_H_INCLUDED_83940578357 +#define SERIALIZE_H_INCLUDED_83940578357 #include <cstdint> #include <zen/string_base.h> #include <zen/file_io.h> - namespace zen { //high-performance unformatted serialization (avoiding wxMemoryOutputStream/wxMemoryInputStream inefficiencies) @@ -134,16 +133,6 @@ template < class BinInputStream> void readArray (BinInputStream& stre - - - - - - - - - - //-----------------------implementation------------------------------- template <class BinContainer> inline void saveBinStream(const Zstring& filename, const BinContainer& cont) //throw FileError @@ -207,40 +196,43 @@ void writeContainer(BinOutputStream& stream, const C& cont) //don't even conside template <class BinInputStream> inline -void readArray(BinInputStream& stream, void* data, size_t len) +void readArray(BinInputStream& stream, void* data, size_t len) //throw UnexpectedEndOfStreamError { - const char* const src = static_cast<const char*>(stream.requestRead(len)); //expect external write of len bytes + //expect external write of len bytes: + const char* const src = static_cast<const char*>(stream.requestRead(len)); //throw UnexpectedEndOfStreamError std::copy(src, src + len, static_cast<char*>(data)); } template <class N, class BinInputStream> inline -N readNumber(BinInputStream& stream) +N readNumber(BinInputStream& stream) //throw UnexpectedEndOfStreamError { assert_static((IsArithmetic<N>::value || IsSameType<N, bool>::value)); N num = 0; - readArray(stream, &num, sizeof(N)); + readArray(stream, &num, sizeof(N)); //throw UnexpectedEndOfStreamError return num; } template <class C, class BinInputStream> inline -C readContainer(BinInputStream& stream) +C readContainer(BinInputStream& stream) //throw UnexpectedEndOfStreamError { C cont; auto strLength = readNumber<std::uint32_t>(stream); - if (strLength > 0) + if (strLength > 0) + { try { cont.resize(strLength); //throw std::bad_alloc - readArray(stream, &*cont.begin(), sizeof(typename C::value_type) * strLength); } catch (std::bad_alloc&) //most likely this is due to data corruption! { throw UnexpectedEndOfStreamError(); } + readArray(stream, &*cont.begin(), sizeof(typename C::value_type) * strLength); //throw UnexpectedEndOfStreamError + } return cont; } } -#endif //SERIALIZE_H_INCLUDED +#endif //SERIALIZE_H_INCLUDED_83940578357 diff --git a/zen/string_base.h b/zen/string_base.h index 2d16e669..a458ef15 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -196,11 +196,11 @@ public: Zbase(const Char* source); //implicit conversion from a C-string Zbase(const Char* source, size_t length); Zbase(const Zbase& source); - Zbase(Zbase&& tmp); + Zbase(Zbase&& tmp); //make noexcept in C++11 explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; return buffer[0]; ups... forgot &, but not a compiler error! //allow explicit construction from different string type, prevent ambiguity via SFINAE template <class S> explicit Zbase(const S& other, typename S::value_type = 0); - ~Zbase(); + ~Zbase(); //make noexcept in C++11 //operator const Char* () const; //NO implicit conversion to a C-string!! Many problems... one of them: if we forget to provide operator overloads, it'll just work with a Char*... @@ -241,7 +241,7 @@ public: void push_back(Char val) { operator+=(val); } //STL access Zbase& operator=(const Zbase& source); - Zbase& operator=(Zbase&& tmp); + Zbase& operator=(Zbase&& tmp); //make noexcept in C++11 Zbase& operator=(const Char* source); Zbase& operator=(Char source); Zbase& operator+=(const Zbase& other); diff --git a/zen/string_traits.h b/zen/string_traits.h index f192e045..69c1fbc8 100644 --- a/zen/string_traits.h +++ b/zen/string_traits.h @@ -81,6 +81,7 @@ public: template <class S, bool isStringClass> struct GetCharTypeImpl : ResultType<NullType> {}; + template <class S> struct GetCharTypeImpl<S, true> : ResultType< diff --git a/zen/tick_count.h b/zen/tick_count.h index 893d8e80..cb15fe20 100644 --- a/zen/tick_count.h +++ b/zen/tick_count.h @@ -10,6 +10,7 @@ #include <cstdint> #include "type_traits.h" #include "basic_math.h" + #ifdef ZEN_WIN #include "win.h" //includes "windows.h" @@ -19,31 +20,20 @@ #elif defined ZEN_MAC #include <mach/mach_time.h> #endif -//#include <algorithm> -//#include "assert_static.h" -//#include <cmath> //template <class T> inline //T dist(T a, T b) //{ // return a > b ? a - b : b - a; //} - - namespace zen { //a portable "GetTickCount()" using "wall time equivalent" - e.g. no jumps due to ntp time corrections class TickVal; -std::int64_t dist(const TickVal& lhs, const TickVal& rhs); //use absolute difference for paranoid security: even QueryPerformanceCounter "wraps-around" at *some* time - -std::int64_t ticksPerSec(); //return 0 on error -TickVal getTicks(); //return invalid value on error: !TickVal::isValid() - - - - - +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() @@ -69,17 +59,17 @@ public: explicit TickVal(const NativeVal& val) : val_(val) {} inline friend - std::int64_t dist(const TickVal& lhs, const TickVal& rhs) + 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 - const auto distSec = numeric::dist(lhs.val_.tv_sec, rhs.val_.tv_sec); - const auto distNsec = numeric::dist(lhs.val_.tv_nsec, rhs.val_.tv_nsec); - - if (distSec > (std::numeric_limits<std::int64_t>::max() - distNsec) / 1000000000) //truncate instead of overflow! - return std::numeric_limits<std::int64_t>::max(); - return distSec * 1000000000 + distNsec; +//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 @@ -107,13 +97,13 @@ private: inline -std::int64_t ticksPerSec() //return 0 on error +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; - static_assert(sizeof(std::int64_t) >= sizeof(frequency.QuadPart), ""); + static_assert(sizeof(int64_t) >= sizeof(frequency.QuadPart), ""); return frequency.QuadPart; #elif defined ZEN_LINUX @@ -123,7 +113,10 @@ std::int64_t ticksPerSec() //return 0 on error mach_timebase_info_data_t tbi = {}; if (::mach_timebase_info(&tbi) != KERN_SUCCESS) return 0; - return 1000000000 * tbi.denom / tbi.numer; +//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 } diff --git a/zen/type_traits.h b/zen/type_traits.h index f69c155a..1c2da5eb 100644 --- a/zen/type_traits.h +++ b/zen/type_traits.h @@ -36,6 +36,13 @@ struct ResultType typedef T Type; }; +//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 std::make_signed<T>::type(t); } + +template<class T> inline +typename std::make_unsigned<T>::type makeUnsigned(T t) { return std::make_unsigned<T>::type(t); } + //################# Built-in Types ######################## //Example: "IsSignedInt<int>::value" evaluates to "true" @@ -247,7 +247,6 @@ size_t unicodeLength(const CharString& str, char) //utf8 while (strFirst < strLast) //[!] { ++len; - size_t utf8len = getUtf8Len(*strFirst); if (utf8len == 0) ++utf8len; //invalid utf8 character strFirst += utf8len; @@ -311,13 +310,15 @@ size_t findUnicodePos(const CharString& str, size_t unicodePos, char) //utf8-cha size_t utfPos = 0; while (unicodePos-- > 0) { + if (utfPos >= strLen) + return strLen; + size_t utf8len = getUtf8Len(strFirst[utfPos]); if (utf8len == 0) ++utf8len; //invalid utf8 character utfPos += utf8len; - - if (utfPos >= strLen) - return strLen; } + if (utfPos >= strLen) + return strLen; return utfPos; } @@ -333,13 +334,15 @@ size_t findUnicodePosWide(const WideString& str, size_t unicodePos, Int2Type<2>) size_t utfPos = 0; while (unicodePos-- > 0) { - size_t utf16len = getUtf16Len(strFirst[utfPos]); - if (utf16len == 0) ++utf16len; //invalid utf16 character - utfPos += utf16len; - if (utfPos >= strLen) return strLen; + + size_t utf16len = getUtf16Len(strFirst[utfPos]); + if (utf16len == 0) ++utf16len; //invalid utf16 character + utfPos += utf16len; } + if (utfPos >= strLen) + return strLen; return utfPos; } |