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:
Ivan Komissarov 2018-10-22 19:08:57 +02:00
parent 269172037d
commit 95476bfcf6
2 changed files with 63 additions and 3 deletions

View File

@ -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

View File

@ -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 { \