source: trunk/src/corelib/global/qendian.h@ 168

Last change on this file since 168 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QENDIAN_H
43#define QENDIAN_H
44
45#include <QtCore/qglobal.h>
46
47QT_BEGIN_HEADER
48
49QT_BEGIN_NAMESPACE
50
51QT_MODULE(Core)
52
53/*
54 * ENDIAN FUNCTIONS
55*/
56inline void qbswap_helper(const uchar *src, uchar *dest, int size)
57{
58 for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
59}
60
61/*
62 * qbswap(const T src, const uchar *dest);
63 * Changes the byte order of \a src from big endian to little endian or vice versa
64 * and stores the result in \a dest.
65 * There is no alignment requirements for \a dest.
66*/
67template <typename T> inline void qbswap(const T src, uchar *dest)
68{
69 qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
70}
71
72// Used to implement a type-safe and alignment-safe copy operation
73// If you want to avoid the memcopy, you must write specializations for this function
74template <typename T> inline void qToUnaligned(const T src, uchar *dest)
75{
76 qMemCopy(dest, &src, sizeof(T));
77}
78
79/* T qFromLittleEndian(const uchar *src)
80 * This function will read a little-endian encoded value from \a src
81 * and return the value in host-endian encoding.
82 * There is no requirement that \a src must be aligned.
83*/
84#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
85inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
86{
87 return 0
88 | src[0]
89 | src[1] * Q_UINT64_C(0x0000000000000100)
90 | src[2] * Q_UINT64_C(0x0000000000010000)
91 | src[3] * Q_UINT64_C(0x0000000001000000)
92 | src[4] * Q_UINT64_C(0x0000000100000000)
93 | src[5] * Q_UINT64_C(0x0000010000000000)
94 | src[6] * Q_UINT64_C(0x0001000000000000)
95 | src[7] * Q_UINT64_C(0x0100000000000000);
96}
97
98inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
99{
100 return 0
101 | src[0]
102 | src[1] * quint32(0x00000100)
103 | src[2] * quint32(0x00010000)
104 | src[3] * quint32(0x01000000);
105}
106
107inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
108{
109 return 0
110 | src[0]
111 | src[1] * 0x0100;
112}
113
114inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
115{ return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
116inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
117{ return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
118inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
119{ return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
120
121template <class T> inline T qFromLittleEndian(const uchar *src)
122{
123 return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
124}
125
126#else
127template <typename T> inline T qFromLittleEndian(const uchar *src);
128template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
129{
130 return 0
131 | src[0]
132 | src[1] * Q_UINT64_C(0x0000000000000100)
133 | src[2] * Q_UINT64_C(0x0000000000010000)
134 | src[3] * Q_UINT64_C(0x0000000001000000)
135 | src[4] * Q_UINT64_C(0x0000000100000000)
136 | src[5] * Q_UINT64_C(0x0000010000000000)
137 | src[6] * Q_UINT64_C(0x0001000000000000)
138 | src[7] * Q_UINT64_C(0x0100000000000000);
139}
140
141template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
142{
143 return 0
144 | src[0]
145 | src[1] * quint32(0x00000100)
146 | src[2] * quint32(0x00010000)
147 | src[3] * quint32(0x01000000);
148}
149
150template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
151{
152 return 0
153 | src[0]
154 | src[1] * 0x0100;
155}
156
157// signed specializations
158template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
159{ return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
160
161template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
162{ return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
163
164template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
165{ return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
166#endif
167
168/* This function will read a big-endian (also known as network order) encoded value from \a src
169 * and return the value in host-endian encoding.
170 * There is no requirement that \a src must be aligned.
171*/
172#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
173inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
174{
175 return 0
176 | src[7]
177 | src[6] * Q_UINT64_C(0x0000000000000100)
178 | src[5] * Q_UINT64_C(0x0000000000010000)
179 | src[4] * Q_UINT64_C(0x0000000001000000)
180 | src[3] * Q_UINT64_C(0x0000000100000000)
181 | src[2] * Q_UINT64_C(0x0000010000000000)
182 | src[1] * Q_UINT64_C(0x0001000000000000)
183 | src[0] * Q_UINT64_C(0x0100000000000000);
184}
185
186inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
187{
188 return 0
189 | src[3]
190 | src[2] * quint32(0x00000100)
191 | src[1] * quint32(0x00010000)
192 | src[0] * quint32(0x01000000);
193}
194
195inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
196{
197 return 0
198 | src[1]
199 | src[0] * 0x0100;
200}
201
202
203inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
204{ return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
205inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
206{ return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
207inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
208{ return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
209
210template <class T> inline T qFromBigEndian(const uchar *src)
211{
212 return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
213}
214
215#else
216template <class T> inline T qFromBigEndian(const uchar *src);
217template<>
218inline quint64 qFromBigEndian<quint64>(const uchar *src)
219{
220 return 0
221 | src[7]
222 | src[6] * Q_UINT64_C(0x0000000000000100)
223 | src[5] * Q_UINT64_C(0x0000000000010000)
224 | src[4] * Q_UINT64_C(0x0000000001000000)
225 | src[3] * Q_UINT64_C(0x0000000100000000)
226 | src[2] * Q_UINT64_C(0x0000010000000000)
227 | src[1] * Q_UINT64_C(0x0001000000000000)
228 | src[0] * Q_UINT64_C(0x0100000000000000);
229}
230
231template<>
232inline quint32 qFromBigEndian<quint32>(const uchar *src)
233{
234 return 0
235 | src[3]
236 | src[2] * quint32(0x00000100)
237 | src[1] * quint32(0x00010000)
238 | src[0] * quint32(0x01000000);
239}
240
241template<>
242inline quint16 qFromBigEndian<quint16>(const uchar *src)
243{
244 return 0
245 | src[1]
246 | src[0] * quint16(0x0100);
247}
248
249
250// signed specializations
251template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
252{ return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
253
254template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
255{ return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
256
257template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
258{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
259#endif
260/*
261 * T qbswap(T source).
262 * Changes the byte order of a value from big endian to little endian or vice versa.
263 * This function can be used if you are not concerned about alignment issues,
264 * and it is therefore a bit more convenient and in most cases more efficient.
265*/
266template <typename T> T qbswap(T source);
267template <> inline quint64 qbswap<quint64>(quint64 source)
268{
269 return 0
270 | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
271 | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
272 | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
273 | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
274 | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
275 | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
276 | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
277 | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
278}
279
280template <> inline quint32 qbswap<quint32>(quint32 source)
281{
282 return 0
283 | ((source & 0x000000ff) << 24)
284 | ((source & 0x0000ff00) << 8)
285 | ((source & 0x00ff0000) >> 8)
286 | ((source & 0xff000000) >> 24);
287}
288
289template <> inline quint16 qbswap<quint16>(quint16 source)
290{
291 return 0
292 | ((source & 0x00ff) << 8)
293 | ((source & 0xff00) >> 8);
294}
295
296// signed specializations
297template <> inline qint64 qbswap<qint64>(qint64 source)
298{
299 return qbswap<quint64>(quint64(source));
300}
301
302template <> inline qint32 qbswap<qint32>(qint32 source)
303{
304 return qbswap<quint32>(quint32(source));
305}
306
307template <> inline qint16 qbswap<qint16>(qint16 source)
308{
309 return qbswap<quint16>(quint16(source));
310}
311
312#if Q_BYTE_ORDER == Q_BIG_ENDIAN
313
314template <typename T> inline T qToBigEndian(T source)
315{ return source; }
316template <typename T> inline T qFromBigEndian(T source)
317{ return source; }
318template <typename T> inline T qToLittleEndian(T source)
319{ return qbswap<T>(source); }
320template <typename T> inline T qFromLittleEndian(T source)
321{ return qbswap<T>(source); }
322template <typename T> inline void qToBigEndian(T src, uchar *dest)
323{ qToUnaligned<T>(src, dest); }
324template <typename T> inline void qToLittleEndian(T src, uchar *dest)
325{ qbswap<T>(src, dest); }
326#else // Q_LITTLE_ENDIAN
327
328template <typename T> inline T qToBigEndian(T source)
329{ return qbswap<T>(source); }
330template <typename T> inline T qFromBigEndian(T source)
331{ return qbswap<T>(source); }
332template <typename T> inline T qToLittleEndian(T source)
333{ return source; }
334template <typename T> inline T qFromLittleEndian(T source)
335{ return source; }
336template <typename T> inline void qToBigEndian(T src, uchar *dest)
337{ qbswap<T>(src, dest); }
338template <typename T> inline void qToLittleEndian(T src, uchar *dest)
339{ qToUnaligned<T>(src, dest); }
340
341#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
342
343QT_END_NAMESPACE
344
345QT_END_HEADER
346
347#endif // QENDIAN_H
Note: See TracBrowser for help on using the repository browser.