File indexing completed on 2024-05-12 05:46:52

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
0004 ** Contact: Qt Software Information (qt-info@nokia.com)
0005 **
0006 ** This file is part of the QtCore module of the Qt Toolkit.
0007 **
0008 ** $QT_BEGIN_LICENSE:LGPL$
0009 ** Commercial Usage
0010 ** Licensees holding valid Qt Commercial licenses may use this file in
0011 ** accordance with the Qt Commercial License Agreement provided with the
0012 ** Software or, alternatively, in accordance with the terms contained in
0013 ** a written agreement between you and Nokia.
0014 **
0015 ** GNU Lesser General Public License Usage
0016 ** Alternatively, this file may be used under the terms of the GNU Lesser
0017 ** General Public License version 2.1 as published by the Free Software
0018 ** Foundation and appearing in the file LICENSE.LGPL included in the
0019 ** packaging of this file.  Please review the following information to
0020 ** ensure the GNU Lesser General Public License version 2.1 requirements
0021 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0022 **
0023 ** In addition, as a special exception, Nokia gives you certain
0024 ** additional rights. These rights are described in the Nokia Qt LGPL
0025 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
0026 ** package.
0027 **
0028 ** GNU General Public License Usage
0029 ** Alternatively, this file may be used under the terms of the GNU
0030 ** General Public License version 3.0 as published by the Free Software
0031 ** Foundation and appearing in the file LICENSE.GPL included in the
0032 ** packaging of this file.  Please review the following information to
0033 ** ensure the GNU General Public License version 3.0 requirements will be
0034 ** met: http://www.gnu.org/copyleft/gpl.html.
0035 **
0036 ** If you are unsure which license is appropriate for your use, please
0037 ** contact the sales department at qt-sales@nokia.com.
0038 ** $QT_END_LICENSE$
0039 **
0040 ****************************************************************************/
0041 
0042 #ifndef QENDIAN_H
0043 #define QENDIAN_H
0044 
0045 #include <QtCore/qglobal.h>
0046 
0047 QT_BEGIN_HEADER
0048 
0049 QT_BEGIN_NAMESPACE
0050 
0051 QT_MODULE(Core)
0052 
0053 /*
0054  * ENDIAN FUNCTIONS
0055 */
0056 inline void qbswap_helper(const uchar *src, uchar *dest, int size)
0057 {
0058     for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
0059 }
0060 
0061 /*
0062  * qbswap(const T src, const uchar *dest);
0063  * Changes the byte order of \a src from big endian to little endian or vice versa
0064  * and stores the result in \a dest.
0065  * There is no alignment requirements for \a dest.
0066 */
0067 template <typename T> inline void qbswap(const T src, uchar *dest)
0068 {
0069     qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
0070 }
0071 
0072 // Used to implement a type-safe and alignment-safe copy operation
0073 // If you want to avoid the memcopy, you must write specializations for this function
0074 template <typename T> inline void qToUnaligned(const T src, uchar *dest)
0075 {
0076     qMemCopy(dest, &src, sizeof(T));
0077 }
0078 
0079 /* T qFromLittleEndian(const uchar *src)
0080  * This function will read a little-endian encoded value from \a src
0081  * and return the value in host-endian encoding.
0082  * There is no requirement that \a src must be aligned.
0083 */
0084 #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
0085 inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
0086 {
0087     return 0
0088         | src[0]
0089         | src[1] * Q_UINT64_C(0x0000000000000100)
0090         | src[2] * Q_UINT64_C(0x0000000000010000)
0091         | src[3] * Q_UINT64_C(0x0000000001000000)
0092         | src[4] * Q_UINT64_C(0x0000000100000000)
0093         | src[5] * Q_UINT64_C(0x0000010000000000)
0094         | src[6] * Q_UINT64_C(0x0001000000000000)
0095         | src[7] * Q_UINT64_C(0x0100000000000000);
0096 }
0097 
0098 inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
0099 {
0100     return 0
0101         | src[0]
0102         | src[1] * quint32(0x00000100)
0103         | src[2] * quint32(0x00010000)
0104         | src[3] * quint32(0x01000000);
0105 }
0106 
0107 inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
0108 {
0109     return 0
0110         | src[0]
0111         | src[1] * 0x0100;
0112 }
0113 
0114 inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
0115 { return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
0116 inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
0117 { return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
0118 inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
0119 { return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
0120 
0121 template <class T> inline T qFromLittleEndian(const uchar *src)
0122 {
0123     return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
0124 }
0125 
0126 #else
0127 template <typename T> inline T qFromLittleEndian(const uchar *src);
0128 template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
0129 {
0130     return 0
0131         | src[0]
0132         | src[1] * Q_UINT64_C(0x0000000000000100)
0133         | src[2] * Q_UINT64_C(0x0000000000010000)
0134         | src[3] * Q_UINT64_C(0x0000000001000000)
0135         | src[4] * Q_UINT64_C(0x0000000100000000)
0136         | src[5] * Q_UINT64_C(0x0000010000000000)
0137         | src[6] * Q_UINT64_C(0x0001000000000000)
0138         | src[7] * Q_UINT64_C(0x0100000000000000);
0139 }
0140 
0141 template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
0142 {
0143     return 0
0144         | src[0]
0145         | src[1] * quint32(0x00000100)
0146         | src[2] * quint32(0x00010000)
0147         | src[3] * quint32(0x01000000);
0148 }
0149 
0150 template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
0151 {
0152     return 0
0153         | src[0]
0154         | src[1] * 0x0100;
0155 }
0156 
0157 // signed specializations
0158 template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
0159 { return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
0160 
0161 template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
0162 { return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
0163 
0164 template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
0165 { return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
0166 #endif
0167 
0168 /* This function will read a big-endian (also known as network order) encoded value from \a src
0169  * and return the value in host-endian encoding.
0170  * There is no requirement that \a src must be aligned.
0171 */
0172 #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
0173 inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
0174 {
0175     return 0
0176         | src[7]
0177         | src[6] * Q_UINT64_C(0x0000000000000100)
0178         | src[5] * Q_UINT64_C(0x0000000000010000)
0179         | src[4] * Q_UINT64_C(0x0000000001000000)
0180         | src[3] * Q_UINT64_C(0x0000000100000000)
0181         | src[2] * Q_UINT64_C(0x0000010000000000)
0182         | src[1] * Q_UINT64_C(0x0001000000000000)
0183         | src[0] * Q_UINT64_C(0x0100000000000000);
0184 }
0185 
0186 inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
0187 {
0188     return 0
0189         | src[3]
0190         | src[2] * quint32(0x00000100)
0191         | src[1] * quint32(0x00010000)
0192         | src[0] * quint32(0x01000000);
0193 }
0194 
0195 inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
0196 {
0197     return 0
0198         | src[1]
0199         | src[0] * 0x0100;
0200 }
0201 
0202 
0203 inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
0204 { return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
0205 inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
0206 { return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
0207 inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
0208 { return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
0209 
0210 template <class T> inline T qFromBigEndian(const uchar *src)
0211 {
0212     return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
0213 }
0214 
0215 #else
0216 template <class T> inline T qFromBigEndian(const uchar *src);
0217 template<>
0218 inline quint64 qFromBigEndian<quint64>(const uchar *src)
0219 {
0220     return 0
0221         | src[7]
0222         | src[6] * Q_UINT64_C(0x0000000000000100)
0223         | src[5] * Q_UINT64_C(0x0000000000010000)
0224         | src[4] * Q_UINT64_C(0x0000000001000000)
0225         | src[3] * Q_UINT64_C(0x0000000100000000)
0226         | src[2] * Q_UINT64_C(0x0000010000000000)
0227         | src[1] * Q_UINT64_C(0x0001000000000000)
0228         | src[0] * Q_UINT64_C(0x0100000000000000);
0229 }
0230 
0231 template<>
0232 inline quint32 qFromBigEndian<quint32>(const uchar *src)
0233 {
0234     return 0
0235         | src[3]
0236         | src[2] * quint32(0x00000100)
0237         | src[1] * quint32(0x00010000)
0238         | src[0] * quint32(0x01000000);
0239 }
0240 
0241 template<>
0242 inline quint16 qFromBigEndian<quint16>(const uchar *src)
0243 {
0244     return 0
0245         | src[1]
0246         | src[0] * quint16(0x0100);
0247 }
0248 
0249 
0250 // signed specializations
0251 template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
0252 { return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
0253 
0254 template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
0255 { return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
0256 
0257 template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
0258 { return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
0259 #endif
0260 /*
0261  * T qbswap(T source).
0262  * Changes the byte order of a value from big endian to little endian or vice versa.
0263  * This function can be used if you are not concerned about alignment issues,
0264  * and it is therefore a bit more convenient and in most cases more efficient.
0265 */
0266 template <typename T> T qbswap(T source);
0267 template <> inline quint64 qbswap<quint64>(quint64 source)
0268 {
0269     return 0
0270         | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
0271         | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
0272         | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
0273         | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
0274         | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
0275         | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
0276         | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
0277         | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
0278 }
0279 
0280 template <> inline quint32 qbswap<quint32>(quint32 source)
0281 {
0282     return 0
0283         | ((source & 0x000000ff) << 24)
0284         | ((source & 0x0000ff00) << 8)
0285         | ((source & 0x00ff0000) >> 8)
0286         | ((source & 0xff000000) >> 24);
0287 }
0288 
0289 template <> inline quint16 qbswap<quint16>(quint16 source)
0290 {
0291     return 0
0292         | ((source & 0x00ff) << 8)
0293         | ((source & 0xff00) >> 8);
0294 }
0295 
0296 // signed specializations
0297 template <> inline qint64 qbswap<qint64>(qint64 source)
0298 {
0299     return qbswap<quint64>(quint64(source));
0300 }
0301 
0302 template <> inline qint32 qbswap<qint32>(qint32 source)
0303 {
0304     return qbswap<quint32>(quint32(source));
0305 }
0306 
0307 template <> inline qint16 qbswap<qint16>(qint16 source)
0308 {
0309     return qbswap<quint16>(quint16(source));
0310 }
0311 
0312 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
0313 
0314 template <typename T> inline T qToBigEndian(T source)
0315 { return source; }
0316 template <typename T> inline T qFromBigEndian(T source)
0317 { return source; }
0318 template <typename T> inline T qToLittleEndian(T source)
0319 { return qbswap<T>(source); }
0320 template <typename T> inline T qFromLittleEndian(T source)
0321 { return qbswap<T>(source); }
0322 template <typename T> inline void qToBigEndian(T src, uchar *dest)
0323 { qToUnaligned<T>(src, dest); }
0324 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
0325 { qbswap<T>(src, dest); }
0326 #else // Q_LITTLE_ENDIAN
0327 
0328 template <typename T> inline T qToBigEndian(T source)
0329 { return qbswap<T>(source); }
0330 template <typename T> inline T qFromBigEndian(T source)
0331 { return qbswap<T>(source); }
0332 template <typename T> inline T qToLittleEndian(T source)
0333 { return source; }
0334 template <typename T> inline T qFromLittleEndian(T source)
0335 { return source; }
0336 template <typename T> inline void qToBigEndian(T src, uchar *dest)
0337 { qbswap<T>(src, dest); }
0338 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
0339 { qToUnaligned<T>(src, dest); }
0340 
0341 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
0342 
0343 QT_END_NAMESPACE
0344 
0345 QT_END_HEADER
0346 
0347 #endif // QENDIAN_H