diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 7c643f7592..1d72ba0fae 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -63,7 +63,7 @@ template 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 inline void qToUnaligned(const T src, uchar *dest) { // Using sizeof(T) inside memcpy function produces internal compiler error with @@ -71,199 +71,14 @@ template 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) +template inline T qFromUnaligned(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); + T dest; + const size_t size = sizeof(T); + memcpy(&dest, src, size); + return dest; } -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(qFromLittleEndian_helper(src, reinterpret_cast(0))); } -inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest) -{ return static_cast(qFromLittleEndian_helper(src, reinterpret_cast(0))); } -inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest) -{ return static_cast(qFromLittleEndian_helper(src, reinterpret_cast(0))); } - -template inline T qFromLittleEndian(const uchar *src) -{ - return qFromLittleEndian_helper(src, reinterpret_cast(0)); -} - -#else -template inline T qFromLittleEndian(const uchar *src); -template <> inline quint64 qFromLittleEndian(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(const uchar *src) -{ - return 0 - | src[0] - | src[1] * quint32(0x00000100) - | src[2] * quint32(0x00010000) - | src[3] * quint32(0x01000000); -} - -template <> inline quint16 qFromLittleEndian(const uchar *src) -{ - return quint16(0 - | src[0] - | src[1] * 0x0100); -} - -// signed specializations -template <> inline qint64 qFromLittleEndian(const uchar *src) -{ return static_cast(qFromLittleEndian(src)); } - -template <> inline qint32 qFromLittleEndian(const uchar *src) -{ return static_cast(qFromLittleEndian(src)); } - -template <> inline qint16 qFromLittleEndian(const uchar *src) -{ return static_cast(qFromLittleEndian(src)); } -#endif - -template <> inline quint8 qFromLittleEndian(const uchar *src) -{ return static_cast(src[0]); } -template <> inline qint8 qFromLittleEndian(const uchar *src) -{ return static_cast(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(qFromBigEndian_helper(src, reinterpret_cast(0))); } -inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest) -{ return static_cast(qFromBigEndian_helper(src, reinterpret_cast(0))); } -inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest) -{ return static_cast(qFromBigEndian_helper(src, reinterpret_cast(0))); } - -template inline T qFromBigEndian(const uchar *src) -{ - return qFromBigEndian_helper(src, reinterpret_cast(0)); -} - -#else -template inline T qFromBigEndian(const uchar *src); -template<> -inline quint64 qFromBigEndian(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(const uchar *src) -{ - return 0 - | src[3] - | src[2] * quint32(0x00000100) - | src[1] * quint32(0x00010000) - | src[0] * quint32(0x01000000); -} - -template<> -inline quint16 qFromBigEndian(const uchar *src) -{ - return quint16( 0 - | src[1] - | src[0] * quint16(0x0100)); -} - - -// signed specializations -template <> inline qint64 qFromBigEndian(const uchar *src) -{ return static_cast(qFromBigEndian(src)); } - -template <> inline qint32 qFromBigEndian(const uchar *src) -{ return static_cast(qFromBigEndian(src)); } - -template <> inline qint16 qFromBigEndian(const uchar *src) -{ return static_cast(qFromBigEndian(src)); } -#endif - -template <> inline quint8 qFromBigEndian(const uchar *src) -{ return static_cast(src[0]); } -template <> inline qint8 qFromBigEndian(const uchar *src) -{ return static_cast(src[0]); } - /* * T qbswap(T source). * Changes the byte order of a value from big endian to little endian or vice versa. @@ -283,6 +98,15 @@ template <> inline quint32 qbswap(quint32 source) { return __builtin_bswap32(source); } + +template <> inline void qbswap(quint64 source, uchar *dest) +{ + qToUnaligned(__builtin_bswap64(source), dest); +} +template <> inline void qbswap(quint32 source, uchar *dest) +{ + qToUnaligned(__builtin_bswap32(source), dest); +} #else template <> inline quint64 qbswap(quint64 source) { @@ -311,6 +135,10 @@ template <> inline quint16 qbswap(quint16 source) { return __builtin_bswap16(source); } +template <> inline void qbswap(quint16 source, uchar *dest) +{ + qToUnaligned(__builtin_bswap16(source), dest); +} #else template <> inline quint16 qbswap(quint16 source) { @@ -336,6 +164,21 @@ template <> inline qint16 qbswap(qint16 source) return qbswap(quint16(source)); } +template <> inline void qbswap(qint64 source, uchar *dest) +{ + qbswap(quint64(source), dest); +} + +template <> inline void qbswap(qint32 source, uchar *dest) +{ + qbswap(quint32(source), dest); +} + +template <> inline void qbswap(qint16 source, uchar *dest) +{ + qbswap(quint16(source), dest); +} + #if Q_BYTE_ORDER == Q_BIG_ENDIAN template inline T qToBigEndian(T source) @@ -377,6 +220,35 @@ template <> inline qint8 qbswap(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 inline T qFromLittleEndian(const uchar *src) +{ + return qFromLittleEndian(qFromUnaligned(src)); +} + +template <> inline quint8 qFromLittleEndian(const uchar *src) +{ return static_cast(src[0]); } +template <> inline qint8 qFromLittleEndian(const uchar *src) +{ return static_cast(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 inline T qFromBigEndian(const uchar *src) +{ + return qFromBigEndian(qFromUnaligned(src)); +} + +template <> inline quint8 qFromBigEndian(const uchar *src) +{ return static_cast(src[0]); } +template <> inline qint8 qFromBigEndian(const uchar *src) +{ return static_cast(src[0]); } + QT_END_NAMESPACE #endif // QENDIAN_H