1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtCore module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
45
#include <QtCore/qglobal.h>
47
// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
63
inline void qbswap_helper(const uchar *src, uchar *dest, int size)
65
for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
69
* qbswap(const T src, const uchar *dest);
70
* Changes the byte order of \a src from big endian to little endian or vice versa
71
* and stores the result in \a dest.
72
* There is no alignment requirements for \a dest.
74
template <typename T> inline void qbswap(const T src, uchar *dest)
76
qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
79
// Used to implement a type-safe and alignment-safe copy operation
80
// If you want to avoid the memcopy, you must write specializations for this function
81
template <typename T> inline void qToUnaligned(const T src, uchar *dest)
83
memcpy(dest, &src, sizeof(T));
86
/* T qFromLittleEndian(const uchar *src)
87
* This function will read a little-endian encoded value from \a src
88
* and return the value in host-endian encoding.
89
* There is no requirement that \a src must be aligned.
92
inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
96
| src[1] * Q_UINT64_C(0x0000000000000100)
97
| src[2] * Q_UINT64_C(0x0000000000010000)
98
| src[3] * Q_UINT64_C(0x0000000001000000)
99
| src[4] * Q_UINT64_C(0x0000000100000000)
100
| src[5] * Q_UINT64_C(0x0000010000000000)
101
| src[6] * Q_UINT64_C(0x0001000000000000)
102
| src[7] * Q_UINT64_C(0x0100000000000000);
105
inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
109
| src[1] * quint32(0x00000100)
110
| src[2] * quint32(0x00010000)
111
| src[3] * quint32(0x01000000);
114
inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
121
inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
122
{ return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
123
inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
124
{ return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
125
inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
126
{ return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
128
template <class T> inline T qFromLittleEndian(const uchar *src)
130
return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
134
template <typename T> inline T qFromLittleEndian(const uchar *src);
135
template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
139
| src[1] * Q_UINT64_C(0x0000000000000100)
140
| src[2] * Q_UINT64_C(0x0000000000010000)
141
| src[3] * Q_UINT64_C(0x0000000001000000)
142
| src[4] * Q_UINT64_C(0x0000000100000000)
143
| src[5] * Q_UINT64_C(0x0000010000000000)
144
| src[6] * Q_UINT64_C(0x0001000000000000)
145
| src[7] * Q_UINT64_C(0x0100000000000000);
148
template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
152
| src[1] * quint32(0x00000100)
153
| src[2] * quint32(0x00010000)
154
| src[3] * quint32(0x01000000);
157
template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
164
// signed specializations
165
template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
166
{ return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
168
template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
169
{ return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
171
template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
172
{ return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
175
template <> inline quint8 qFromLittleEndian<quint8>(const uchar *src)
176
{ return static_cast<quint8>(src[0]); }
177
template <> inline qint8 qFromLittleEndian<qint8>(const uchar *src)
178
{ return static_cast<qint8>(src[0]); }
180
/* This function will read a big-endian (also known as network order) encoded value from \a src
181
* and return the value in host-endian encoding.
182
* There is no requirement that \a src must be aligned.
185
inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
189
| src[6] * Q_UINT64_C(0x0000000000000100)
190
| src[5] * Q_UINT64_C(0x0000000000010000)
191
| src[4] * Q_UINT64_C(0x0000000001000000)
192
| src[3] * Q_UINT64_C(0x0000000100000000)
193
| src[2] * Q_UINT64_C(0x0000010000000000)
194
| src[1] * Q_UINT64_C(0x0001000000000000)
195
| src[0] * Q_UINT64_C(0x0100000000000000);
198
inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
202
| src[2] * quint32(0x00000100)
203
| src[1] * quint32(0x00010000)
204
| src[0] * quint32(0x01000000);
207
inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
215
inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
216
{ return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
217
inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
218
{ return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
219
inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
220
{ return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
222
template <class T> inline T qFromBigEndian(const uchar *src)
224
return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
228
template <class T> inline T qFromBigEndian(const uchar *src);
230
inline quint64 qFromBigEndian<quint64>(const uchar *src)
234
| src[6] * Q_UINT64_C(0x0000000000000100)
235
| src[5] * Q_UINT64_C(0x0000000000010000)
236
| src[4] * Q_UINT64_C(0x0000000001000000)
237
| src[3] * Q_UINT64_C(0x0000000100000000)
238
| src[2] * Q_UINT64_C(0x0000010000000000)
239
| src[1] * Q_UINT64_C(0x0001000000000000)
240
| src[0] * Q_UINT64_C(0x0100000000000000);
244
inline quint32 qFromBigEndian<quint32>(const uchar *src)
248
| src[2] * quint32(0x00000100)
249
| src[1] * quint32(0x00010000)
250
| src[0] * quint32(0x01000000);
254
inline quint16 qFromBigEndian<quint16>(const uchar *src)
258
| src[0] * quint16(0x0100));
262
// signed specializations
263
template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
264
{ return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
266
template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
267
{ return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
269
template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
270
{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
273
template <> inline quint8 qFromBigEndian<quint8>(const uchar *src)
274
{ return static_cast<quint8>(src[0]); }
275
template <> inline qint8 qFromBigEndian<qint8>(const uchar *src)
276
{ return static_cast<qint8>(src[0]); }
279
* T qbswap(T source).
280
* Changes the byte order of a value from big endian to little endian or vice versa.
281
* This function can be used if you are not concerned about alignment issues,
282
* and it is therefore a bit more convenient and in most cases more efficient.
284
template <typename T> T qbswap(T source);
287
template <> inline quint64 qbswap<quint64>(quint64 source)
289
return bswap_64(source);
291
template <> inline quint32 qbswap<quint32>(quint32 source)
293
return bswap_32(source);
295
template <> inline quint16 qbswap<quint16>(quint16 source)
297
return bswap_16(source);
300
template <> inline quint64 qbswap<quint64>(quint64 source)
303
| ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
304
| ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
305
| ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
306
| ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
307
| ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
308
| ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
309
| ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
310
| ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
313
template <> inline quint32 qbswap<quint32>(quint32 source)
316
| ((source & 0x000000ff) << 24)
317
| ((source & 0x0000ff00) << 8)
318
| ((source & 0x00ff0000) >> 8)
319
| ((source & 0xff000000) >> 24);
322
template <> inline quint16 qbswap<quint16>(quint16 source)
325
| ((source & 0x00ff) << 8)
326
| ((source & 0xff00) >> 8) );
330
// signed specializations
331
template <> inline qint64 qbswap<qint64>(qint64 source)
333
return qbswap<quint64>(quint64(source));
336
template <> inline qint32 qbswap<qint32>(qint32 source)
338
return qbswap<quint32>(quint32(source));
341
template <> inline qint16 qbswap<qint16>(qint16 source)
343
return qbswap<quint16>(quint16(source));
346
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
348
template <typename T> inline T qToBigEndian(T source)
350
template <typename T> inline T qFromBigEndian(T source)
352
template <typename T> inline T qToLittleEndian(T source)
353
{ return qbswap<T>(source); }
354
template <typename T> inline T qFromLittleEndian(T source)
355
{ return qbswap<T>(source); }
356
template <typename T> inline void qToBigEndian(T src, uchar *dest)
357
{ qToUnaligned<T>(src, dest); }
358
template <typename T> inline void qToLittleEndian(T src, uchar *dest)
359
{ qbswap<T>(src, dest); }
360
#else // Q_LITTLE_ENDIAN
362
template <typename T> inline T qToBigEndian(T source)
363
{ return qbswap<T>(source); }
364
template <typename T> inline T qFromBigEndian(T source)
365
{ return qbswap<T>(source); }
366
template <typename T> inline T qToLittleEndian(T source)
368
template <typename T> inline T qFromLittleEndian(T source)
370
template <typename T> inline void qToBigEndian(T src, uchar *dest)
371
{ qbswap<T>(src, dest); }
372
template <typename T> inline void qToLittleEndian(T src, uchar *dest)
373
{ qToUnaligned<T>(src, dest); }
375
#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
377
template <> inline quint8 qbswap<quint8>(quint8 source)
382
template <> inline qint8 qbswap<qint8>(qint8 source)