summaryrefslogtreecommitdiff
path: root/zen/int64.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2015-10-02 14:52:04 +0200
committerDaniel Wilhelm <daniel@wili.li>2015-10-02 14:52:04 +0200
commit1845c028b8cb8496d1d78f0da738120e1c31401a (patch)
treeadf9fb436aea09be367aef8ed3b6cdbf6a46e34c /zen/int64.h
parent6.7 (diff)
downloadFreeFileSync-1845c028b8cb8496d1d78f0da738120e1c31401a.tar.gz
FreeFileSync-1845c028b8cb8496d1d78f0da738120e1c31401a.tar.bz2
FreeFileSync-1845c028b8cb8496d1d78f0da738120e1c31401a.zip
6.8
Diffstat (limited to 'zen/int64.h')
-rw-r--r--zen/int64.h222
1 files changed, 18 insertions, 204 deletions
diff --git a/zen/int64.h b/zen/int64.h
index f658e034..4183c8da 100644
--- a/zen/int64.h
+++ b/zen/int64.h
@@ -7,251 +7,65 @@
#ifndef FFS_LARGE_64_BIT_INTEGER_H_INCLUDED
#define FFS_LARGE_64_BIT_INTEGER_H_INCLUDED
-#include <cassert>
-#include <limits>
#include <cstdint>
-#include <cstdint>
-#include <ostream>
-#include "assert_static.h"
-#include "type_tools.h"
#ifdef ZEN_WIN
#include "win.h"
#endif
-/*
-zen::Int64/zen::UInt64: wrapper classes around std::int64_t/std::uint64_t
-
- - default initialization with 0
- - debug runtime overflow/underflow checks
- - safe and explicit semantics: no unsafe type conversions
- - safe conversion to and from Windows 64-bit integers
- - specializes std::numeric_limits
- - support stream operator<< and operator>>
-*/
-
namespace zen
{
-template <class T, class U> inline
-void checkRange(U value)
-{
- //caveat: std::numeric_limits<T>::min returns minimum positive(!) number for T = double, while behaving correctly for integer types... sigh
- assert(double(std::numeric_limits<T>::lowest()) <= double(value) && //new with C++11!
- double(std::numeric_limits<T>::max() ) >= double(value));
-}
-
-class Int64
-{
-public:
- //safe implicit conversions
- Int64() : value(0) {}
- Int64(const Int64& rhs) : value(rhs.value) {}
- template <class T>
- Int64(T rhs, typename EnableIf<IsSignedInt<T>::value&& sizeof(T) <= sizeof(std::int64_t)>::Type* = nullptr) :
- value(static_cast<std::int64_t>(rhs)) {}
-
- //unsafe explicit but checked conversion for all other integer types
- template <class T> explicit Int64(T rhs, typename EnableIf<!(IsSignedInt<T>::value&& sizeof(T) <= sizeof(std::int64_t))>::Type* = nullptr) :
- value(static_cast<std::int64_t>(rhs)) { checkRange<std::int64_t>(rhs); }
-
- Int64& operator=(const Int64& rhs) { value = rhs.value; return *this; }
-
#ifdef ZEN_WIN
- Int64(DWORD low, LONG high)
+inline
+ std::int64_t get64BitInt(DWORD low, LONG high)
{
- assert_static(sizeof(low) + sizeof(high) == sizeof(value));
+ static_assert(sizeof(low) + sizeof(high) == sizeof(std::int64_t), "");
LARGE_INTEGER cvt = {};
cvt.LowPart = low;
cvt.HighPart = high;
- value = cvt.QuadPart;
- }
- LONG getHi() const
- {
- LARGE_INTEGER cvt = {};
- cvt.QuadPart = value;
- return cvt.HighPart;
+ return cvt.QuadPart;
}
- DWORD getLo() const
- {
- LARGE_INTEGER cvt = {};
- cvt.QuadPart = value;
- return cvt.LowPart;
- }
-#endif
-
- Int64& operator+=(const Int64& rhs) { checkRange<std::int64_t>(double(value) + rhs.value); value += rhs.value; return *this; }
- Int64& operator-=(const Int64& rhs) { checkRange<std::int64_t>(double(value) - rhs.value); value -= rhs.value; return *this; }
- Int64& operator*=(const Int64& rhs) { checkRange<std::int64_t>(double(value) * rhs.value); value *= rhs.value; return *this; }
- Int64& operator/=(const Int64& rhs) { assert(rhs.value != 0); value /= rhs.value; return *this; }
- Int64& operator%=(const Int64& rhs) { assert(rhs.value != 0); value %= rhs.value; return *this; }
- Int64& operator&=(const Int64& rhs) { value &= rhs.value; return *this;}
- Int64& operator|=(const Int64& rhs) { value |= rhs.value; return *this;}
- Int64& operator<<=(int rhs) { assert(rhs < 0 || (value << rhs) >> rhs == value); value <<= rhs; return *this; }
- Int64& operator>>=(int rhs) { assert(rhs > 0 || (value >> rhs) << rhs == value); value >>= rhs; return *this; }
- Int64 operator-() const { return -value; }
-
- inline friend bool operator==(const Int64& lhs, const Int64& rhs) { return lhs.value == rhs.value; }
- inline friend bool operator!=(const Int64& lhs, const Int64& rhs) { return lhs.value != rhs.value; }
- inline friend bool operator< (const Int64& lhs, const Int64& rhs) { return lhs.value < rhs.value; }
- inline friend bool operator> (const Int64& lhs, const Int64& rhs) { return lhs.value > rhs.value; }
- inline friend bool operator<=(const Int64& lhs, const Int64& rhs) { return lhs.value <= rhs.value; }
- inline friend bool operator>=(const Int64& lhs, const Int64& rhs) { return lhs.value >= rhs.value; }
-
- //checked conversion to arbitrary target integer type
- template <class T> inline friend T to(Int64 number) { checkRange<T>(number.value); return static_cast<T>(number.value); }
- template <class T> inline friend std::basic_istream<T>& operator>>(std::basic_istream<T>& lhs, Int64& rhs) { lhs >> rhs.value; return lhs; }
- template <class T> inline friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, const Int64& rhs) { lhs << rhs.value; return lhs; }
+std::int64_t get64BitInt(std::uint64_t low, std::int64_t high) = delete;
-private:
- std::int64_t value;
-};
-inline Int64 operator+ (const Int64& lhs, const Int64& rhs) { return Int64(lhs) += rhs; }
-inline Int64 operator- (const Int64& lhs, const Int64& rhs) { return Int64(lhs) -= rhs; }
-inline Int64 operator* (const Int64& lhs, const Int64& rhs) { return Int64(lhs) *= rhs; }
-inline Int64 operator/ (const Int64& lhs, const Int64& rhs) { return Int64(lhs) /= rhs; }
-inline Int64 operator% (const Int64& lhs, const Int64& rhs) { return Int64(lhs) %= rhs; }
-inline Int64 operator& (const Int64& lhs, const Int64& rhs) { return Int64(lhs) &= rhs; }
-inline Int64 operator| (const Int64& lhs, const Int64& rhs) { return Int64(lhs) |= rhs; }
-inline Int64 operator<<(const Int64& lhs, int rhs) { return Int64(lhs) <<= rhs; }
-inline Int64 operator>>(const Int64& lhs, int rhs) { return Int64(lhs) >>= rhs; }
-
-
-class UInt64
-{
-public:
- //safe implicit conversions
- UInt64() : value(0) {}
- UInt64(const UInt64& rhs) : value(rhs.value) {}
- template <class T>
- UInt64(T rhs, typename EnableIf<IsUnsignedInt<T>::value&& sizeof(T) <= sizeof(std::uint64_t)>::Type* = nullptr) :
- value(static_cast<std::uint64_t>(rhs)) {}
-
- //unsafe explicit but checked conversion for all other integer types
- template <class T> explicit UInt64(T rhs, typename EnableIf<!(IsUnsignedInt<T>::value&& sizeof(T) <= sizeof(std::uint64_t))>::Type* = nullptr) :
- value(static_cast<std::uint64_t>(rhs)) { checkRange<std::uint64_t>(rhs); }
-
- UInt64& operator=(const UInt64& rhs) { value = rhs.value; return *this; }
-
-#ifdef ZEN_WIN
- UInt64(DWORD low, DWORD high)
+inline
+std::uint64_t get64BitUInt(DWORD low, DWORD high)
{
- assert_static(sizeof(low) + sizeof(high) == sizeof(value));
+ static_assert(sizeof(low) + sizeof(high) == sizeof(std::uint64_t), "");
ULARGE_INTEGER cvt = {};
cvt.LowPart = low;
cvt.HighPart = high;
- value = cvt.QuadPart;
- }
- DWORD getHi() const
- {
- ULARGE_INTEGER cvt = {};
- cvt.QuadPart = value;
- return cvt.HighPart;
- }
- DWORD getLo() const
- {
- ULARGE_INTEGER cvt = {};
- cvt.QuadPart = value;
- return cvt.LowPart;
+ return cvt.QuadPart;
}
-#endif
-
- UInt64& operator+=(const UInt64& rhs) { checkRange<std::uint64_t>(double(value) + rhs.value); value += rhs.value; return *this; }
- UInt64& operator-=(const UInt64& rhs) { checkRange<std::uint64_t>(double(value) - rhs.value); value -= rhs.value; return *this; }
- UInt64& operator*=(const UInt64& rhs) { checkRange<std::uint64_t>(double(value) * rhs.value); value *= rhs.value; return *this; }
- UInt64& operator/=(const UInt64& rhs) { assert(rhs.value != 0); value /= rhs.value; return *this; }
- UInt64& operator%=(const UInt64& rhs) { assert(rhs.value != 0); value %= rhs.value; return *this; }
- UInt64& operator&=(const UInt64& rhs) { value &= rhs.value; return *this;}
- UInt64& operator|=(const UInt64& rhs) { value |= rhs.value; return *this;}
- UInt64& operator<<=(int rhs) { assert(rhs < 0 || (value << rhs) >> rhs == value); value <<= rhs; return *this; }
- UInt64& operator>>=(int rhs) { assert(rhs > 0 || (value >> rhs) << rhs == value); value >>= rhs; return *this; }
-
- inline friend bool operator==(const UInt64& lhs, const UInt64& rhs) { return lhs.value == rhs.value; }
- inline friend bool operator!=(const UInt64& lhs, const UInt64& rhs) { return lhs.value != rhs.value; }
- inline friend bool operator< (const UInt64& lhs, const UInt64& rhs) { return lhs.value < rhs.value; }
- inline friend bool operator> (const UInt64& lhs, const UInt64& rhs) { return lhs.value > rhs.value; }
- inline friend bool operator<=(const UInt64& lhs, const UInt64& rhs) { return lhs.value <= rhs.value; }
- inline friend bool operator>=(const UInt64& lhs, const UInt64& rhs) { return lhs.value >= rhs.value; }
-
- //checked conversion to arbitrary target integer type
- template <class T> friend T to(UInt64 number);
-
- template <class T> inline friend std::basic_istream<T>& operator>>(std::basic_istream<T>& lhs, UInt64& rhs) { lhs >> rhs.value; return lhs; }
- template <class T> inline friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, const UInt64& rhs) { lhs << rhs.value; return lhs; }
-
-private:
- std::uint64_t value;
-};
-
-template <class T> inline T to(UInt64 number) { checkRange<T>(number.value); return static_cast<T>(number.value); } //Clang 3.2 doesn't properly handle inline-friends defined in class definition
-inline UInt64 operator+ (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) += rhs; }
-inline UInt64 operator- (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) -= rhs; }
-inline UInt64 operator* (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) *= rhs; }
-inline UInt64 operator/ (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) /= rhs; }
-inline UInt64 operator% (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) %= rhs; }
-inline UInt64 operator& (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) &= rhs; }
-inline UInt64 operator| (const UInt64& lhs, const UInt64& rhs) { return UInt64(lhs) |= rhs; }
-inline UInt64 operator<<(const UInt64& lhs, int rhs) { return UInt64(lhs) <<= rhs; }
-inline UInt64 operator>>(const UInt64& lhs, int rhs) { return UInt64(lhs) >>= rhs; }
+std::int64_t get64BitUInt(std::uint64_t low, std::uint64_t high) = delete;
-template <> inline UInt64 to(Int64 number) { checkRange<std::uint64_t>(number.value); return UInt64(number.value); }
-template <> inline Int64 to(UInt64 number) { checkRange<std:: int64_t>(number.value); return Int64(number.value); }
-
-#ifdef ZEN_WIN
//convert FILETIME (number of 100-nanosecond intervals since January 1, 1601 UTC)
// to time_t (number of seconds since Jan. 1st 1970 UTC)
//
//FAT32 time is preserved exactly: FAT32 -> toTimeT -> tofiletime -> FAT32
inline
-Int64 toTimeT(const FILETIME& ft)
+std::int64_t filetimeToTimeT(const FILETIME& ft)
{
- return to<Int64>(UInt64(ft.dwLowDateTime, ft.dwHighDateTime) / 10000000U) - Int64(3054539008UL, 2);
+ return static_cast<std::int64_t>(get64BitUInt(ft.dwLowDateTime, ft.dwHighDateTime) / 10000000U) - get64BitInt(3054539008UL, 2); //caveat: signed/unsigned arithmetics!
//timeshift between ansi C time and FILETIME in seconds == 11644473600s
}
inline
-FILETIME toFileTime(const Int64& utcTime)
-{
- const UInt64 fileTimeLong = to<UInt64>(utcTime + Int64(3054539008UL, 2)) * 10000000U;
- const FILETIME output = { fileTimeLong.getLo(), fileTimeLong.getHi() };
+FILETIME timetToFileTime(std::int64_t utcTime)
+{
+ ULARGE_INTEGER cvt = {};
+ cvt.QuadPart = (utcTime + get64BitInt(3054539008UL, 2)) * 10000000U; //caveat: signed/unsigned arithmetics!
+
+ const FILETIME output = { cvt.LowPart, cvt.HighPart };
return output;
}
#endif
}
-//specialize numeric limits
-namespace std
-{
-assert_static(std::numeric_limits<std:: int64_t>::is_specialized);
-assert_static(std::numeric_limits<std::uint64_t>::is_specialized);
-
-template <> class numeric_limits<zen::Int64> : public numeric_limits<std::int64_t>
-{
-public:
- static zen::Int64 min() throw() { return numeric_limits<std::int64_t>::min(); }
- static zen::Int64 max() throw() { return numeric_limits<std::int64_t>::max(); }
-};
-
-template <> class numeric_limits<zen::UInt64> : public numeric_limits<std::uint64_t>
-{
-public:
- static zen::UInt64 min() throw() { return numeric_limits<std::uint64_t>::min(); }
- static zen::UInt64 max() throw() { return numeric_limits<std::uint64_t>::max(); }
-};
-}
-
-/*
-//specialize zen type trait
-namespace zen -> we cannot mix signed/unsigned in general arithmetic operations -> we'll use the ostream-approach
-{
-template <> struct IsUnsignedInt<UInt64> : StaticBool<true> {};
-template <> struct IsSignedInt <Int64> : StaticBool<true> {};
-}
-*/
#endif //FFS_LARGE_64_BIT_INTEGER_H_INCLUDED
bgstack15