QtBase  v6.3.1
qendian.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Copyright (C) 2021 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QENDIAN_H
42 #define QENDIAN_H
43 
44 #include <QtCore/qfloat16.h>
45 #include <QtCore/qglobal.h>
46 
47 #include <limits>
48 
49 // include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
50 #include <stdlib.h>
51 #include <string.h>
52 
53 #ifdef min // MSVC
54 #undef min
55 #undef max
56 #endif
57 
59 
60 /*
61  * ENDIAN FUNCTIONS
62 */
63 
64 // Used to implement a type-safe and alignment-safe copy operation
65 // If you want to avoid the memcpy, you must write specializations for these functions
66 template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
67 {
68  // Using sizeof(T) inside memcpy function produces internal compiler error with
69  // MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
70  const size_t size = sizeof(T);
71 #if __has_builtin(__builtin_memcpy)
72  __builtin_memcpy
73 #else
74  memcpy
75 #endif
76  (dest, &src, size);
77 }
78 
79 template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
80 {
81  T dest;
82  const size_t size = sizeof(T);
83 #if __has_builtin(__builtin_memcpy)
84  __builtin_memcpy
85 #else
86  memcpy
87 #endif
88  (&dest, src, size);
89  return dest;
90 }
91 
92 // These definitions are written so that they are recognized by most compilers
93 // as bswap and replaced with single instruction builtins if available.
95 {
96  return 0
97  | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
98  | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
99  | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
100  | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
101  | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
102  | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
103  | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
104  | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
105 }
106 
108 {
109  return 0
110  | ((source & 0x000000ff) << 24)
111  | ((source & 0x0000ff00) << 8)
112  | ((source & 0x00ff0000) >> 8)
113  | ((source & 0xff000000) >> 24);
114 }
115 
117 {
118  return quint16( 0
119  | ((source & 0x00ff) << 8)
120  | ((source & 0xff00) >> 8) );
121 }
122 
124 {
125  return source;
126 }
127 
128 /*
129  * T qbswap(T source).
130  * Changes the byte order of a value from big-endian to little-endian or vice versa.
131  * This function can be used if you are not concerned about alignment issues,
132  * and it is therefore a bit more convenient and in most cases more efficient.
133 */
134 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
135 inline constexpr T qbswap(T source)
136 {
137  return T(qbswap_helper(typename QIntegerForSizeof<T>::Unsigned(source)));
138 }
139 
140 // floating specializations
141 template<typename Float>
143 {
144  // memcpy call in qFromUnaligned is recognized by optimizer as a correct way of type prunning
145  auto temp = qFromUnaligned<typename QIntegerForSizeof<Float>::Unsigned>(&source);
146  temp = qbswap(temp);
147  return qFromUnaligned<Float>(&temp);
148 }
149 
151 {
152  return qbswapFloatHelper(source);
153 }
154 
155 inline float qbswap(float source)
156 {
157  return qbswapFloatHelper(source);
158 }
159 
160 inline double qbswap(double source)
161 {
162  return qbswapFloatHelper(source);
163 }
164 
165 /*
166  * qbswap(const T src, const void *dest);
167  * Changes the byte order of \a src from big-endian to little-endian or vice versa
168  * and stores the result in \a dest.
169  * There is no alignment requirements for \a dest.
170 */
171 template <typename T> inline void qbswap(const T src, void *dest)
172 {
173  qToUnaligned<T>(qbswap(src), dest);
174 }
175 
176 template <int Size> void *qbswap(const void *source, qsizetype count, void *dest) noexcept;
177 template<> inline void *qbswap<1>(const void *source, qsizetype count, void *dest) noexcept
178 {
179  return source != dest ? memcpy(dest, source, size_t(count)) : dest;
180 }
181 template<> Q_CORE_EXPORT void *qbswap<2>(const void *source, qsizetype count, void *dest) noexcept;
182 template<> Q_CORE_EXPORT void *qbswap<4>(const void *source, qsizetype count, void *dest) noexcept;
183 template<> Q_CORE_EXPORT void *qbswap<8>(const void *source, qsizetype count, void *dest) noexcept;
184 
185 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
186 
187 template <typename T> inline constexpr T qToBigEndian(T source)
188 { return source; }
189 template <typename T> inline constexpr T qFromBigEndian(T source)
190 { return source; }
191 template <typename T> inline constexpr T qToLittleEndian(T source)
192 { return qbswap(source); }
193 template <typename T> inline constexpr T qFromLittleEndian(T source)
194 { return qbswap(source); }
195 template <typename T> inline void qToBigEndian(T src, void *dest)
196 { qToUnaligned<T>(src, dest); }
197 template <typename T> inline void qToLittleEndian(T src, void *dest)
198 { qbswap<T>(src, dest); }
199 
200 template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
201 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
202 template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
203 { qbswap<sizeof(T)>(source, count, dest); }
204 template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
205 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
206 template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
207 { qbswap<sizeof(T)>(source, count, dest); }
208 #else // Q_LITTLE_ENDIAN
209 
210 template <typename T> inline constexpr T qToBigEndian(T source)
211 { return qbswap(source); }
212 template <typename T> inline constexpr T qFromBigEndian(T source)
213 { return qbswap(source); }
214 template <typename T> inline constexpr T qToLittleEndian(T source)
215 { return source; }
216 template <typename T> inline constexpr T qFromLittleEndian(T source)
217 { return source; }
218 template <typename T> inline void qToBigEndian(T src, void *dest)
219 { qbswap<T>(src, dest); }
220 template <typename T> inline void qToLittleEndian(T src, void *dest)
221 { qToUnaligned<T>(src, dest); }
222 
223 template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
224 { qbswap<sizeof(T)>(source, count, dest); }
225 template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
226 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
227 template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
228 { qbswap<sizeof(T)>(source, count, dest); }
229 template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
230 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
231 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
232 
233 
234 /* T qFromLittleEndian(const void *src)
235  * This function will read a little-endian encoded value from \a src
236  * and return the value in host-endian encoding.
237  * There is no requirement that \a src must be aligned.
238 */
239 template <typename T> inline T qFromLittleEndian(const void *src)
240 {
241  return qFromLittleEndian(qFromUnaligned<T>(src));
242 }
243 
244 template <> inline quint8 qFromLittleEndian<quint8>(const void *src)
245 { return static_cast<const quint8 *>(src)[0]; }
246 template <> inline qint8 qFromLittleEndian<qint8>(const void *src)
247 { return static_cast<const qint8 *>(src)[0]; }
248 
249 /* This function will read a big-endian (also known as network order) encoded value from \a src
250  * and return the value in host-endian encoding.
251  * There is no requirement that \a src must be aligned.
252 */
253 template <class T> inline T qFromBigEndian(const void *src)
254 {
255  return qFromBigEndian(qFromUnaligned<T>(src));
256 }
257 
258 template <> inline quint8 qFromBigEndian<quint8>(const void *src)
259 { return static_cast<const quint8 *>(src)[0]; }
260 template <> inline qint8 qFromBigEndian<qint8>(const void *src)
261 { return static_cast<const qint8 *>(src)[0]; }
262 
263 template<class S>
265 {
266  typedef typename S::StorageType T;
267  T val;
268 public:
269  QSpecialInteger() = default;
270  explicit constexpr QSpecialInteger(T i) : val(S::toSpecial(i)) {}
271 
272  QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
273  operator T() const { return S::fromSpecial(val); }
274 
275  bool operator ==(QSpecialInteger<S> i) const { return val == i.val; }
276  bool operator !=(QSpecialInteger<S> i) const { return val != i.val; }
277 
279  { return (*this = S::fromSpecial(val) + i); }
281  { return (*this = S::fromSpecial(val) - i); }
283  { return (*this = S::fromSpecial(val) * i); }
285  { return (*this = S::fromSpecial(val) >> i); }
287  { return (*this = S::fromSpecial(val) << i); }
289  { return (*this = S::fromSpecial(val) / i); }
291  { return (*this = S::fromSpecial(val) % i); }
293  { return (*this = S::fromSpecial(val) | i); }
295  { return (*this = S::fromSpecial(val) & i); }
297  { return (*this = S::fromSpecial(val) ^ i); }
299  { return (*this = S::fromSpecial(val) + 1); }
301  { return (*this = S::fromSpecial(val) - 1); }
303  {
304  QSpecialInteger<S> pre = *this;
305  *this += 1;
306  return pre;
307  }
309  {
310  QSpecialInteger<S> pre = *this;
311  *this -= 1;
312  return pre;
313  }
314 
315  static constexpr QSpecialInteger max()
316  { return QSpecialInteger((std::numeric_limits<T>::max)()); }
317  static constexpr QSpecialInteger min()
318  { return QSpecialInteger((std::numeric_limits<T>::min)()); }
319 };
320 
321 template<typename T>
323 public:
324  typedef T StorageType;
325  static constexpr T toSpecial(T source) { return qToLittleEndian(source); }
326  static constexpr T fromSpecial(T source) { return qFromLittleEndian(source); }
327 };
328 
329 template<typename T>
331 public:
332  typedef T StorageType;
333  static constexpr T toSpecial(T source) { return qToBigEndian(source); }
334  static constexpr T fromSpecial(T source) { return qFromBigEndian(source); }
335 };
336 
337 #ifdef Q_CLANG_QDOC
338 template<typename T>
339 class QLEInteger {
340 public:
341  explicit constexpr QLEInteger(T i);
342  QLEInteger &operator =(T i);
343  operator T() const;
344  bool operator ==(QLEInteger i) const;
345  bool operator !=(QLEInteger i) const;
347  QLEInteger &operator -=(T i);
348  QLEInteger &operator *=(T i);
349  QLEInteger &operator >>=(T i);
350  QLEInteger &operator <<=(T i);
351  QLEInteger &operator /=(T i);
352  QLEInteger &operator %=(T i);
354  QLEInteger &operator &=(T i);
355  QLEInteger &operator ^=(T i);
356  QLEInteger &operator ++();
357  QLEInteger &operator --();
358  QLEInteger &operator ++(int);
359  QLEInteger &operator --(int);
360 
361  static constexpr QLEInteger max();
362  static constexpr QLEInteger min();
363 };
364 
365 template<typename T>
366 class QBEInteger {
367 public:
368  explicit constexpr QBEInteger(T i);
369  QBEInteger &operator =(T i);
370  operator T() const;
371  bool operator ==(QBEInteger i) const;
372  bool operator !=(QBEInteger i) const;
374  QBEInteger &operator -=(T i);
375  QBEInteger &operator *=(T i);
376  QBEInteger &operator >>=(T i);
377  QBEInteger &operator <<=(T i);
378  QBEInteger &operator /=(T i);
379  QBEInteger &operator %=(T i);
381  QBEInteger &operator &=(T i);
382  QBEInteger &operator ^=(T i);
383  QBEInteger &operator ++();
384  QBEInteger &operator --();
385  QBEInteger &operator ++(int);
386  QBEInteger &operator --(int);
387 
388  static constexpr QBEInteger max();
389  static constexpr QBEInteger min();
390 };
391 #else
392 
393 template<typename T>
395 
396 template<typename T>
398 #endif
399 template <typename T>
401  : public QTypeInfoMerger<QLEInteger<T>, T> {};
402 
403 template <typename T>
405  : public QTypeInfoMerger<QBEInteger<T>, T> {};
406 
413 
420 
422 
423 #endif // QENDIAN_H
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
@ Float
The QBEInteger class provides platform-independent big-endian integers.
static constexpr T fromSpecial(T source)
Definition: qendian.h:334
static constexpr T toSpecial(T source)
Definition: qendian.h:333
The QLEInteger class provides platform-independent little-endian integers.
static constexpr T fromSpecial(T source)
Definition: qendian.h:326
static constexpr T toSpecial(T source)
Definition: qendian.h:325
bool operator!=(QSpecialInteger< S > i) const
Definition: qendian.h:276
static constexpr QSpecialInteger max()
Definition: qendian.h:315
QSpecialInteger & operator<<=(T i)
Definition: qendian.h:286
QSpecialInteger & operator^=(T i)
Definition: qendian.h:296
QSpecialInteger & operator%=(T i)
Definition: qendian.h:290
constexpr QSpecialInteger(T i)
Definition: qendian.h:270
bool operator==(QSpecialInteger< S > i) const
Definition: qendian.h:275
QSpecialInteger & operator=(T i)
Definition: qendian.h:272
QSpecialInteger & operator&=(T i)
Definition: qendian.h:294
QSpecialInteger & operator++()
Definition: qendian.h:298
QSpecialInteger & operator>>=(T i)
Definition: qendian.h:284
QSpecialInteger & operator--()
Definition: qendian.h:300
QSpecialInteger & operator*=(T i)
Definition: qendian.h:282
QSpecialInteger & operator-=(T i)
Definition: qendian.h:280
QSpecialInteger & operator+=(T i)
Definition: qendian.h:278
QSpecialInteger()=default
QSpecialInteger & operator|=(T i)
Definition: qendian.h:292
static constexpr QSpecialInteger min()
Definition: qendian.h:317
QSpecialInteger & operator/=(T i)
Definition: qendian.h:288
Provides 16-bit floating point support.
Definition: qfloat16.h:75
#define T(x)
Definition: main.cpp:42
QString & operator+=(QString &that, const ProString &other)
Definition: proitems.h:262
constexpr bool operator!=(const timespec &t1, const timespec &t2)
Definition: qcore_unix_p.h:124
QBEInteger< quint64 > quint64_be
Definition: qendian.h:419
quint8 qFromLittleEndian< quint8 >(const void *src)
Definition: qendian.h:244
QLEInteger< qint64 > qint64_le
Definition: qendian.h:409
Q_CORE_EXPORT void * qbswap< 2 >(const void *source, qsizetype count, void *dest) noexcept
Definition: qendian.cpp:896
QBEInteger< qint32 > qint32_be
Definition: qendian.h:415
QLEInteger< qint32 > qint32_le
Definition: qendian.h:408
QBEInteger< qint64 > qint64_be
Definition: qendian.h:416
QLEInteger< quint32 > quint32_le
Definition: qendian.h:411
QLEInteger< quint64 > quint64_le
Definition: qendian.h:412
constexpr quint64 qbswap_helper(quint64 source)
Definition: qendian.h:94
Q_CORE_EXPORT void * qbswap< 8 >(const void *source, qsizetype count, void *dest) noexcept
Definition: qendian.cpp:914
constexpr T qbswap(T source)
Definition: qendian.h:135
QBEInteger< quint32 > quint32_be
Definition: qendian.h:418
constexpr T qFromLittleEndian(T source)
Definition: qendian.h:193
constexpr T qToBigEndian(T source)
Definition: qendian.h:187
QLEInteger< quint16 > quint16_le
Definition: qendian.h:410
QSpecialInteger< QBigEndianStorageType< T > > QBEInteger
Definition: qendian.h:397
QLEInteger< qint16 > qint16_le
Definition: qendian.h:407
constexpr T qFromBigEndian(T source)
Definition: qendian.h:189
QT_BEGIN_NAMESPACE Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
Definition: qendian.h:66
QSpecialInteger< QLittleEndianStorageType< T > > QLEInteger
Definition: qendian.h:394
qint8 qFromBigEndian< qint8 >(const void *src)
Definition: qendian.h:260
QBEInteger< qint16 > qint16_be
Definition: qendian.h:414
quint8 qFromBigEndian< quint8 >(const void *src)
Definition: qendian.h:258
QBEInteger< quint16 > quint16_be
Definition: qendian.h:417
void * qbswap< 1 >(const void *source, qsizetype count, void *dest) noexcept
Definition: qendian.h:177
constexpr T qToLittleEndian(T source)
Definition: qendian.h:191
Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
The <QtEndian> header provides functions to convert between little and big endian representations of ...
Definition: qendian.h:79
Q_CORE_EXPORT void * qbswap< 4 >(const void *source, qsizetype count, void *dest) noexcept
Definition: qendian.cpp:905
qint8 qFromLittleEndian< qint8 >(const void *src)
Definition: qendian.h:246
Float qbswapFloatHelper(Float source)
Definition: qendian.h:142
#define Q_UINT64_C(c)
Definition: qglobal.h:296
unsigned int quint32
Definition: qglobal.h:288
unsigned short quint16
Definition: qglobal.h:286
unsigned long long quint64
Definition: qglobal.h:299
ptrdiff_t qsizetype
Definition: qglobal.h:308
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition: qglobal.h:283
unsigned char quint8
Definition: qglobal.h:284
bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLenum src
GLsizei GLsizei GLchar * source
GLuint GLfloat * val
Definition: qopenglext.h:1513
QUrl::FormattingOptions & operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
Definition: qurl.h:327
Definition: main.cpp:38