/* Copyright (C) 2015 Srivats P. This file is part of "Ostinato" This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ #ifndef _UINT128_H #define _UINT128_H #include #include #include #include class UInt128 { public: UInt128(); UInt128(int lo); UInt128(quint64 hi, quint64 lo); UInt128(quint8 *value); quint64 hi64() const; quint64 lo64() const; quint8* toArray() const; bool operator!() const; bool operator==(const UInt128 &other) const; bool operator!=(const UInt128 &other) const; UInt128 operator+(const UInt128 &other) const; UInt128 operator-(const UInt128 &other) const; UInt128 operator*(const uint &other) const; UInt128 operator<<(const int &shift) const; UInt128 operator~() const; UInt128 operator&(const UInt128 &other) const; UInt128 operator|(const UInt128 &other) const; private: quint64 hi_; quint64 lo_; quint8 array_[16]; }; Q_DECLARE_METATYPE(UInt128); inline UInt128::UInt128() { // Do nothing - value will be garbage like any other uint } inline UInt128::UInt128(int lo) { hi_ = 0; lo_ = lo; } inline UInt128::UInt128(quint64 hi, quint64 lo) { hi_ = hi; lo_ = lo; } inline UInt128::UInt128(quint8 *value) { hi_ = (quint64(value[0]) << 56) | (quint64(value[1]) << 48) | (quint64(value[2]) << 40) | (quint64(value[3]) << 32) | (quint64(value[4]) << 24) | (quint64(value[5]) << 16) | (quint64(value[6]) << 8) | (quint64(value[7]) << 0); lo_ = (quint64(value[ 8]) << 56) | (quint64(value[ 9]) << 48) | (quint64(value[10]) << 40) | (quint64(value[11]) << 32) | (quint64(value[12]) << 24) | (quint64(value[13]) << 16) | (quint64(value[14]) << 8) | (quint64(value[15]) << 0); } inline quint64 UInt128::hi64() const { return hi_; } inline quint64 UInt128::lo64() const { return lo_; } inline quint8* UInt128::toArray() const { qToBigEndian(hi_, const_cast(array_ + 0)); qToBigEndian(lo_, const_cast(array_ + 8)); return (quint8*)array_; } inline bool UInt128::operator!() const { return (hi_ == 0) && (lo_ == 0); } inline bool UInt128::operator==(const UInt128 &other) const { return ((hi_ == other.hi_) && (lo_ == other.lo_)); } inline bool UInt128::operator!=(const UInt128 &other) const { return ((hi_ != other.hi_) || (lo_ != other.lo_)); } inline UInt128 UInt128::operator+(const UInt128 &other) const { UInt128 sum; sum.lo_ = lo_ + other.lo_; sum.hi_ = hi_ + other.hi_ + (sum.lo_ < lo_); return sum; } inline UInt128 UInt128::operator-(const UInt128 &other) const { UInt128 diff; diff.lo_ = lo_ - other.lo_; diff.hi_ = hi_ - other.hi_ - (diff.lo_ > lo_); return diff; } inline UInt128 UInt128::operator*(const uint &other) const { UInt128 product; // FIXME product.hi_ = 0; product.lo_ = lo_ * other; return product; } inline UInt128 UInt128::operator<<(const int &shift) const { UInt128 shifted; if (shift < 64) return UInt128((hi_<>(64-shift)), lo_ << shift); return UInt128(hi_<<(shift-64), 0); } inline UInt128 UInt128::operator~() const { return UInt128(~hi_, ~lo_); } inline UInt128 UInt128::operator&(const UInt128 &other) const { return UInt128(hi_ & other.hi_, lo_ & other.lo_); } inline UInt128 UInt128::operator|(const UInt128 &other) const { return UInt128(hi_ | other.hi_, lo_ | other.lo_); } #if QT_VERSION >= 0x050700 template <> inline UInt128 qFromBigEndian(const void *src) #else template <> inline UInt128 qFromBigEndian(const uchar *src) #endif { quint64 hi, lo; hi = qFromBigEndian(src); lo = qFromBigEndian((uchar*)src+8); return UInt128(hi, lo); } #if QT_VERSION >= 0x050700 template <> inline void qToBigEndian(UInt128 src, void *dest) #else template <> inline void qToBigEndian(UInt128 src, uchar *dest) #endif { memcpy(dest, src.toArray(), 16); } template <> inline UInt128 qToBigEndian(const UInt128 src) { quint64 hi, lo; hi = qToBigEndian(src.hi64()); lo = qToBigEndian(src.lo64()); return UInt128(hi, lo); } inline QDebug operator<<(QDebug debug, const UInt128 &value) { QDebugStateSaver saver(debug); debug.maybeSpace() << hex << value.hi64() << " " << value.lo64(); return debug; } inline uint qHash(const UInt128 &key) { return qHash(key.hi64()) ^ qHash(key.lo64()); } #endif