Qt 4.8
qendian.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
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.
16 **
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.
24 **
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.
28 **
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.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QENDIAN_H
43 #define QENDIAN_H
44 
45 #include <QtCore/qglobal.h>
46 
47 // include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
48 #include <stdlib.h>
49 
50 #ifdef __GLIBC__
51 #include <byteswap.h>
52 #endif
53 
55 
57 
58 QT_MODULE(Core)
59 
60 /*
61  * ENDIAN FUNCTIONS
62 */
63 inline void qbswap_helper(const uchar *src, uchar *dest, int size)
64 {
65  for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
66 }
67 
68 /*
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.
73 */
74 template <typename T> inline void qbswap(const T src, uchar *dest)
75 {
76  qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
77 }
78 
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)
82 {
83  qMemCopy(dest, &src, sizeof(T));
84 }
85 
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.
90 */
91 #if defined Q_CC_SUN
92 inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
93 {
94  return 0
95  | src[0]
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);
103 }
104 
105 inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
106 {
107  return 0
108  | src[0]
109  | src[1] * quint32(0x00000100)
110  | src[2] * quint32(0x00010000)
111  | src[3] * quint32(0x01000000);
112 }
113 
114 inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
115 {
116  return 0
117  | src[0]
118  | src[1] * 0x0100;
119 }
120 
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))); }
127 
128 template <class T> inline T qFromLittleEndian(const uchar *src)
129 {
130  return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
131 }
132 
133 #else
134 template <typename T> inline T qFromLittleEndian(const uchar *src);
135 template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
136 {
137  return 0
138  | src[0]
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);
146 }
147 
148 template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
149 {
150  return 0
151  | src[0]
152  | src[1] * quint32(0x00000100)
153  | src[2] * quint32(0x00010000)
154  | src[3] * quint32(0x01000000);
155 }
156 
157 template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
158 {
159  return quint16(0
160  | src[0]
161  | src[1] * 0x0100);
162 }
163 
164 // signed specializations
165 template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
166 { return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
167 
168 template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
169 { return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
170 
171 template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
172 { return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
173 #endif
174 
175 /* This function will read a big-endian (also known as network order) encoded value from \a src
176  * and return the value in host-endian encoding.
177  * There is no requirement that \a src must be aligned.
178 */
179 #if defined Q_CC_SUN
180 inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
181 {
182  return 0
183  | src[7]
184  | src[6] * Q_UINT64_C(0x0000000000000100)
185  | src[5] * Q_UINT64_C(0x0000000000010000)
186  | src[4] * Q_UINT64_C(0x0000000001000000)
187  | src[3] * Q_UINT64_C(0x0000000100000000)
188  | src[2] * Q_UINT64_C(0x0000010000000000)
189  | src[1] * Q_UINT64_C(0x0001000000000000)
190  | src[0] * Q_UINT64_C(0x0100000000000000);
191 }
192 
193 inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
194 {
195  return 0
196  | src[3]
197  | src[2] * quint32(0x00000100)
198  | src[1] * quint32(0x00010000)
199  | src[0] * quint32(0x01000000);
200 }
201 
202 inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
203 {
204  return 0
205  | src[1]
206  | src[0] * 0x0100;
207 }
208 
209 
210 inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
211 { return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
212 inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
213 { return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
214 inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
215 { return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
216 
217 template <class T> inline T qFromBigEndian(const uchar *src)
218 {
219  return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
220 }
221 
222 #else
223 template <class T> inline T qFromBigEndian(const uchar *src);
224 template<>
226 {
227  return 0
228  | src[7]
229  | src[6] * Q_UINT64_C(0x0000000000000100)
230  | src[5] * Q_UINT64_C(0x0000000000010000)
231  | src[4] * Q_UINT64_C(0x0000000001000000)
232  | src[3] * Q_UINT64_C(0x0000000100000000)
233  | src[2] * Q_UINT64_C(0x0000010000000000)
234  | src[1] * Q_UINT64_C(0x0001000000000000)
235  | src[0] * Q_UINT64_C(0x0100000000000000);
236 }
237 
238 template<>
240 {
241  return 0
242  | src[3]
243  | src[2] * quint32(0x00000100)
244  | src[1] * quint32(0x00010000)
245  | src[0] * quint32(0x01000000);
246 }
247 
248 template<>
250 {
251  return quint16( 0
252  | src[1]
253  | src[0] * quint16(0x0100));
254 }
255 
256 
257 // signed specializations
258 template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
259 { return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
260 
261 template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
262 { return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
263 
264 template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
265 { return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
266 #endif
267 /*
268  * T qbswap(T source).
269  * Changes the byte order of a value from big endian to little endian or vice versa.
270  * This function can be used if you are not concerned about alignment issues,
271  * and it is therefore a bit more convenient and in most cases more efficient.
272 */
273 template <typename T> T qbswap(T source);
274 
275 #ifdef __GLIBC__
276 template <> inline quint64 qbswap<quint64>(quint64 source)
277 {
278  return bswap_64(source);
279 }
280 template <> inline quint32 qbswap<quint32>(quint32 source)
281 {
282  return bswap_32(source);
283 }
284 template <> inline quint16 qbswap<quint16>(quint16 source)
285 {
286  return bswap_16(source);
287 }
288 #else
289 template <> inline quint64 qbswap<quint64>(quint64 source)
290 {
291  return 0
292  | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
293  | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
294  | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
295  | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
296  | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
297  | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
298  | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
299  | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
300 }
301 
302 template <> inline quint32 qbswap<quint32>(quint32 source)
303 {
304  return 0
305  | ((source & 0x000000ff) << 24)
306  | ((source & 0x0000ff00) << 8)
307  | ((source & 0x00ff0000) >> 8)
308  | ((source & 0xff000000) >> 24);
309 }
310 
311 template <> inline quint16 qbswap<quint16>(quint16 source)
312 {
313  return quint16( 0
314  | ((source & 0x00ff) << 8)
315  | ((source & 0xff00) >> 8) );
316 }
317 #endif // __GLIBC__
318 
319 // signed specializations
320 template <> inline qint64 qbswap<qint64>(qint64 source)
321 {
322  return qbswap<quint64>(quint64(source));
323 }
324 
325 template <> inline qint32 qbswap<qint32>(qint32 source)
326 {
327  return qbswap<quint32>(quint32(source));
328 }
329 
330 template <> inline qint16 qbswap<qint16>(qint16 source)
331 {
332  return qbswap<quint16>(quint16(source));
333 }
334 
335 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
336 
337 template <typename T> inline T qToBigEndian(T source)
338 { return source; }
339 template <typename T> inline T qFromBigEndian(T source)
340 { return source; }
341 template <typename T> inline T qToLittleEndian(T source)
342 { return qbswap<T>(source); }
343 template <typename T> inline T qFromLittleEndian(T source)
344 { return qbswap<T>(source); }
345 template <typename T> inline void qToBigEndian(T src, uchar *dest)
346 { qToUnaligned<T>(src, dest); }
347 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
348 { qbswap<T>(src, dest); }
349 #else // Q_LITTLE_ENDIAN
350 
351 template <typename T> inline T qToBigEndian(T source)
352 { return qbswap<T>(source); }
353 template <typename T> inline T qFromBigEndian(T source)
354 { return qbswap<T>(source); }
355 template <typename T> inline T qToLittleEndian(T source)
356 { return source; }
357 template <typename T> inline T qFromLittleEndian(T source)
358 { return source; }
359 template <typename T> inline void qToBigEndian(T src, uchar *dest)
360 { qbswap<T>(src, dest); }
361 template <typename T> inline void qToLittleEndian(T src, uchar *dest)
362 { qToUnaligned<T>(src, dest); }
363 
364 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
365 
366 template <> inline quint8 qbswap<quint8>(quint8 source)
367 {
368  return source;
369 }
370 
372 
374 
375 #endif // QENDIAN_H
quint64 qFromLittleEndian< quint64 >(const uchar *src)
Definition: qendian.h:135
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
quint64 qbswap< quint64 >(quint64 source)
Definition: qendian.h:289
int qint32
Definition: qglobal.h:937
#define QT_MODULE(x)
Definition: qglobal.h:2783
void qbswap(const T src, uchar *dest)
Definition: qendian.h:74
#define QT_BEGIN_HEADER
Definition: qglobal.h:136
quint16 qFromLittleEndian< quint16 >(const uchar *src)
Definition: qendian.h:157
T qFromBigEndian(const uchar *src)
qint16 qbswap< qint16 >(qint16 source)
Definition: qendian.h:330
unsigned char quint8
Definition: qglobal.h:934
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
qint64 qFromLittleEndian< qint64 >(const uchar *src)
Definition: qendian.h:165
qint64 qbswap< qint64 >(qint64 source)
Definition: qendian.h:320
unsigned char uchar
Definition: qglobal.h:994
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void qToUnaligned(const T src, uchar *dest)
Definition: qendian.h:81
unsigned __int64 quint64
Definition: qglobal.h:943
short qint16
Definition: qglobal.h:935
T qToBigEndian(T source)
Definition: qendian.h:337
unsigned short quint16
Definition: qglobal.h:936
quint32 qFromLittleEndian< quint32 >(const uchar *src)
Definition: qendian.h:148
qint16 qFromBigEndian< qint16 >(const uchar *src)
Definition: qendian.h:264
__int64 qint64
Definition: qglobal.h:942
qint32 qFromLittleEndian< qint32 >(const uchar *src)
Definition: qendian.h:168
quint8 qbswap< quint8 >(quint8 source)
Definition: qendian.h:366
qint32 qFromBigEndian< qint32 >(const uchar *src)
Definition: qendian.h:261
quint16 qFromBigEndian< quint16 >(const uchar *src)
Definition: qendian.h:249
void * qMemCopy(void *dest, const void *src, size_t n)
Definition: qglobal.cpp:2508
quint64 qFromBigEndian< quint64 >(const uchar *src)
Definition: qendian.h:225
qint64 qFromBigEndian< qint64 >(const uchar *src)
Definition: qendian.h:258
qint32 qbswap< qint32 >(qint32 source)
Definition: qendian.h:325
unsigned int quint32
Definition: qglobal.h:938
void qbswap_helper(const uchar *src, uchar *dest, int size)
Definition: qendian.h:63
qint16 qFromLittleEndian< qint16 >(const uchar *src)
Definition: qendian.h:171
quint32 qbswap< quint32 >(quint32 source)
Definition: qendian.h:302
#define Q_UINT64_C(c)
Definition: qglobal.h:941
quint16 qbswap< quint16 >(quint16 source)
Definition: qendian.h:311
#define QT_END_HEADER
Definition: qglobal.h:137
T qToLittleEndian(T source)
Definition: qendian.h:341
T qFromLittleEndian(const uchar *src)