- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

# qendian.h

Go to the documentation of this file.

    00001 /****************************************************************************
    00002 **
    00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
    00004 ** All rights reserved.
    00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
    00006 **
    00007 ** This file is part of the QtCore module of the Qt Toolkit.
    00008 **
    00009 ** $QT_BEGIN_LICENSE:LGPL$
    00010 ** Commercial Usage
    00011 ** Licensees holding valid Qt Commercial licenses may use this file in
    00012 ** accordance with the Qt Commercial License Agreement provided with the
    00013 ** Software or, alternatively, in accordance with the terms contained in
    00014 ** a written agreement between you and Nokia.
    00015 **
    00016 ** GNU Lesser General Public License Usage
    00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
    00018 ** General Public License version 2.1 as published by the Free Software
    00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
    00020 ** packaging of this file.  Please review the following information to
    00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
    00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    00023 **
    00024 ** In addition, as a special exception, Nokia gives you certain additional
    00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
    00027 **
    00028 ** GNU General Public License Usage
    00029 ** Alternatively, this file may be used under the terms of the GNU
    00030 ** General Public License version 3.0 as published by the Free Software
    00031 ** Foundation and appearing in the file LICENSE.GPL included in the
    00032 ** packaging of this file.  Please review the following information to
    00033 ** ensure the GNU General Public License version 3.0 requirements will be
    00034 ** met: http://www.gnu.org/copyleft/gpl.html.
    00035 **
    00036 ** If you have questions regarding the use of this file, please contact
    00037 ** Nokia at qt-info@nokia.com.
    00038 ** $QT_END_LICENSE$
    00039 **
    00040 ****************************************************************************/
    00041
    00042 #ifndef QENDIAN_H
    00043 #define QENDIAN_H
    00044
    00045 #include <QtCore/qglobal.h>
    00046
    00047 #ifdef Q_OS_LINUX
    00048 # include <features.h>
    00049 #endif
    00050
    00051 #ifdef __GLIBC__
    00052 #include <byteswap.h>
    00053 #endif
    00054
    00055 QT_BEGIN_HEADER
    00056
    00057 QT_BEGIN_NAMESPACE
    00058
    00059 QT_MODULE(Core)
    00060
    00061 /*
    00062  * ENDIAN FUNCTIONS
    00063 */
    00064 inline void qbswap_helper(const uchar *src, uchar *dest, int size)
    00065 {
    00066     for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
    00067 }
    00068
    00069 /*
    00070  * qbswap(const T src, const uchar *dest);
    00071  * Changes the byte order of \a src from big endian to little endian or vice versa
    00072  * and stores the result in \a dest.
    00073  * There is no alignment requirements for \a dest.
    00074 */
    00075 template <typename T> inline void qbswap(const T src, uchar *dest)
    00076 {
    00077     qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
    00078 }
    00079
    00080 // Used to implement a type-safe and alignment-safe copy operation
    00081 // If you want to avoid the memcopy, you must write specializations for this function
    00082 template <typename T> inline void qToUnaligned(const T src, uchar *dest)
    00083 {
    00084     qMemCopy(dest, &src, sizeof(T));
    00085 }
    00086
    00087 /* T qFromLittleEndian(const uchar *src)
    00088  * This function will read a little-endian encoded value from \a src
    00089  * and return the value in host-endian encoding.
    00090  * There is no requirement that \a src must be aligned.
    00091 */
    00092 #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
    00093 inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
    00094 {
    00095     return 0
    00096         | src[0]
    00097         | src[1] * Q_UINT64_C(0x0000000000000100)
    00098         | src[2] * Q_UINT64_C(0x0000000000010000)
    00099         | src[3] * Q_UINT64_C(0x0000000001000000)
    00100         | src[4] * Q_UINT64_C(0x0000000100000000)
    00101         | src[5] * Q_UINT64_C(0x0000010000000000)
    00102         | src[6] * Q_UINT64_C(0x0001000000000000)
    00103         | src[7] * Q_UINT64_C(0x0100000000000000);
    00104 }
    00105
    00106 inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
    00107 {
    00108     return 0
    00109         | src[0]
    00110         | src[1] * quint32(0x00000100)
    00111         | src[2] * quint32(0x00010000)
    00112         | src[3] * quint32(0x01000000);
    00113 }
    00114
    00115 inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
    00116 {
    00117     return 0
    00118         | src[0]
    00119         | src[1] * 0x0100;
    00120 }
    00121
    00122 inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
    00123 { return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
    00124 inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
    00125 { return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
    00126 inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
    00127 { return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
    00128
    00129 template <class T> inline T qFromLittleEndian(const uchar *src)
    00130 {
    00131     return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
    00132 }
    00133
    00134 #else
    00135 template <typename T> inline T qFromLittleEndian(const uchar *src);
    00136 template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
    00137 {
    00138     return 0
    00139         | src[0]
    00140         | src[1] * Q_UINT64_C(0x0000000000000100)
    00141         | src[2] * Q_UINT64_C(0x0000000000010000)
    00142         | src[3] * Q_UINT64_C(0x0000000001000000)
    00143         | src[4] * Q_UINT64_C(0x0000000100000000)
    00144         | src[5] * Q_UINT64_C(0x0000010000000000)
    00145         | src[6] * Q_UINT64_C(0x0001000000000000)
    00146         | src[7] * Q_UINT64_C(0x0100000000000000);
    00147 }
    00148
    00149 template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
    00150 {
    00151     return 0
    00152         | src[0]
    00153         | src[1] * quint32(0x00000100)
    00154         | src[2] * quint32(0x00010000)
    00155         | src[3] * quint32(0x01000000);
    00156 }
    00157
    00158 template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
    00159 {
    00160     return quint16(0
    00161                    | src[0]
    00162                    | src[1] * 0x0100);
    00163 }
    00164
    00165 // signed specializations
    00166 template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
    00167 { return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
    00168
    00169 template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
    00170 { return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
    00171
    00172 template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
    00173 { return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
    00174 #endif
    00175
    00176 /* This function will read a big-endian (also known as network order) encoded value from \a src
    00177  * and return the value in host-endian encoding.
    00178  * There is no requirement that \a src must be aligned.
    00179 */
    00180 #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
    00181 inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
    00182 {
    00183     return 0
    00184         | src[7]
    00185         | src[6] * Q_UINT64_C(0x0000000000000100)
    00186         | src[5] * Q_UINT64_C(0x0000000000010000)
    00187         | src[4] * Q_UINT64_C(0x0000000001000000)
    00188         | src[3] * Q_UINT64_C(0x0000000100000000)
    00189         | src[2] * Q_UINT64_C(0x0000010000000000)
    00190         | src[1] * Q_UINT64_C(0x0001000000000000)
    00191         | src[0] * Q_UINT64_C(0x0100000000000000);
    00192 }
    00193
    00194 inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
    00195 {
    00196     return 0
    00197         | src[3]
    00198         | src[2] * quint32(0x00000100)
    00199         | src[1] * quint32(0x00010000)
    00200         | src[0] * quint32(0x01000000);
    00201 }
    00202
    00203 inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
    00204 {
    00205     return 0
    00206         | src[1]
    00207         | src[0] * 0x0100;
    00208 }
    00209
    00210
    00211 inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
    00212 { return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
    00213 inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
    00214 { return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
    00215 inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
    00216 { return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
    00217
    00218 template <class T> inline T qFromBigEndian(const uchar *src)
    00219 {
    00220     return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
    00221 }
    00222
    00223 #else
    00224 template <class T> inline T qFromBigEndian(const uchar *src);
    00225 template<>
    00226 inline quint64 qFromBigEndian<quint64>(const uchar *src)
    00227 {
    00228     return 0
    00229         | src[7]
    00230         | src[6] * Q_UINT64_C(0x0000000000000100)
    00231         | src[5] * Q_UINT64_C(0x0000000000010000)
    00232         | src[4] * Q_UINT64_C(0x0000000001000000)
    00233         | src[3] * Q_UINT64_C(0x0000000100000000)
    00234         | src[2] * Q_UINT64_C(0x0000010000000000)
    00235         | src[1] * Q_UINT64_C(0x0001000000000000)
    00236         | src[0] * Q_UINT64_C(0x0100000000000000);
    00237 }
    00238
    00239 template<>
    00240 inline quint32 qFromBigEndian<quint32>(const uchar *src)
    00241 {
    00242     return 0
    00243         | src[3]
    00244         | src[2] * quint32(0x00000100)
    00245         | src[1] * quint32(0x00010000)
    00246         | src[0] * quint32(0x01000000);
    00247 }
    00248
    00249 template<>
    00250 inline quint16 qFromBigEndian<quint16>(const uchar *src)
    00251 {
    00252     return quint16( 0
    00253                     | src[1]
    00254                     | src[0] * quint16(0x0100));
    00255 }
    00256
    00257
    00258 // signed specializations
    00259 template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
    00260 { return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
    00261
    00262 template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
    00263 { return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
    00264
    00265 template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
    00266 { return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
    00267 #endif
    00268 /*
    00269  * T qbswap(T source).
    00270  * Changes the byte order of a value from big endian to little endian or vice versa.
    00271  * This function can be used if you are not concerned about alignment issues,
    00272  * and it is therefore a bit more convenient and in most cases more efficient.
    00273 */
    00274 template <typename T> T qbswap(T source);
    00275
    00276 #ifdef __GLIBC__
    00277 template <> inline quint64 qbswap<quint64>(quint64 source)
    00278 {
    00279     return bswap_64(source);
    00280 }
    00281 template <> inline quint32 qbswap<quint32>(quint32 source)
    00282 {
    00283     return bswap_32(source);
    00284 }
    00285 template <> inline quint16 qbswap<quint16>(quint16 source)
    00286 {
    00287     return bswap_16(source);
    00288 }
    00289 #else
    00290 template <> inline quint64 qbswap<quint64>(quint64 source)
    00291 {
    00292     return 0
    00293         | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
    00294         | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
    00295         | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
    00296         | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
    00297         | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
    00298         | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
    00299         | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
    00300         | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
    00301 }
    00302
    00303 template <> inline quint32 qbswap<quint32>(quint32 source)
    00304 {
    00305     return 0
    00306         | ((source & 0x000000ff) << 24)
    00307         | ((source & 0x0000ff00) << 8)
    00308         | ((source & 0x00ff0000) >> 8)
    00309         | ((source & 0xff000000) >> 24);
    00310 }
    00311
    00312 template <> inline quint16 qbswap<quint16>(quint16 source)
    00313 {
    00314     return quint16( 0
    00315                     | ((source & 0x00ff) << 8)
    00316                     | ((source & 0xff00) >> 8) );
    00317 }
    00318 #endif // __GLIBC__
    00319
    00320 // signed specializations
    00321 template <> inline qint64 qbswap<qint64>(qint64 source)
    00322 {
    00323     return qbswap<quint64>(quint64(source));
    00324 }
    00325
    00326 template <> inline qint32 qbswap<qint32>(qint32 source)
    00327 {
    00328     return qbswap<quint32>(quint32(source));
    00329 }
    00330
    00331 template <> inline qint16 qbswap<qint16>(qint16 source)
    00332 {
    00333     return qbswap<quint16>(quint16(source));
    00334 }
    00335
    00336 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
    00337
    00338 template <typename T> inline T qToBigEndian(T source)
    00339 { return source; }
    00340 template <typename T> inline T qFromBigEndian(T source)
    00341 { return source; }
    00342 template <typename T> inline T qToLittleEndian(T source)
    00343 { return qbswap<T>(source); }
    00344 template <typename T> inline T qFromLittleEndian(T source)
    00345 { return qbswap<T>(source); }
    00346 template <typename T> inline void qToBigEndian(T src, uchar *dest)
    00347 { qToUnaligned<T>(src, dest); }
    00348 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
    00349 { qbswap<T>(src, dest); }
    00350 #else // Q_LITTLE_ENDIAN
    00351
    00352 template <typename T> inline T qToBigEndian(T source)
    00353 { return qbswap<T>(source); }
    00354 template <typename T> inline T qFromBigEndian(T source)
    00355 { return qbswap<T>(source); }
    00356 template <typename T> inline T qToLittleEndian(T source)
    00357 { return source; }
    00358 template <typename T> inline T qFromLittleEndian(T source)
    00359 { return source; }
    00360 template <typename T> inline void qToBigEndian(T src, uchar *dest)
    00361 { qbswap<T>(src, dest); }
    00362 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
    00363 { qToUnaligned<T>(src, dest); }
    00364
    00365 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
    00366
    00367 QT_END_NAMESPACE
    00368
    00369 QT_END_HEADER
    00370
    00371 #endif // QENDIAN_H