~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/corelib/global/qendian.h

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 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
#include <string.h>
 
50
 
 
51
#ifdef __GLIBC__
 
52
#include <byteswap.h>
 
53
#endif
 
54
 
 
55
QT_BEGIN_HEADER
 
56
 
 
57
QT_BEGIN_NAMESPACE
 
58
 
 
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
    memcpy(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
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]); }
 
179
 
 
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.
 
183
*/
 
184
#if defined Q_CC_SUN
 
185
inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
 
186
{
 
187
    return 0
 
188
        | src[7]
 
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);
 
196
}
 
197
 
 
198
inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
 
199
{
 
200
    return 0
 
201
        | src[3]
 
202
        | src[2] * quint32(0x00000100)
 
203
        | src[1] * quint32(0x00010000)
 
204
        | src[0] * quint32(0x01000000);
 
205
}
 
206
 
 
207
inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
 
208
{
 
209
    return 0
 
210
        | src[1]
 
211
        | src[0] * 0x0100;
 
212
}
 
213
 
 
214
 
 
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))); }
 
221
 
 
222
template <class T> inline T qFromBigEndian(const uchar *src)
 
223
{
 
224
    return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
 
225
}
 
226
 
 
227
#else
 
228
template <class T> inline T qFromBigEndian(const uchar *src);
 
229
template<>
 
230
inline quint64 qFromBigEndian<quint64>(const uchar *src)
 
231
{
 
232
    return 0
 
233
        | src[7]
 
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);
 
241
}
 
242
 
 
243
template<>
 
244
inline quint32 qFromBigEndian<quint32>(const uchar *src)
 
245
{
 
246
    return 0
 
247
        | src[3]
 
248
        | src[2] * quint32(0x00000100)
 
249
        | src[1] * quint32(0x00010000)
 
250
        | src[0] * quint32(0x01000000);
 
251
}
 
252
 
 
253
template<>
 
254
inline quint16 qFromBigEndian<quint16>(const uchar *src)
 
255
{
 
256
    return quint16( 0
 
257
                    | src[1]
 
258
                    | src[0] * quint16(0x0100));
 
259
}
 
260
 
 
261
 
 
262
// signed specializations
 
263
template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
 
264
{ return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
 
265
 
 
266
template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
 
267
{ return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
 
268
 
 
269
template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
 
270
{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
 
271
#endif
 
272
 
 
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]); }
 
277
 
 
278
/*
 
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.
 
283
*/
 
284
template <typename T> T qbswap(T source);
 
285
 
 
286
#ifdef __GLIBC__
 
287
template <> inline quint64 qbswap<quint64>(quint64 source)
 
288
{
 
289
    return bswap_64(source);
 
290
}
 
291
template <> inline quint32 qbswap<quint32>(quint32 source)
 
292
{
 
293
    return bswap_32(source);
 
294
}
 
295
template <> inline quint16 qbswap<quint16>(quint16 source)
 
296
{
 
297
    return bswap_16(source);
 
298
}
 
299
#else
 
300
template <> inline quint64 qbswap<quint64>(quint64 source)
 
301
{
 
302
    return 0
 
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);
 
311
}
 
312
 
 
313
template <> inline quint32 qbswap<quint32>(quint32 source)
 
314
{
 
315
    return 0
 
316
        | ((source & 0x000000ff) << 24)
 
317
        | ((source & 0x0000ff00) << 8)
 
318
        | ((source & 0x00ff0000) >> 8)
 
319
        | ((source & 0xff000000) >> 24);
 
320
}
 
321
 
 
322
template <> inline quint16 qbswap<quint16>(quint16 source)
 
323
{
 
324
    return quint16( 0
 
325
                    | ((source & 0x00ff) << 8)
 
326
                    | ((source & 0xff00) >> 8) );
 
327
}
 
328
#endif // __GLIBC__
 
329
 
 
330
// signed specializations
 
331
template <> inline qint64 qbswap<qint64>(qint64 source)
 
332
{
 
333
    return qbswap<quint64>(quint64(source));
 
334
}
 
335
 
 
336
template <> inline qint32 qbswap<qint32>(qint32 source)
 
337
{
 
338
    return qbswap<quint32>(quint32(source));
 
339
}
 
340
 
 
341
template <> inline qint16 qbswap<qint16>(qint16 source)
 
342
{
 
343
    return qbswap<quint16>(quint16(source));
 
344
}
 
345
 
 
346
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
 
347
 
 
348
template <typename T> inline T qToBigEndian(T source)
 
349
{ return source; }
 
350
template <typename T> inline T qFromBigEndian(T source)
 
351
{ return 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
 
361
 
 
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)
 
367
{ return source; }
 
368
template <typename T> inline T qFromLittleEndian(T source)
 
369
{ return 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); }
 
374
 
 
375
#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
 
376
 
 
377
template <> inline quint8 qbswap<quint8>(quint8 source)
 
378
{
 
379
    return source;
 
380
}
 
381
 
 
382
template <> inline qint8 qbswap<qint8>(qint8 source)
 
383
{
 
384
    return source;
 
385
}
 
386
 
 
387
QT_END_NAMESPACE
 
388
 
 
389
QT_END_HEADER
 
390
 
 
391
#endif // QENDIAN_H