diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 4e9cd2e6e3..cacb822947 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -52,22 +52,6 @@ QT_BEGIN_NAMESPACE /* * ENDIAN FUNCTIONS */ -inline void qbswap_helper(const void *src, void *dest, int size) -{ - for (int i = 0; i < size ; ++i) - static_cast(dest)[i] = static_cast(src)[size - 1 - i]; -} - -/* - * qbswap(const T src, const void *dest); - * Changes the byte order of \a src from big endian to little endian or vice versa - * and stores the result in \a dest. - * There is no alignment requirements for \a dest. -*/ -template inline void qbswap(const T src, void *dest) -{ - qbswap_helper(&src, dest, sizeof(T)); -} // Used to implement a type-safe and alignment-safe copy operation // If you want to avoid the memcpy, you must write specializations for these functions @@ -103,30 +87,11 @@ template Q_ALWAYS_INLINE T qFromUnaligned(const void *src) * This function can be used if you are not concerned about alignment issues, * and it is therefore a bit more convenient and in most cases more efficient. */ -template T qbswap(T source); +template Q_DECL_CONSTEXPR T qbswap(T source); -// GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8; -// Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one -#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32) -template <> inline quint64 qbswap(quint64 source) -{ - return __builtin_bswap64(source); -} -template <> inline quint32 qbswap(quint32 source) -{ - return __builtin_bswap32(source); -} - -template <> inline void qbswap(quint64 source, void *dest) -{ - qToUnaligned(__builtin_bswap64(source), dest); -} -template <> inline void qbswap(quint32 source, void *dest) -{ - qToUnaligned(__builtin_bswap32(source), dest); -} -#else -template <> inline quint64 qbswap(quint64 source) +// These definitions are written so that they are recognized by most compilers +// as bswap and replaced with single instruction builtins if available. +template <> inline Q_DECL_CONSTEXPR quint64 qbswap(quint64 source) { return 0 | ((source & Q_UINT64_C(0x00000000000000ff)) << 56) @@ -139,7 +104,7 @@ template <> inline quint64 qbswap(quint64 source) | ((source & Q_UINT64_C(0xff00000000000000)) >> 56); } -template <> inline quint32 qbswap(quint32 source) +template <> inline Q_DECL_CONSTEXPR quint32 qbswap(quint32 source) { return 0 | ((source & 0x000000ff) << 24) @@ -147,65 +112,61 @@ template <> inline quint32 qbswap(quint32 source) | ((source & 0x00ff0000) >> 8) | ((source & 0xff000000) >> 24); } -#endif // GCC & Clang intrinsics -#if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16) -template <> inline quint16 qbswap(quint16 source) -{ - return __builtin_bswap16(source); -} -template <> inline void qbswap(quint16 source, void *dest) -{ - qToUnaligned(__builtin_bswap16(source), dest); -} -#else -template <> inline quint16 qbswap(quint16 source) + +template <> inline Q_DECL_CONSTEXPR quint16 qbswap(quint16 source) { return quint16( 0 | ((source & 0x00ff) << 8) | ((source & 0xff00) >> 8) ); } -#endif // GCC & Clang intrinsics + +template <> inline Q_DECL_CONSTEXPR quint8 qbswap(quint8 source) +{ + return source; +} // signed specializations -template <> inline qint64 qbswap(qint64 source) +template <> inline Q_DECL_CONSTEXPR qint64 qbswap(qint64 source) { return qbswap(quint64(source)); } -template <> inline qint32 qbswap(qint32 source) +template <> inline Q_DECL_CONSTEXPR qint32 qbswap(qint32 source) { return qbswap(quint32(source)); } -template <> inline qint16 qbswap(qint16 source) +template <> inline Q_DECL_CONSTEXPR qint16 qbswap(qint16 source) { return qbswap(quint16(source)); } -template <> inline void qbswap(qint64 source, void *dest) +template <> inline Q_DECL_CONSTEXPR qint8 qbswap(qint8 source) { - qbswap(quint64(source), dest); + return source; } -template <> inline void qbswap(qint32 source, void *dest) +/* + * qbswap(const T src, const void *dest); + * Changes the byte order of \a src from big endian to little endian or vice versa + * and stores the result in \a dest. + * There is no alignment requirements for \a dest. +*/ +template inline void qbswap(const T src, void *dest) { - qbswap(quint32(source), dest); + qToUnaligned(qbswap(src), dest); } -template <> inline void qbswap(qint16 source, void *dest) -{ - qbswap(quint16(source), dest); -} #if Q_BYTE_ORDER == Q_BIG_ENDIAN -template inline T qToBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qToBigEndian(T source) { return source; } -template inline T qFromBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromBigEndian(T source) { return source; } -template inline T qToLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qToLittleEndian(T source) { return qbswap(source); } -template inline T qFromLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source) { return qbswap(source); } template inline void qToBigEndian(T src, void *dest) { qToUnaligned(src, dest); } @@ -213,13 +174,13 @@ template inline void qToLittleEndian(T src, void *dest) { qbswap(src, dest); } #else // Q_LITTLE_ENDIAN -template inline T qToBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qToBigEndian(T source) { return qbswap(source); } -template inline T qFromBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromBigEndian(T source) { return qbswap(source); } -template inline T qToLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qToLittleEndian(T source) { return source; } -template inline T qFromLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source) { return source; } template inline void qToBigEndian(T src, void *dest) { qbswap(src, dest); } @@ -228,15 +189,6 @@ template inline void qToLittleEndian(T src, void *dest) #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN -template <> inline quint8 qbswap(quint8 source) -{ - return source; -} - -template <> inline qint8 qbswap(qint8 source) -{ - return source; -} /* T qFromLittleEndian(const void *src) * This function will read a little-endian encoded value from \a src