diff options
Diffstat (limited to 'src/corelib/global/qendian.h')
-rw-r--r-- | src/corelib/global/qendian.h | 254 |
1 files changed, 63 insertions, 191 deletions
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 0e383c18d2..957ba2ad63 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -63,7 +63,7 @@ template <typename T> inline void qbswap(const T src, uchar *dest) } // Used to implement a type-safe and alignment-safe copy operation -// If you want to avoid the memcopy, you must write specializations for this function +// If you want to avoid the memcpy, you must write specializations for these functions template <typename T> inline void qToUnaligned(const T src, uchar *dest) { // Using sizeof(T) inside memcpy function produces internal compiler error with @@ -71,199 +71,14 @@ template <typename T> inline void qToUnaligned(const T src, uchar *dest) const size_t size = sizeof(T); memcpy(dest, &src, size); } - -/* T qFromLittleEndian(const uchar *src) - * This function will read a little-endian encoded value from \a src - * and return the value in host-endian encoding. - * There is no requirement that \a src must be aligned. -*/ -#if defined Q_CC_SUN -inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest) -{ - return 0 - | src[0] - | src[1] * Q_UINT64_C(0x0000000000000100) - | src[2] * Q_UINT64_C(0x0000000000010000) - | src[3] * Q_UINT64_C(0x0000000001000000) - | src[4] * Q_UINT64_C(0x0000000100000000) - | src[5] * Q_UINT64_C(0x0000010000000000) - | src[6] * Q_UINT64_C(0x0001000000000000) - | src[7] * Q_UINT64_C(0x0100000000000000); -} - -inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest) -{ - return 0 - | src[0] - | src[1] * quint32(0x00000100) - | src[2] * quint32(0x00010000) - | src[3] * quint32(0x01000000); -} - -inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest) -{ - return 0 - | src[0] - | src[1] * 0x0100; -} - -inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest) -{ return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); } -inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest) -{ return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); } -inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest) -{ return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); } - -template <class T> inline T qFromLittleEndian(const uchar *src) -{ - return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0)); -} - -#else -template <typename T> inline T qFromLittleEndian(const uchar *src); -template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src) -{ - return 0 - | src[0] - | src[1] * Q_UINT64_C(0x0000000000000100) - | src[2] * Q_UINT64_C(0x0000000000010000) - | src[3] * Q_UINT64_C(0x0000000001000000) - | src[4] * Q_UINT64_C(0x0000000100000000) - | src[5] * Q_UINT64_C(0x0000010000000000) - | src[6] * Q_UINT64_C(0x0001000000000000) - | src[7] * Q_UINT64_C(0x0100000000000000); -} - -template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src) -{ - return 0 - | src[0] - | src[1] * quint32(0x00000100) - | src[2] * quint32(0x00010000) - | src[3] * quint32(0x01000000); -} - -template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src) -{ - return quint16(0 - | src[0] - | src[1] * 0x0100); -} - -// signed specializations -template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src) -{ return static_cast<qint64>(qFromLittleEndian<quint64>(src)); } - -template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src) -{ return static_cast<qint32>(qFromLittleEndian<quint32>(src)); } - -template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src) -{ return static_cast<qint16>(qFromLittleEndian<quint16>(src)); } -#endif - -template <> inline quint8 qFromLittleEndian<quint8>(const uchar *src) -{ return static_cast<quint8>(src[0]); } -template <> inline qint8 qFromLittleEndian<qint8>(const uchar *src) -{ return static_cast<qint8>(src[0]); } - -/* This function will read a big-endian (also known as network order) encoded value from \a src - * and return the value in host-endian encoding. - * There is no requirement that \a src must be aligned. -*/ -#if defined Q_CC_SUN -inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest) -{ - return 0 - | src[7] - | src[6] * Q_UINT64_C(0x0000000000000100) - | src[5] * Q_UINT64_C(0x0000000000010000) - | src[4] * Q_UINT64_C(0x0000000001000000) - | src[3] * Q_UINT64_C(0x0000000100000000) - | src[2] * Q_UINT64_C(0x0000010000000000) - | src[1] * Q_UINT64_C(0x0001000000000000) - | src[0] * Q_UINT64_C(0x0100000000000000); -} - -inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest) -{ - return 0 - | src[3] - | src[2] * quint32(0x00000100) - | src[1] * quint32(0x00010000) - | src[0] * quint32(0x01000000); -} - -inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des) -{ - return 0 - | src[1] - | src[0] * 0x0100; -} - - -inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest) -{ return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); } -inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest) -{ return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); } -inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest) -{ return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); } - -template <class T> inline T qFromBigEndian(const uchar *src) -{ - return qFromBigEndian_helper(src, reinterpret_cast<T*>(0)); -} - -#else -template <class T> inline T qFromBigEndian(const uchar *src); -template<> -inline quint64 qFromBigEndian<quint64>(const uchar *src) +template <typename T> inline T qFromUnaligned(const uchar *src) { - return 0 - | src[7] - | src[6] * Q_UINT64_C(0x0000000000000100) - | src[5] * Q_UINT64_C(0x0000000000010000) - | src[4] * Q_UINT64_C(0x0000000001000000) - | src[3] * Q_UINT64_C(0x0000000100000000) - | src[2] * Q_UINT64_C(0x0000010000000000) - | src[1] * Q_UINT64_C(0x0001000000000000) - | src[0] * Q_UINT64_C(0x0100000000000000); -} - -template<> -inline quint32 qFromBigEndian<quint32>(const uchar *src) -{ - return 0 - | src[3] - | src[2] * quint32(0x00000100) - | src[1] * quint32(0x00010000) - | src[0] * quint32(0x01000000); -} - -template<> -inline quint16 qFromBigEndian<quint16>(const uchar *src) -{ - return quint16( 0 - | src[1] - | src[0] * quint16(0x0100)); + T dest; + const size_t size = sizeof(T); + memcpy(&dest, src, size); + return dest; } - -// signed specializations -template <> inline qint64 qFromBigEndian<qint64>(const uchar *src) -{ return static_cast<qint64>(qFromBigEndian<quint64>(src)); } - -template <> inline qint32 qFromBigEndian<qint32>(const uchar *src) -{ return static_cast<qint32>(qFromBigEndian<quint32>(src)); } - -template <> inline qint16 qFromBigEndian<qint16>(const uchar *src) -{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); } -#endif - -template <> inline quint8 qFromBigEndian<quint8>(const uchar *src) -{ return static_cast<quint8>(src[0]); } -template <> inline qint8 qFromBigEndian<qint8>(const uchar *src) -{ return static_cast<qint8>(src[0]); } - /* * T qbswap(T source). * Changes the byte order of a value from big endian to little endian or vice versa. @@ -289,6 +104,15 @@ template <> inline quint32 qbswap<quint32>(quint32 source) { return __builtin_bswap32(source); } + +template <> inline void qbswap<quint64>(quint64 source, uchar *dest) +{ + qToUnaligned<quint64>(__builtin_bswap64(source), dest); +} +template <> inline void qbswap<quint32>(quint32 source, uchar *dest) +{ + qToUnaligned<quint32>(__builtin_bswap32(source), dest); +} #else template <> inline quint64 qbswap<quint64>(quint64 source) { @@ -317,6 +141,10 @@ template <> inline quint16 qbswap<quint16>(quint16 source) { return __builtin_bswap16(source); } +template <> inline void qbswap<quint16>(quint16 source, uchar *dest) +{ + qToUnaligned<quint16>(__builtin_bswap16(source), dest); +} #else template <> inline quint16 qbswap<quint16>(quint16 source) { @@ -344,6 +172,21 @@ template <> inline qint16 qbswap<qint16>(qint16 source) return qbswap<quint16>(quint16(source)); } +template <> inline void qbswap<qint64>(qint64 source, uchar *dest) +{ + qbswap<quint64>(quint64(source), dest); +} + +template <> inline void qbswap<qint32>(qint32 source, uchar *dest) +{ + qbswap<quint32>(quint32(source), dest); +} + +template <> inline void qbswap<qint16>(qint16 source, uchar *dest) +{ + qbswap<quint16>(quint16(source), dest); +} + #if Q_BYTE_ORDER == Q_BIG_ENDIAN template <typename T> inline T qToBigEndian(T source) @@ -385,6 +228,35 @@ template <> inline qint8 qbswap<qint8>(qint8 source) return source; } +/* T qFromLittleEndian(const uchar *src) + * This function will read a little-endian encoded value from \a src + * and return the value in host-endian encoding. + * There is no requirement that \a src must be aligned. +*/ +template <typename T> inline T qFromLittleEndian(const uchar *src) +{ + return qFromLittleEndian(qFromUnaligned<T>(src)); +} + +template <> inline quint8 qFromLittleEndian<quint8>(const uchar *src) +{ return static_cast<quint8>(src[0]); } +template <> inline qint8 qFromLittleEndian<qint8>(const uchar *src) +{ return static_cast<qint8>(src[0]); } + +/* This function will read a big-endian (also known as network order) encoded value from \a src + * and return the value in host-endian encoding. + * There is no requirement that \a src must be aligned. +*/ +template <class T> inline T qFromBigEndian(const uchar *src) +{ + return qFromBigEndian(qFromUnaligned<T>(src)); +} + +template <> inline quint8 qFromBigEndian<quint8>(const uchar *src) +{ return static_cast<quint8>(src[0]); } +template <> inline qint8 qFromBigEndian<qint8>(const uchar *src) +{ return static_cast<qint8>(src[0]); } + QT_END_NAMESPACE #endif // QENDIAN_H |