qendian: Fix float conversions
Since Qt 5.10, qTo/FromBig/LittleEndian<float/double> stopped working. It may be confusing, but big endian floats do exist, so not to break old code, we should support them. Change-Id: I21cdbc7f48ec030ce3d82f1cd1aad212f0fe5dd0 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
269172037d
commit
95476bfcf6
@ -41,6 +41,7 @@
|
||||
#ifndef QENDIAN_H
|
||||
#define QENDIAN_H
|
||||
|
||||
#include <QtCore/qfloat16.h>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
|
||||
@ -151,6 +152,31 @@ template <> inline Q_DECL_CONSTEXPR qint8 qbswap<qint8>(qint8 source)
|
||||
return source;
|
||||
}
|
||||
|
||||
// floating specializations
|
||||
template<typename Float>
|
||||
Float qbswapFloatHelper(Float source)
|
||||
{
|
||||
// memcpy call in qFromUnaligned is recognized by optimizer as a correct way of type prunning
|
||||
auto temp = qFromUnaligned<typename QIntegerForSizeof<Float>::Unsigned>(&source);
|
||||
temp = qbswap(temp);
|
||||
return qFromUnaligned<Float>(&temp);
|
||||
}
|
||||
|
||||
template <> inline qfloat16 qbswap<qfloat16>(qfloat16 source)
|
||||
{
|
||||
return qbswapFloatHelper(source);
|
||||
}
|
||||
|
||||
template <> inline float qbswap<float>(float source)
|
||||
{
|
||||
return qbswapFloatHelper(source);
|
||||
}
|
||||
|
||||
template <> inline double qbswap<double>(double source)
|
||||
{
|
||||
return qbswapFloatHelper(source);
|
||||
}
|
||||
|
||||
/*
|
||||
* qbswap(const T src, const void *dest);
|
||||
* Changes the byte order of \a src from big endian to little endian or vice versa
|
||||
|
@ -64,6 +64,9 @@ struct TestData
|
||||
quint16 data16;
|
||||
quint8 data8;
|
||||
|
||||
float dataFloat;
|
||||
double dataDouble;
|
||||
|
||||
quint8 reserved;
|
||||
};
|
||||
|
||||
@ -72,6 +75,7 @@ template <> quint8 getData(const TestData &d) { return d.data8; }
|
||||
template <> quint16 getData(const TestData &d) { return d.data16; }
|
||||
template <> quint32 getData(const TestData &d) { return d.data32; }
|
||||
template <> quint64 getData(const TestData &d) { return d.data64; }
|
||||
template <> float getData(const TestData &d) { return d.dataFloat; }
|
||||
|
||||
union RawTestData
|
||||
{
|
||||
@ -79,9 +83,39 @@ union RawTestData
|
||||
TestData data;
|
||||
};
|
||||
|
||||
static const TestData inNativeEndian = { Q_UINT64_C(0x0123456789abcdef), 0x00c0ffee, 0xcafe, 0xcf, '\0' };
|
||||
static const RawTestData inBigEndian = { "\x01\x23\x45\x67\x89\xab\xcd\xef" "\x00\xc0\xff\xee" "\xca\xfe" "\xcf" };
|
||||
static const RawTestData inLittleEndian = { "\xef\xcd\xab\x89\x67\x45\x23\x01" "\xee\xff\xc0\x00" "\xfe\xca" "\xcf" };
|
||||
template <typename Float>
|
||||
Float int2Float(typename QIntegerForSizeof<Float>::Unsigned i)
|
||||
{
|
||||
Float result = 0;
|
||||
memcpy(reinterpret_cast<char *>(&result), reinterpret_cast<const char *>(&i), sizeof (Float));
|
||||
return result;
|
||||
}
|
||||
|
||||
static const TestData inNativeEndian = {
|
||||
Q_UINT64_C(0x0123456789abcdef),
|
||||
0x00c0ffee,
|
||||
0xcafe,
|
||||
0xcf,
|
||||
int2Float<float>(0x00c0ffeeU),
|
||||
int2Float<double>(Q_UINT64_C(0x0123456789abcdef)),
|
||||
'\0'
|
||||
};
|
||||
static const RawTestData inBigEndian = {
|
||||
"\x01\x23\x45\x67\x89\xab\xcd\xef"
|
||||
"\x00\xc0\xff\xee"
|
||||
"\xca\xfe"
|
||||
"\xcf"
|
||||
"\x00\xc0\xff\xee"
|
||||
"\x01\x23\x45\x67\x89\xab\xcd\xef"
|
||||
};
|
||||
static const RawTestData inLittleEndian = {
|
||||
"\xef\xcd\xab\x89\x67\x45\x23\x01"
|
||||
"\xee\xff\xc0\x00"
|
||||
"\xfe\xca"
|
||||
"\xcf"
|
||||
"\xee\xff\xc0\x00"
|
||||
"\xef\xcd\xab\x89\x67\x45\x23\x01"
|
||||
};
|
||||
|
||||
#define EXPAND_ENDIAN_TEST(endian) \
|
||||
do { \
|
||||
|
Loading…
Reference in New Issue
Block a user