Move qle_bitfield to qendian_p.h
Makes the qle_bitfield template more generic and moves it to qendian_p.h It is also hardened to be more reliable. Change-Id: I53214ec99cceee4f5e8934ae688c99e555a5fb42 Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
01d5aaa0f6
commit
6ca65dd97d
@ -51,7 +51,7 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "qendian.h"
|
#include <QtCore/qendian.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -136,6 +136,88 @@ typedef QBEInteger<quint16> quint16_be;
|
|||||||
typedef QBEInteger<quint32> quint32_be;
|
typedef QBEInteger<quint32> quint32_be;
|
||||||
typedef QBEInteger<quint64> quint64_be;
|
typedef QBEInteger<quint64> quint64_be;
|
||||||
|
|
||||||
|
// Note if using multiple of these bitfields in a union; the underlying storage type must
|
||||||
|
// match. Since we always use an unsigned storage type, unsigned and signed versions may
|
||||||
|
// be used together, but different bit-widths may not.
|
||||||
|
template<class S, int pos, int width>
|
||||||
|
class QSpecialIntegerBitfield
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef typename S::StorageType T;
|
||||||
|
typedef typename std::make_unsigned<T>::type UT;
|
||||||
|
|
||||||
|
static Q_DECL_CONSTEXPR UT mask()
|
||||||
|
{
|
||||||
|
return ((UT(1) << width) - 1) << pos;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// FIXME: val is public until qtdeclarative is fixed to not access it directly.
|
||||||
|
UT val;
|
||||||
|
|
||||||
|
QSpecialIntegerBitfield &operator =(T t)
|
||||||
|
{
|
||||||
|
UT i = S::fromSpecial(val);
|
||||||
|
i &= ~mask();
|
||||||
|
i |= (UT(t) << pos) & mask();
|
||||||
|
val = S::toSpecial(i);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
if (std::is_signed<T>::value) {
|
||||||
|
UT i = S::fromSpecial(val);
|
||||||
|
i <<= (sizeof(T) * 8) - width - pos;
|
||||||
|
T t = T(i);
|
||||||
|
t >>= (sizeof(T) * 8) - width;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return (S::fromSpecial(val) & mask()) >> pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !() const { return !(val & S::toSpecial(mask())); }
|
||||||
|
bool operator ==(QSpecialIntegerBitfield<S, pos, width> i) const
|
||||||
|
{ return ((val ^ i.val) & S::toSpecial(mask())) == 0; }
|
||||||
|
bool operator !=(QSpecialIntegerBitfield<S, pos, width> i) const
|
||||||
|
{ return ((val ^ i.val) & S::toSpecial(mask())) != 0; }
|
||||||
|
|
||||||
|
QSpecialIntegerBitfield &operator +=(T i)
|
||||||
|
{ return (*this = (T(*this) + i)); }
|
||||||
|
QSpecialIntegerBitfield &operator -=(T i)
|
||||||
|
{ return (*this = (T(*this) - i)); }
|
||||||
|
QSpecialIntegerBitfield &operator *=(T i)
|
||||||
|
{ return (*this = (T(*this) * i)); }
|
||||||
|
QSpecialIntegerBitfield &operator /=(T i)
|
||||||
|
{ return (*this = (T(*this) / i)); }
|
||||||
|
QSpecialIntegerBitfield &operator %=(T i)
|
||||||
|
{ return (*this = (T(*this) % i)); }
|
||||||
|
QSpecialIntegerBitfield &operator |=(T i)
|
||||||
|
{ return (*this = (T(*this) | i)); }
|
||||||
|
QSpecialIntegerBitfield &operator &=(T i)
|
||||||
|
{ return (*this = (T(*this) & i)); }
|
||||||
|
QSpecialIntegerBitfield &operator ^=(T i)
|
||||||
|
{ return (*this = (T(*this) ^ i)); }
|
||||||
|
QSpecialIntegerBitfield &operator >>=(T i)
|
||||||
|
{ return (*this = (T(*this) >> i)); }
|
||||||
|
QSpecialIntegerBitfield &operator <<=(T i)
|
||||||
|
{ return (*this = (T(*this) << i)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, int pos, int width>
|
||||||
|
using QLEIntegerBitfield = QSpecialIntegerBitfield<QLittleEndianStorageType<T>, pos, width>;
|
||||||
|
|
||||||
|
template<typename T, int pos, int width>
|
||||||
|
using QBEIntegerBitfield = QSpecialIntegerBitfield<QBigEndianStorageType<T>, pos, width>;
|
||||||
|
|
||||||
|
template<int pos, int width>
|
||||||
|
using qint32_le_bitfield = QLEIntegerBitfield<int, pos, width>;
|
||||||
|
template<int pos, int width>
|
||||||
|
using quint32_le_bitfield = QLEIntegerBitfield<uint, pos, width>;
|
||||||
|
template<int pos, int width>
|
||||||
|
using qint32_be_bitfield = QBEIntegerBitfield<int, pos, width>;
|
||||||
|
template<int pos, int width>
|
||||||
|
using quint32_be_bitfield = QBEIntegerBitfield<uint, pos, width>;
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QENDIAN_P_H
|
#endif // QENDIAN_P_H
|
||||||
|
@ -140,97 +140,10 @@ typedef q_littleendian<int> qle_int;
|
|||||||
typedef q_littleendian<unsigned int> qle_uint;
|
typedef q_littleendian<unsigned int> qle_uint;
|
||||||
|
|
||||||
template<int pos, int width>
|
template<int pos, int width>
|
||||||
class qle_bitfield
|
using qle_bitfield = QLEIntegerBitfield<uint, pos, width>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint val;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
mask = ((1u << width) - 1) << pos
|
|
||||||
};
|
|
||||||
|
|
||||||
void operator =(uint t) {
|
|
||||||
uint i = qFromLittleEndian(val);
|
|
||||||
i &= ~mask;
|
|
||||||
i |= t << pos;
|
|
||||||
val = qToLittleEndian(i);
|
|
||||||
}
|
|
||||||
operator uint() const {
|
|
||||||
uint t = qFromLittleEndian(val);
|
|
||||||
t &= mask;
|
|
||||||
t >>= pos;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
bool operator !() const {
|
|
||||||
return !operator uint();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ==(uint t) { return uint(*this) == t; }
|
|
||||||
bool operator !=(uint t) { return uint(*this) != t; }
|
|
||||||
bool operator <(uint t) { return uint(*this) < t; }
|
|
||||||
bool operator >(uint t) { return uint(*this) > t; }
|
|
||||||
bool operator <=(uint t) { return uint(*this) <= t; }
|
|
||||||
bool operator >=(uint t) { return uint(*this) >= t; }
|
|
||||||
qle_bitfield &operator +=(uint i) {
|
|
||||||
*this = (uint(*this) + i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
qle_bitfield &operator -=(uint i) {
|
|
||||||
*this = (uint(*this) - i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
qle_bitfield &operator |=(uint i) {
|
|
||||||
*this = (uint(*this) | i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
qle_bitfield &operator &=(uint i) {
|
|
||||||
*this = (uint(*this) & i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int pos, int width>
|
template<int pos, int width>
|
||||||
class qle_signedbitfield
|
using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint val;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
mask = ((1u << width) - 1) << pos
|
|
||||||
};
|
|
||||||
|
|
||||||
void operator =(int t) {
|
|
||||||
uint i = qFromLittleEndian(val);
|
|
||||||
i &= ~mask;
|
|
||||||
i |= t << pos;
|
|
||||||
val = qToLittleEndian(i);
|
|
||||||
}
|
|
||||||
operator int() const {
|
|
||||||
uint i = qFromLittleEndian(val);
|
|
||||||
i <<= 32 - width - pos;
|
|
||||||
int t = (int) i;
|
|
||||||
t >>= 32 - width;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
bool operator !() const {
|
|
||||||
return !operator int();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ==(int t) { return int(*this) == t; }
|
|
||||||
bool operator !=(int t) { return int(*this) != t; }
|
|
||||||
bool operator <(int t) { return int(*this) < t; }
|
|
||||||
bool operator >(int t) { return int(*this) > t; }
|
|
||||||
bool operator <=(int t) { return int(*this) <= t; }
|
|
||||||
bool operator >=(int t) { return int(*this) >= t; }
|
|
||||||
qle_signedbitfield &operator +=(int i) {
|
|
||||||
*this = (int(*this) + i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
qle_signedbitfield &operator -=(int i) {
|
|
||||||
*this = (int(*this) - i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef qle_uint offset;
|
typedef qle_uint offset;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
CONFIG += testcase
|
CONFIG += testcase
|
||||||
TARGET = tst_qtendian
|
TARGET = tst_qtendian
|
||||||
QT = core testlib
|
QT = core core-private testlib
|
||||||
SOURCES = tst_qtendian.cpp
|
SOURCES = tst_qtendian.cpp
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
#include <QtCore/qendian.h>
|
#include <QtCore/qendian.h>
|
||||||
|
#include <QtCore/private/qendian_p.h>
|
||||||
|
|
||||||
|
|
||||||
class tst_QtEndian: public QObject
|
class tst_QtEndian: public QObject
|
||||||
@ -41,6 +42,11 @@ private slots:
|
|||||||
|
|
||||||
void toBigEndian();
|
void toBigEndian();
|
||||||
void toLittleEndian();
|
void toLittleEndian();
|
||||||
|
|
||||||
|
void endianIntegers_data();
|
||||||
|
void endianIntegers();
|
||||||
|
|
||||||
|
void endianBitfields();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestData
|
struct TestData
|
||||||
@ -129,5 +135,83 @@ void tst_QtEndian::toLittleEndian()
|
|||||||
|
|
||||||
#undef ENDIAN_TEST
|
#undef ENDIAN_TEST
|
||||||
|
|
||||||
|
void tst_QtEndian::endianIntegers_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<int>("val");
|
||||||
|
|
||||||
|
QTest::newRow("-30000") << -30000;
|
||||||
|
QTest::newRow("-1") << -1;
|
||||||
|
QTest::newRow("0") << 0;
|
||||||
|
QTest::newRow("1020") << 1020;
|
||||||
|
QTest::newRow("16385") << 16385;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QtEndian::endianIntegers()
|
||||||
|
{
|
||||||
|
QFETCH(int, val);
|
||||||
|
|
||||||
|
qint16 vi16 = val;
|
||||||
|
qint32 vi32 = val;
|
||||||
|
qint64 vi64 = val;
|
||||||
|
quint16 vu16 = val;
|
||||||
|
quint32 vu32 = val;
|
||||||
|
quint64 vu64 = val;
|
||||||
|
|
||||||
|
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||||
|
QCOMPARE(*reinterpret_cast<qint16_be*>(&vi16), vi16);
|
||||||
|
QCOMPARE(*reinterpret_cast<qint32_be*>(&vi32), vi32);
|
||||||
|
QCOMPARE(*reinterpret_cast<qint64_be*>(&vi64), vi64);
|
||||||
|
QCOMPARE(*reinterpret_cast<qint16_le*>(&vi16), qbswap(vi16));
|
||||||
|
QCOMPARE(*reinterpret_cast<qint32_le*>(&vi32), qbswap(vi32));
|
||||||
|
QCOMPARE(*reinterpret_cast<qint64_le*>(&vi64), qbswap(vi64));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint16_be*>(&vu16), vu16);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint32_be*>(&vu32), vu32);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint64_be*>(&vu64), vu64);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint16_le*>(&vu16), qbswap(vu16));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint32_le*>(&vu32), qbswap(vu32));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint64_le*>(&vu64), qbswap(vu64));
|
||||||
|
#else
|
||||||
|
QCOMPARE(*reinterpret_cast<qint16_be*>(&vi16), qbswap(vi16));
|
||||||
|
QCOMPARE(*reinterpret_cast<qint32_be*>(&vi32), qbswap(vi32));
|
||||||
|
QCOMPARE(*reinterpret_cast<qint64_be*>(&vi64), qbswap(vi64));
|
||||||
|
QCOMPARE(*reinterpret_cast<qint16_le*>(&vi16), vi16);
|
||||||
|
QCOMPARE(*reinterpret_cast<qint32_le*>(&vi32), vi32);
|
||||||
|
QCOMPARE(*reinterpret_cast<qint64_le*>(&vi64), vi64);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint16_be*>(&vu16), qbswap(vu16));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint32_be*>(&vu32), qbswap(vu32));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint64_be*>(&vu64), qbswap(vu64));
|
||||||
|
QCOMPARE(*reinterpret_cast<quint16_le*>(&vu16), vu16);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint32_le*>(&vu32), vu32);
|
||||||
|
QCOMPARE(*reinterpret_cast<quint64_le*>(&vu64), vu64);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QtEndian::endianBitfields()
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
quint32_be_bitfield<21, 11> upper;
|
||||||
|
quint32_be_bitfield<10, 11> lower;
|
||||||
|
qint32_be_bitfield<0, 10> bottom;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
u.upper = 200;
|
||||||
|
QCOMPARE(u.upper, 200U);
|
||||||
|
u.lower = 1000;
|
||||||
|
u.bottom = -8;
|
||||||
|
QCOMPARE(u.lower, 1000U);
|
||||||
|
QCOMPARE(u.upper, 200U);
|
||||||
|
|
||||||
|
u.lower += u.upper;
|
||||||
|
QCOMPARE(u.upper, 200U);
|
||||||
|
QCOMPARE(u.lower, 1200U);
|
||||||
|
|
||||||
|
u.upper = 65536 + 7;
|
||||||
|
u.lower = 65535;
|
||||||
|
QCOMPARE(u.lower, 65535U & ((1<<11) - 1));
|
||||||
|
QCOMPARE(u.upper, 7U);
|
||||||
|
|
||||||
|
QCOMPARE(u.bottom, -8);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QtEndian)
|
QTEST_MAIN(tst_QtEndian)
|
||||||
#include "tst_qtendian.moc"
|
#include "tst_qtendian.moc"
|
||||||
|
Loading…
Reference in New Issue
Block a user