Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qendian.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QENDIAN_H
6#define QENDIAN_H
7
8#if 0
9#pragma qt_class(QtEndian)
10#endif
11
12#include <QtCore/qfloat16.h>
13#include <QtCore/qglobal.h>
14
15#include <limits>
16
17// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
18#include <stdlib.h>
19#include <string.h>
20
21#ifdef min // MSVC
22#undef min
23#undef max
24#endif
25
27
28/*
29 * ENDIAN FUNCTIONS
30*/
31
32// Used to implement a type-safe and alignment-safe copy operation
33// If you want to avoid the memcpy, you must write specializations for these functions
34template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
35{
36 // Using sizeof(T) inside memcpy function produces internal compiler error with
37 // MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
38 const size_t size = sizeof(T);
39#if __has_builtin(__builtin_memcpy)
40 __builtin_memcpy
41#else
42 memcpy
43#endif
44 (dest, &src, size);
45}
46
47template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
48{
49 T dest;
50 const size_t size = sizeof(T);
51#if __has_builtin(__builtin_memcpy)
52 __builtin_memcpy
53#else
54 memcpy
55#endif
56 (&dest, src, size);
57 return dest;
58}
59
60// These definitions are written so that they are recognized by most compilers
61// as bswap and replaced with single instruction builtins if available.
63{
64 return 0
65 | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
66 | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
67 | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
68 | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
69 | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
70 | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
71 | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
72 | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
73}
74
76{
77 return 0
78 | ((source & 0x000000ff) << 24)
79 | ((source & 0x0000ff00) << 8)
80 | ((source & 0x00ff0000) >> 8)
81 | ((source & 0xff000000) >> 24);
82}
83
85{
86 return quint16( 0
87 | ((source & 0x00ff) << 8)
88 | ((source & 0xff00) >> 8) );
89}
90
92{
93 return source;
94}
95
96/*
97 * T qbswap(T source).
98 * Changes the byte order of a value from big-endian to little-endian or vice versa.
99 * This function can be used if you are not concerned about alignment issues,
100 * and it is therefore a bit more convenient and in most cases more efficient.
101*/
102template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
103inline constexpr T qbswap(T source)
104{
105 return T(qbswap_helper(typename QIntegerForSizeof<T>::Unsigned(source)));
106}
107
108#ifdef QT_SUPPORTS_INT128
109// extra definitions for q(u)int128, in case std::is_integral_v<~~> == false
110inline constexpr quint128 qbswap(quint128 source)
111{
112 quint128 result = {};
114 result <<= 64;
116 return result;
117}
118
119inline constexpr qint128 qbswap(qint128 source)
120{
121 return qint128(qbswap(quint128(source)));
122}
123#endif
124
125// floating specializations
126template<typename Float>
128{
129 // memcpy call in qFromUnaligned is recognized by optimizer as a correct way of type prunning
130 auto temp = qFromUnaligned<typename QIntegerForSizeof<Float>::Unsigned>(&source);
131 temp = qbswap(temp);
132 return qFromUnaligned<Float>(&temp);
133}
134
136{
138}
139
140inline float qbswap(float source)
141{
143}
144
145inline double qbswap(double source)
146{
148}
149
150/*
151 * qbswap(const T src, const void *dest);
152 * Changes the byte order of \a src from big-endian to little-endian or vice versa
153 * and stores the result in \a dest.
154 * There is no alignment requirements for \a dest.
155*/
156template <typename T> inline void qbswap(const T src, void *dest)
157{
158 qToUnaligned<T>(qbswap(src), dest);
159}
160
161template <int Size> void *qbswap(const void *source, qsizetype count, void *dest) noexcept;
162template<> inline void *qbswap<1>(const void *source, qsizetype count, void *dest) noexcept
163{
164 return source != dest ? memcpy(dest, source, size_t(count)) : dest;
165}
166template<> Q_CORE_EXPORT void *qbswap<2>(const void *source, qsizetype count, void *dest) noexcept;
167template<> Q_CORE_EXPORT void *qbswap<4>(const void *source, qsizetype count, void *dest) noexcept;
168template<> Q_CORE_EXPORT void *qbswap<8>(const void *source, qsizetype count, void *dest) noexcept;
169
170#if Q_BYTE_ORDER == Q_BIG_ENDIAN
171
172template <typename T> inline constexpr T qToBigEndian(T source)
173{ return source; }
174template <typename T> inline constexpr T qFromBigEndian(T source)
175{ return source; }
176template <typename T> inline constexpr T qToLittleEndian(T source)
177{ return qbswap(source); }
178template <typename T> inline constexpr T qFromLittleEndian(T source)
179{ return qbswap(source); }
180template <typename T> inline void qToBigEndian(T src, void *dest)
181{ qToUnaligned<T>(src, dest); }
182template <typename T> inline void qToLittleEndian(T src, void *dest)
183{ qbswap<T>(src, dest); }
184
185template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
186{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
187template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
188{ qbswap<sizeof(T)>(source, count, dest); }
189template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
190{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
191template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
192{ qbswap<sizeof(T)>(source, count, dest); }
193#else // Q_LITTLE_ENDIAN
194
195template <typename T> inline constexpr T qToBigEndian(T source)
196{ return qbswap(source); }
197template <typename T> inline constexpr T qFromBigEndian(T source)
198{ return qbswap(source); }
199template <typename T> inline constexpr T qToLittleEndian(T source)
200{ return source; }
201template <typename T> inline constexpr T qFromLittleEndian(T source)
202{ return source; }
203template <typename T> inline void qToBigEndian(T src, void *dest)
204{ qbswap<T>(src, dest); }
205template <typename T> inline void qToLittleEndian(T src, void *dest)
206{ qToUnaligned<T>(src, dest); }
207
208template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
209{ qbswap<sizeof(T)>(source, count, dest); }
210template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
211{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
212template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
213{ qbswap<sizeof(T)>(source, count, dest); }
214template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
215{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
216#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
217
218
219/* T qFromLittleEndian(const void *src)
220 * This function will read a little-endian encoded value from \a src
221 * and return the value in host-endian encoding.
222 * There is no requirement that \a src must be aligned.
223*/
224template <typename T> inline T qFromLittleEndian(const void *src)
225{
226 return qFromLittleEndian(qFromUnaligned<T>(src));
227}
228
229template <> inline quint8 qFromLittleEndian<quint8>(const void *src)
230{ return static_cast<const quint8 *>(src)[0]; }
231template <> inline qint8 qFromLittleEndian<qint8>(const void *src)
232{ return static_cast<const qint8 *>(src)[0]; }
233
234/* This function will read a big-endian (also known as network order) encoded value from \a src
235 * and return the value in host-endian encoding.
236 * There is no requirement that \a src must be aligned.
237*/
238template <class T> inline T qFromBigEndian(const void *src)
239{
240 return qFromBigEndian(qFromUnaligned<T>(src));
241}
242
243template <> inline quint8 qFromBigEndian<quint8>(const void *src)
244{ return static_cast<const quint8 *>(src)[0]; }
245template <> inline qint8 qFromBigEndian<qint8>(const void *src)
246{ return static_cast<const qint8 *>(src)[0]; }
247
248template<class S>
250{
251 typedef typename S::StorageType T;
252 T val;
253public:
254 QSpecialInteger() = default;
255 explicit constexpr QSpecialInteger(T i) : val(S::toSpecial(i)) {}
256
257 QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
258 operator T() const { return S::fromSpecial(val); }
259
260 bool operator ==(QSpecialInteger<S> i) const { return val == i.val; }
261 bool operator !=(QSpecialInteger<S> i) const { return val != i.val; }
262
264 { return (*this = S::fromSpecial(val) + i); }
266 { return (*this = S::fromSpecial(val) - i); }
268 { return (*this = S::fromSpecial(val) * i); }
270 { return (*this = S::fromSpecial(val) >> i); }
272 { return (*this = S::fromSpecial(val) << i); }
274 { return (*this = S::fromSpecial(val) / i); }
276 { return (*this = S::fromSpecial(val) % i); }
278 { return (*this = S::fromSpecial(val) | i); }
280 { return (*this = S::fromSpecial(val) & i); }
282 { return (*this = S::fromSpecial(val) ^ i); }
284 { return (*this = S::fromSpecial(val) + 1); }
286 { return (*this = S::fromSpecial(val) - 1); }
288 {
289 QSpecialInteger<S> pre = *this;
290 *this += 1;
291 return pre;
292 }
294 {
295 QSpecialInteger<S> pre = *this;
296 *this -= 1;
297 return pre;
298 }
299
300 static constexpr QSpecialInteger max()
301 { return QSpecialInteger((std::numeric_limits<T>::max)()); }
302 static constexpr QSpecialInteger min()
303 { return QSpecialInteger((std::numeric_limits<T>::min)()); }
304};
305
306template<typename T>
308public:
309 typedef T StorageType;
310 static constexpr T toSpecial(T source) { return qToLittleEndian(source); }
311 static constexpr T fromSpecial(T source) { return qFromLittleEndian(source); }
312};
313
314template<typename T>
316public:
317 typedef T StorageType;
318 static constexpr T toSpecial(T source) { return qToBigEndian(source); }
319 static constexpr T fromSpecial(T source) { return qFromBigEndian(source); }
320};
321
322#ifdef Q_QDOC
323template<typename T>
324class QLEInteger {
325public:
326 explicit constexpr QLEInteger(T i);
327 QLEInteger &operator =(T i);
328 operator T() const;
329 bool operator ==(QLEInteger i) const;
330 bool operator !=(QLEInteger i) const;
332 QLEInteger &operator -=(T i);
333 QLEInteger &operator *=(T i);
334 QLEInteger &operator >>=(T i);
335 QLEInteger &operator <<=(T i);
336 QLEInteger &operator /=(T i);
337 QLEInteger &operator %=(T i);
339 QLEInteger &operator &=(T i);
340 QLEInteger &operator ^=(T i);
341 QLEInteger &operator ++();
342 QLEInteger &operator --();
343 QLEInteger operator ++(int);
344 QLEInteger operator --(int);
345
346 static constexpr QLEInteger max();
347 static constexpr QLEInteger min();
348};
349
350template<typename T>
351class QBEInteger {
352public:
353 explicit constexpr QBEInteger(T i);
354 QBEInteger &operator =(T i);
355 operator T() const;
356 bool operator ==(QBEInteger i) const;
357 bool operator !=(QBEInteger i) const;
359 QBEInteger &operator -=(T i);
360 QBEInteger &operator *=(T i);
361 QBEInteger &operator >>=(T i);
362 QBEInteger &operator <<=(T i);
363 QBEInteger &operator /=(T i);
364 QBEInteger &operator %=(T i);
366 QBEInteger &operator &=(T i);
367 QBEInteger &operator ^=(T i);
368 QBEInteger &operator ++();
369 QBEInteger &operator --();
370 QBEInteger operator ++(int);
371 QBEInteger operator --(int);
372
373 static constexpr QBEInteger max();
374 static constexpr QBEInteger min();
375};
376#else
377
378template<typename T>
379using QLEInteger = QSpecialInteger<QLittleEndianStorageType<T>>;
380
381template<typename T>
382using QBEInteger = QSpecialInteger<QBigEndianStorageType<T>>;
383#endif
384template <typename T>
386 : public QTypeInfoMerger<QLEInteger<T>, T> {};
387
388template <typename T>
390 : public QTypeInfoMerger<QBEInteger<T>, T> {};
391
392typedef QLEInteger<qint16> qint16_le;
393typedef QLEInteger<qint32> qint32_le;
394typedef QLEInteger<qint64> qint64_le;
395typedef QLEInteger<quint16> quint16_le;
396typedef QLEInteger<quint32> quint32_le;
397typedef QLEInteger<quint64> quint64_le;
398
399typedef QBEInteger<qint16> qint16_be;
400typedef QBEInteger<qint32> qint32_be;
401typedef QBEInteger<qint64> qint64_be;
402typedef QBEInteger<quint16> quint16_be;
403typedef QBEInteger<quint32> quint32_be;
404typedef QBEInteger<quint64> quint64_be;
405
407
408#endif // QENDIAN_H
\inmodule QtCore
static constexpr T fromSpecial(T source)
Definition qendian.h:319
static constexpr T toSpecial(T source)
Definition qendian.h:318
\inmodule QtCore
static constexpr T fromSpecial(T source)
Definition qendian.h:311
static constexpr T toSpecial(T source)
Definition qendian.h:310
bool operator!=(QSpecialInteger< S > i) const
Definition qendian.h:261
static constexpr QSpecialInteger max()
Definition qendian.h:300
QSpecialInteger & operator>>=(T i)
Definition qendian.h:269
constexpr QSpecialInteger(T i)
Definition qendian.h:255
QSpecialInteger & operator<<=(T i)
Definition qendian.h:271
QSpecialInteger & operator++()
Definition qendian.h:283
bool operator==(QSpecialInteger< S > i) const
Definition qendian.h:260
QSpecialInteger & operator=(T i)
Definition qendian.h:257
QSpecialInteger & operator&=(T i)
Definition qendian.h:279
QSpecialInteger & operator+=(T i)
Definition qendian.h:263
QSpecialInteger & operator|=(T i)
Definition qendian.h:277
QSpecialInteger & operator--()
Definition qendian.h:285
QSpecialInteger & operator*=(T i)
Definition qendian.h:267
QSpecialInteger & operator^=(T i)
Definition qendian.h:281
QSpecialInteger()=default
QSpecialInteger & operator%=(T i)
Definition qendian.h:275
QSpecialInteger & operator/=(T i)
Definition qendian.h:273
static constexpr QSpecialInteger min()
Definition qendian.h:302
QSpecialInteger & operator-=(T i)
Definition qendian.h:265
\inmodule QtCore
Definition qtypeinfo.h:100
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
Definition qfloat16.h:47
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Definition qnumeric.h:366
#define Q_ALWAYS_INLINE
constexpr bool operator!=(const timespec &t1, const timespec &t2)
constexpr timespec & operator+=(timespec &t1, const timespec &t2)
QBEInteger< quint64 > quint64_be
Definition qendian.h:404
quint8 qFromLittleEndian< quint8 >(const void *src)
Definition qendian.h:229
QLEInteger< qint64 > qint64_le
Definition qendian.h:394
QSpecialInteger< QLittleEndianStorageType< T > > QLEInteger
Constructs a QLEInteger with the given value.
Definition qendian.h:379
QBEInteger< qint32 > qint32_be
Definition qendian.h:400
QLEInteger< qint32 > qint32_le
Definition qendian.h:393
Q_CORE_EXPORT void * qbswap< 4 >(const void *source, qsizetype count, void *dest) noexcept
Definition qendian.cpp:869
void * qbswap< 1 >(const void *source, qsizetype count, void *dest) noexcept
Definition qendian.h:162
QBEInteger< qint64 > qint64_be
Definition qendian.h:401
QLEInteger< quint32 > quint32_le
Definition qendian.h:396
QLEInteger< quint64 > quint64_le
Definition qendian.h:397
constexpr quint64 qbswap_helper(quint64 source)
Definition qendian.h:62
constexpr T qbswap(T source)
Definition qendian.h:103
Q_CORE_EXPORT void * qbswap< 2 >(const void *source, qsizetype count, void *dest) noexcept
Definition qendian.cpp:860
QBEInteger< quint32 > quint32_be
Definition qendian.h:403
constexpr T qFromLittleEndian(T source)
Definition qendian.h:178
constexpr T qToBigEndian(T source)
Definition qendian.h:172
QLEInteger< quint16 > quint16_le
Definition qendian.h:395
QLEInteger< qint16 > qint16_le
Definition qendian.h:392
constexpr T qFromBigEndian(T source)
Definition qendian.h:174
Q_CORE_EXPORT void * qbswap< 8 >(const void *source, qsizetype count, void *dest) noexcept
Definition qendian.cpp:878
QT_BEGIN_NAMESPACE Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
Definition qendian.h:34
qint8 qFromBigEndian< qint8 >(const void *src)
Definition qendian.h:245
QBEInteger< qint16 > qint16_be
Definition qendian.h:399
Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
Definition qendian.h:47
quint8 qFromBigEndian< quint8 >(const void *src)
Definition qendian.h:243
QBEInteger< quint16 > quint16_be
Definition qendian.h:402
QSpecialInteger< QBigEndianStorageType< T > > QBEInteger
Constructs a QBEInteger with the given value.
Definition qendian.h:382
constexpr T qToLittleEndian(T source)
Definition qendian.h:176
qint8 qFromLittleEndian< qint8 >(const void *src)
Definition qendian.h:231
Float qbswapFloatHelper(Float source)
Definition qendian.h:127
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLenum src
GLsizei GLsizei GLchar * source
GLuint GLfloat * val
GLuint64EXT * result
[6]
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1220
#define Q_UINT64_C(c)
Definition qtypes.h:58
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45
unsigned char quint8
Definition qtypes.h:46
QUrl::FormattingOptions & operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
Definition qurl.h:301