1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Copyright (C) 2018 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 | #include "qendian.h" |
42 | |
43 | #include "qalgorithms.h" |
44 | #include <private/qsimd_p.h> |
45 | |
46 | QT_BEGIN_NAMESPACE |
47 | |
48 | /*! |
49 | \headerfile <QtEndian> |
50 | \title Endian Conversion Functions |
51 | \ingroup funclists |
52 | \brief The <QtEndian> header provides functions to convert between |
53 | little and big endian representations of numbers. |
54 | */ |
55 | |
56 | /*! |
57 | \fn template <typename T> T qFromUnaligned(const void *ptr) |
58 | \internal |
59 | \since 5.5 |
60 | |
61 | Loads a \c{T} from address \a ptr, which may be misaligned. |
62 | |
63 | Use of this function avoids the undefined behavior that the C++ standard |
64 | otherwise attributes to unaligned loads. |
65 | */ |
66 | |
67 | /*! |
68 | \fn template <typename T> void qToUnaligned(const T t, void *ptr) |
69 | \internal |
70 | \since 4.5 |
71 | |
72 | Stores \a t to address \a ptr, which may be misaligned. |
73 | |
74 | Use of this function avoids the undefined behavior that the C++ standard |
75 | otherwise attributes to unaligned stores. |
76 | */ |
77 | |
78 | |
79 | /*! |
80 | \fn template <typename T> T qFromBigEndian(const void *src) |
81 | \since 4.3 |
82 | \relates <QtEndian> |
83 | |
84 | Reads a big-endian number from memory location \a src and returns the number in the |
85 | host byte order representation. |
86 | On CPU architectures where the host byte order is little-endian (such as x86) this |
87 | will swap the byte order; otherwise it will just read from \a src. |
88 | |
89 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
90 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
91 | applicable. |
92 | |
93 | \note Since Qt 5.7, the type of the \a src parameter is a void pointer. |
94 | |
95 | There are no data alignment constraints for \a src. |
96 | |
97 | \sa qFromLittleEndian() |
98 | \sa qToBigEndian() |
99 | \sa qToLittleEndian() |
100 | */ |
101 | /*! |
102 | \fn template <typename T> T qFromBigEndian(T src) |
103 | \since 4.3 |
104 | \relates <QtEndian> |
105 | \overload |
106 | |
107 | Converts \a src from big-endian byte order and returns the number in host byte order |
108 | representation of that number. |
109 | On CPU architectures where the host byte order is little-endian (such as x86) this |
110 | will return \a src with the byte order swapped; otherwise it will return \a src |
111 | unmodified. |
112 | */ |
113 | /*! |
114 | \fn template <typename T> T qFromBigEndian(const void *src, qsizetype count, void *dest) |
115 | \since 5.12 |
116 | \relates <QtEndian> |
117 | |
118 | Reads \a count big-endian numbers from memory location \a src and stores |
119 | them in the host byte order representation at \a dest. On CPU architectures |
120 | where the host byte order is little-endian (such as x86) this will swap the |
121 | byte order; otherwise it will just perform a \c memcpy from \a src to \a |
122 | dest. |
123 | |
124 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
125 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
126 | applicable. |
127 | |
128 | There are no data alignment constraints for \a src. However, \a dest is |
129 | expected to be naturally aligned for type \c{T}. |
130 | |
131 | If \a src and \a dest can be the same pointer, this function will perform |
132 | an in-place swap (if necessary). If they are not the same, the memory |
133 | regions must not overlap. |
134 | |
135 | \sa qFromLittleEndian() |
136 | \sa qToBigEndian() |
137 | \sa qToLittleEndian() |
138 | */ |
139 | /*! |
140 | \fn template <typename T> inline T qFromLittleEndian(const void *src) |
141 | \since 4.3 |
142 | \relates <QtEndian> |
143 | |
144 | Reads a little-endian number from memory location \a src and returns the number in |
145 | the host byte order representation. |
146 | On CPU architectures where the host byte order is big-endian (such as PowerPC) this |
147 | will swap the byte order; otherwise it will just read from \a src. |
148 | |
149 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
150 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
151 | applicable. |
152 | |
153 | \note Since Qt 5.7, the type of the \a src parameter is a void pointer. |
154 | |
155 | There are no data alignment constraints for \a src. |
156 | |
157 | \sa qFromBigEndian() |
158 | \sa qToBigEndian() |
159 | \sa qToLittleEndian() |
160 | */ |
161 | /*! |
162 | \fn template <typename T> inline T qFromLittleEndian(T src) |
163 | \since 4.3 |
164 | \relates <QtEndian> |
165 | \overload |
166 | |
167 | Converts \a src from little-endian byte order and returns the number in host byte |
168 | order representation of that number. |
169 | On CPU architectures where the host byte order is big-endian (such as PowerPC) this |
170 | will return \a src with the byte order swapped; otherwise it will return \a src |
171 | unmodified. |
172 | */ |
173 | /*! |
174 | \fn template <typename T> inline T qFromLittleEndian(const void *src, qsizetype count, void *dest) |
175 | \since 5.12 |
176 | \relates <QtEndian> |
177 | |
178 | Reads \a count little-endian numbers from memory location \a src and stores |
179 | them in the host byte order representation at \a dest. On CPU architectures |
180 | where the host byte order is big-endian (such as PowerPC) this will swap the |
181 | byte order; otherwise it will just perform a \c memcpy from \a src to \a |
182 | dest. |
183 | |
184 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
185 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
186 | applicable. |
187 | |
188 | There are no data alignment constraints for \a src. However, \a dest is |
189 | expected to be naturally aligned for type \c{T}. |
190 | |
191 | If \a src and \a dest can be the same pointer, this function will perform |
192 | an in-place swap (if necessary). If they are not the same, the memory |
193 | regions must not overlap. |
194 | |
195 | \sa qToBigEndian() |
196 | \sa qToLittleEndian() |
197 | */ |
198 | /*! |
199 | \fn template <typename T> void qToBigEndian(T src, void *dest) |
200 | \since 4.3 |
201 | \relates <QtEndian> |
202 | |
203 | Writes the number \a src with template type \c{T} to the memory location at \a dest |
204 | in big-endian byte order. |
205 | |
206 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
207 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
208 | applicable. |
209 | |
210 | There are no data alignment constraints for \a dest. |
211 | |
212 | \note Since Qt 5.7, the type of the \a dest parameter is a void pointer. |
213 | |
214 | \sa qFromBigEndian() |
215 | \sa qFromLittleEndian() |
216 | \sa qToLittleEndian() |
217 | */ |
218 | /*! |
219 | \fn template <typename T> T qToBigEndian(T src) |
220 | \since 4.3 |
221 | \relates <QtEndian> |
222 | \overload |
223 | |
224 | Converts \a src from host byte order and returns the number in big-endian byte order |
225 | representation of that number. |
226 | On CPU architectures where the host byte order is little-endian (such as x86) this |
227 | will return \a src with the byte order swapped; otherwise it will return \a src |
228 | unmodified. |
229 | */ |
230 | /*! |
231 | \fn template <typename T> T qToBigEndian(const void *src, qsizetype count, void *dest) |
232 | \since 5.12 |
233 | \relates <QtEndian> |
234 | |
235 | Reads \a count numbers from memory location \a src in the host byte order |
236 | and stores them in big-endian representation at \a dest. On CPU |
237 | architectures where the host byte order is little-endian (such as x86) this |
238 | will swap the byte order; otherwise it will just perform a \c memcpy from |
239 | \a src to \a dest. |
240 | |
241 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
242 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
243 | applicable. |
244 | |
245 | There are no data alignment constraints for \a dest. However, \a src is |
246 | expected to be naturally aligned for type \c{T}. |
247 | |
248 | If \a src and \a dest can be the same pointer, this function will perform |
249 | an in-place swap (if necessary). If they are not the same, the memory |
250 | regions must not overlap. |
251 | |
252 | \sa qFromLittleEndian() |
253 | \sa qToBigEndian() |
254 | \sa qToLittleEndian() |
255 | */ |
256 | /*! |
257 | \fn template <typename T> void qToLittleEndian(T src, void *dest) |
258 | \since 4.3 |
259 | \relates <QtEndian> |
260 | |
261 | Writes the number \a src with template type \c{T} to the memory location at \a dest |
262 | in little-endian byte order. |
263 | |
264 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
265 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
266 | applicable. |
267 | |
268 | There are no data alignment constraints for \a dest. |
269 | |
270 | \note Since Qt 5.7, the type of the \a dest parameter is a void pointer. |
271 | |
272 | \sa qFromBigEndian() |
273 | \sa qFromLittleEndian() |
274 | \sa qToBigEndian() |
275 | */ |
276 | /*! |
277 | \fn template <typename T> T qToLittleEndian(T src) |
278 | \since 4.3 |
279 | \relates <QtEndian> |
280 | \overload |
281 | |
282 | Converts \a src from host byte order and returns the number in little-endian byte |
283 | order representation of that number. |
284 | On CPU architectures where the host byte order is big-endian (such as PowerPC) this |
285 | will return \a src with the byte order swapped; otherwise it will return \a src |
286 | unmodified. |
287 | */ |
288 | /*! |
289 | \fn template <typename T> T qToLittleEndian(const void *src, qsizetype count, void *dest) |
290 | \since 5.12 |
291 | \relates <QtEndian> |
292 | |
293 | Reads \a count numbers from memory location \a src in the host byte order |
294 | and stores them in little-endian representation at \a dest. On CPU |
295 | architectures where the host byte order is big-endian (such as PowerPC) |
296 | this will swap the byte order; otherwise it will just perform a \c memcpy |
297 | from \a src to \a dest. |
298 | |
299 | \note Template type \c{T} can either be a quint16, qint16, quint32, qint32, |
300 | quint64, or qint64. Other types of integers, e.g., qlong, are not |
301 | applicable. |
302 | |
303 | There are no data alignment constraints for \a dest. However, \a src is |
304 | expected to be naturally aligned for type \c{T}. |
305 | |
306 | If \a src and \a dest can be the same pointer, this function will perform |
307 | an in-place swap (if necessary). If they are not the same, the memory |
308 | regions must not overlap. |
309 | |
310 | \sa qFromLittleEndian() |
311 | \sa qToBigEndian() |
312 | \sa qToLittleEndian() |
313 | */ |
314 | |
315 | /*! |
316 | \class QLEInteger |
317 | \inmodule QtCore |
318 | \brief The QLEInteger class provides platform-independent little-endian integers. |
319 | \since 5.10 |
320 | |
321 | The template parameter \c T must be a C++ integer type: |
322 | \list |
323 | \li 8-bit: char, signed char, unsigned char, qint8, quint8 |
324 | \li 16-bit: short, unsigned short, qint16, quint16, char16_t |
325 | \li 32-bit: int, unsigned int, qint32, quint32, char32_t |
326 | \li 64-bit: long long, unsigned long long, qint64, quint64 |
327 | \li platform-specific size: long, unsigned long |
328 | \li pointer size: qintptr, quintptr, qptrdiff |
329 | \endlist |
330 | |
331 | \note Using this class may be slower than using native integers, so only use it when |
332 | an exact endianness is needed. |
333 | */ |
334 | |
335 | /*! \fn template <typename T> QLEInteger<T>::QLEInteger(T value) |
336 | |
337 | Constructs a QLEInteger with the given \a value. |
338 | */ |
339 | |
340 | /*! \fn template <typename T> QLEInteger &QLEInteger<T>::operator=(T i) |
341 | |
342 | Assigns \a i to this QLEInteger and returns a reference to |
343 | this QLEInteger. |
344 | */ |
345 | |
346 | /*! |
347 | \fn template <typename T> QLEInteger<T>::operator T() const |
348 | |
349 | Returns the value of this QLEInteger as a native integer. |
350 | */ |
351 | |
352 | /*! |
353 | \fn template <typename T> bool QLEInteger<T>::operator==(QLEInteger other) const |
354 | |
355 | Returns \c true if the value of this QLEInteger is equal to the value of \a other. |
356 | */ |
357 | |
358 | /*! |
359 | \fn template <typename T> bool QLEInteger<T>::operator!=(QLEInteger other) const |
360 | |
361 | Returns \c true if the value of this QLEInteger is not equal to the value of \a other. |
362 | */ |
363 | |
364 | /*! |
365 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator+=(T i) |
366 | |
367 | Adds \a i to this QLEInteger and returns a reference to |
368 | this object. |
369 | */ |
370 | |
371 | /*! |
372 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator-=(T i) |
373 | |
374 | Subtracts \a i from this QLEInteger and returns a reference to |
375 | this object. |
376 | */ |
377 | |
378 | /*! |
379 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator*=(T i) |
380 | |
381 | Multiplies \a i with this QLEInteger and returns a reference to |
382 | this object. |
383 | */ |
384 | |
385 | /*! |
386 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator/=(T i) |
387 | |
388 | Divides this QLEInteger with \a i and returns a reference to |
389 | this object. |
390 | */ |
391 | |
392 | /*! |
393 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator%=(T i) |
394 | |
395 | Sets this QLEInteger to the remainder of a division by \a i and |
396 | returns a reference to this object. |
397 | */ |
398 | |
399 | /*! |
400 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator>>=(T i) |
401 | |
402 | Performs a left-shift by \a i on this QLEInteger and returns a |
403 | reference to this object. |
404 | */ |
405 | |
406 | /*! |
407 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator<<=(T i) |
408 | |
409 | Performs a right-shift by \a i on this QLEInteger and returns a |
410 | reference to this object. |
411 | */ |
412 | |
413 | /*! |
414 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator|=(T i) |
415 | |
416 | Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to |
417 | this object. |
418 | */ |
419 | |
420 | /*! |
421 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator&=(T i) |
422 | |
423 | Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to |
424 | this object. |
425 | */ |
426 | |
427 | /*! |
428 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator^=(T i) |
429 | |
430 | Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to |
431 | this object. |
432 | */ |
433 | |
434 | /*! |
435 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator++() |
436 | |
437 | Performs a prefix ++ (increment) on this QLEInteger and returns a reference to |
438 | this object. |
439 | */ |
440 | |
441 | /*! |
442 | \fn template <typename T> QLEInteger QLEInteger<T>::operator++(int) |
443 | |
444 | Performs a postfix ++ (increment) on this QLEInteger and returns a reference to |
445 | this object. |
446 | */ |
447 | |
448 | /*! |
449 | \fn template <typename T> QLEInteger &QLEInteger<T>::operator--() |
450 | |
451 | Performs a prefix -- (decrement) on this QLEInteger and returns a reference to |
452 | this object. |
453 | */ |
454 | |
455 | /*! |
456 | \fn template <typename T> QLEInteger QLEInteger<T>::operator--(int) |
457 | |
458 | Performs a postfix -- (decrement) on this QLEInteger and returns a reference to |
459 | this object. |
460 | */ |
461 | |
462 | /*! |
463 | \fn template <typename T> QLEInteger QLEInteger<T>::max() |
464 | |
465 | Returns the maximum (finite) value representable by the numeric type T. |
466 | */ |
467 | |
468 | /*! |
469 | \fn template <typename T> QLEInteger QLEInteger<T>::min() |
470 | |
471 | Returns the minimum (finite) value representable by the numeric type T. |
472 | */ |
473 | |
474 | /*! |
475 | \class QBEInteger |
476 | \inmodule QtCore |
477 | \brief The QBEInteger class provides platform-independent big-endian integers. |
478 | \since 5.10 |
479 | |
480 | The template parameter \c T must be a C++ integer type: |
481 | \list |
482 | \li 8-bit: char, signed char, unsigned char, qint8, quint8 |
483 | \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11) |
484 | \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11) |
485 | \li 64-bit: long long, unsigned long long, qint64, quint64 |
486 | \li platform-specific size: long, unsigned long |
487 | \li pointer size: qintptr, quintptr, qptrdiff |
488 | \endlist |
489 | |
490 | \note Using this class may be slower than using native integers, so only use it when |
491 | an exact endianness is needed. |
492 | */ |
493 | |
494 | /*! \fn template <typename T> QBEInteger<T>::QBEInteger(T value) |
495 | |
496 | Constructs a QBEInteger with the given \a value. |
497 | */ |
498 | |
499 | /*! \fn template <typename T> QBEInteger &QBEInteger<T>::operator=(T i) |
500 | |
501 | Assigns \a i to this QBEInteger and returns a reference to |
502 | this QBEInteger. |
503 | */ |
504 | |
505 | /*! |
506 | \fn template <typename T> QBEInteger<T>::operator T() const |
507 | |
508 | Returns the value of this QBEInteger as a native integer. |
509 | */ |
510 | |
511 | /*! |
512 | \fn template <typename T> bool QBEInteger<T>::operator==(QBEInteger other) const |
513 | |
514 | Returns \c true if the value of this QBEInteger is equal to the value of \a other. |
515 | */ |
516 | |
517 | /*! |
518 | \fn template <typename T> bool QBEInteger<T>::operator!=(QBEInteger other) const |
519 | |
520 | Returns \c true if the value of this QBEInteger is not equal to the value of \a other. |
521 | */ |
522 | |
523 | /*! |
524 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator+=(T i) |
525 | |
526 | Adds \a i to this QBEInteger and returns a reference to |
527 | this object. |
528 | */ |
529 | |
530 | /*! |
531 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator-=(T i) |
532 | |
533 | Subtracts \a i from this QBEInteger and returns a reference to |
534 | this object. |
535 | */ |
536 | |
537 | /*! |
538 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator*=(T i) |
539 | |
540 | Multiplies \a i with this QBEInteger and returns a reference to |
541 | this object. |
542 | */ |
543 | |
544 | /*! |
545 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator/=(T i) |
546 | |
547 | Divides this QBEInteger with \a i and returns a reference to |
548 | this object. |
549 | */ |
550 | |
551 | /*! |
552 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator%=(T i) |
553 | |
554 | Sets this QBEInteger to the remainder of a division by \a i and |
555 | returns a reference to this object. |
556 | */ |
557 | |
558 | /*! |
559 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator>>=(T i) |
560 | |
561 | Performs a left-shift by \a i on this QBEInteger and returns a |
562 | reference to this object. |
563 | */ |
564 | |
565 | /*! |
566 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator<<=(T i) |
567 | |
568 | Performs a right-shift by \a i on this QBEInteger and returns a |
569 | reference to this object. |
570 | */ |
571 | |
572 | /*! |
573 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator|=(T i) |
574 | |
575 | Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to |
576 | this object. |
577 | */ |
578 | |
579 | /*! |
580 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator&=(T i) |
581 | |
582 | Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to |
583 | this object. |
584 | */ |
585 | |
586 | /*! |
587 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator^=(T i) |
588 | |
589 | Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to |
590 | this object. |
591 | */ |
592 | |
593 | /*! |
594 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator++() |
595 | |
596 | Performs a prefix ++ (increment) on this QBEInteger and returns a reference to |
597 | this object. |
598 | */ |
599 | |
600 | /*! |
601 | \fn template <typename T> QBEInteger QBEInteger<T>::operator++(int) |
602 | |
603 | Performs a postfix ++ (increment) on this QBEInteger and returns a reference to |
604 | this object. |
605 | */ |
606 | |
607 | /*! |
608 | \fn template <typename T> QBEInteger &QBEInteger<T>::operator--() |
609 | |
610 | Performs a prefix -- (decrement) on this QBEInteger and returns a reference to |
611 | this object. |
612 | */ |
613 | |
614 | /*! |
615 | \fn template <typename T> QBEInteger QBEInteger<T>::operator--(int) |
616 | |
617 | Performs a postfix -- (decrement) on this QBEInteger and returns a reference to |
618 | this object. |
619 | */ |
620 | |
621 | /*! |
622 | \fn template <typename T> QBEInteger QBEInteger<T>::max() |
623 | |
624 | Returns the maximum (finite) value representable by the numeric type T. |
625 | */ |
626 | |
627 | /*! |
628 | \fn template <typename T> QBEInteger QBEInteger<T>::min() |
629 | |
630 | Returns the minimum (finite) value representable by the numeric type T. |
631 | */ |
632 | |
633 | /*! |
634 | \typedef quint16_le |
635 | \relates <QtEndian> |
636 | \since 5.10 |
637 | |
638 | Typedef for QLEInteger<quint16>. This type is guaranteed to be stored in memory as |
639 | a 16-bit little-endian unsigned integer on all platforms supported by Qt. |
640 | |
641 | \sa quint16 |
642 | */ |
643 | |
644 | /*! |
645 | \typedef quint32_le |
646 | \relates <QtEndian> |
647 | \since 5.10 |
648 | |
649 | Typedef for QLEInteger<quint32>. This type is guaranteed to be stored in memory as |
650 | a 32-bit little-endian unsigned integer on all platforms supported by Qt. |
651 | |
652 | \sa quint32 |
653 | */ |
654 | |
655 | /*! |
656 | \typedef quint64_le |
657 | \relates <QtEndian> |
658 | \since 5.10 |
659 | |
660 | Typedef for QLEInteger<quint64>. This type is guaranteed to be stored in memory as |
661 | a 64-bit little-endian unsigned integer on all platforms supported by Qt. |
662 | |
663 | \sa quint64 |
664 | */ |
665 | |
666 | /*! |
667 | \typedef quint16_be |
668 | \relates <QtEndian> |
669 | \since 5.10 |
670 | |
671 | Typedef for QBEInteger<quint16>. This type is guaranteed to be stored in memory as |
672 | a 16-bit big-endian unsigned integer on all platforms supported by Qt. |
673 | |
674 | \sa quint16 |
675 | */ |
676 | |
677 | /*! |
678 | \typedef quint32_be |
679 | \relates <QtEndian> |
680 | \since 5.10 |
681 | |
682 | Typedef for QBEInteger<quint32>. This type is guaranteed to be stored in memory as |
683 | a 32-bit big-endian unsigned integer on all platforms supported by Qt. |
684 | |
685 | \sa quint32 |
686 | */ |
687 | |
688 | /*! |
689 | \typedef quint64_be |
690 | \relates <QtEndian> |
691 | \since 5.10 |
692 | |
693 | Typedef for QBEInteger<quint64>. This type is guaranteed to be stored in memory as |
694 | a 64-bit big-endian unsigned integer on all platforms supported by Qt. |
695 | |
696 | \sa quint64 |
697 | */ |
698 | |
699 | /*! |
700 | \typedef qint16_le |
701 | \relates <QtEndian> |
702 | \since 5.10 |
703 | |
704 | Typedef for QLEInteger<qint16>. This type is guaranteed to be stored in memory as |
705 | a 16-bit little-endian signed integer on all platforms supported by Qt. |
706 | |
707 | \sa qint16 |
708 | */ |
709 | |
710 | /*! |
711 | \typedef qint32_le |
712 | \relates <QtEndian> |
713 | \since 5.10 |
714 | |
715 | Typedef for QLEInteger<qint32>. This type is guaranteed to be stored in memory as |
716 | a 32-bit little-endian signed integer on all platforms supported by Qt. |
717 | |
718 | \sa qint32 |
719 | */ |
720 | |
721 | /*! |
722 | \typedef qint64_le |
723 | \relates <QtEndian> |
724 | \since 5.10 |
725 | |
726 | Typedef for QLEInteger<qint64>. This type is guaranteed to be stored in memory as |
727 | a 64-bit little-endian signed integer on all platforms supported by Qt. |
728 | |
729 | \sa qint64 |
730 | */ |
731 | |
732 | /*! |
733 | \typedef qint16_be |
734 | \relates <QtEndian> |
735 | \since 5.10 |
736 | |
737 | Typedef for QBEInteger<qint16>. This type is guaranteed to be stored in memory as |
738 | a 16-bit big-endian signed integer on all platforms supported by Qt. |
739 | |
740 | \sa qint16 |
741 | */ |
742 | |
743 | /*! |
744 | \typedef qint32_be |
745 | \relates <QtEndian> |
746 | \since 5.10 |
747 | |
748 | Typedef for QBEInteger<qint32>. This type is guaranteed to be stored in memory as |
749 | a 32-bit big-endian signed integer on all platforms supported by Qt. |
750 | |
751 | \sa qint32 |
752 | */ |
753 | |
754 | /*! |
755 | \typedef qint64_be |
756 | \relates <QtEndian> |
757 | \since 5.10 |
758 | |
759 | Typedef for QBEInteger<qint64>. This type is guaranteed to be stored in memory as |
760 | a 64-bit big-endian signed integer on all platforms supported by Qt. |
761 | |
762 | \sa qint64 |
763 | */ |
764 | |
765 | #if defined(__SSSE3__) |
766 | using ShuffleMask = uchar[16]; |
767 | alignas(16) static const ShuffleMask shuffleMasks[3] = { |
768 | // 16-bit |
769 | {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14}, |
770 | // 32-bit |
771 | {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12}, |
772 | // 64-bit |
773 | {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8} |
774 | }; |
775 | |
776 | static size_t sseSwapLoop(const uchar *src, size_t bytes, uchar *dst, |
777 | const __m128i *shuffleMaskPtr) noexcept |
778 | { |
779 | size_t i = 0; |
780 | const __m128i shuffleMask = _mm_load_si128(shuffleMaskPtr); |
781 | |
782 | # ifdef __AVX2__ |
783 | const __m256i shuffleMask256 = _mm256_inserti128_si256(_mm256_castsi128_si256(shuffleMask), shuffleMask, 1); |
784 | for ( ; i + sizeof(__m256i) <= bytes; i += sizeof(__m256i)) { |
785 | __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + i)); |
786 | data = _mm256_shuffle_epi8(data, shuffleMask256); |
787 | _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst + i), data); |
788 | } |
789 | # else |
790 | for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) { |
791 | __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i)); |
792 | __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1); |
793 | data1 = _mm_shuffle_epi8(data1, shuffleMask); |
794 | data2 = _mm_shuffle_epi8(data2, shuffleMask); |
795 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1); |
796 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2); |
797 | } |
798 | # endif |
799 | |
800 | if (i + sizeof(__m128i) <= bytes) { |
801 | __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i)); |
802 | data = _mm_shuffle_epi8(data, shuffleMask); |
803 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data); |
804 | i += sizeof(__m128i); |
805 | } |
806 | |
807 | return i; |
808 | } |
809 | |
810 | template <typename T> static Q_ALWAYS_INLINE |
811 | size_t simdSwapLoop(const uchar *src, size_t bytes, uchar *dst) noexcept |
812 | { |
813 | auto shuffleMaskPtr = reinterpret_cast<const __m128i *>(shuffleMasks[0]); |
814 | shuffleMaskPtr += qCountTrailingZeroBits(sizeof(T)) - 1; |
815 | size_t i = sseSwapLoop(src, bytes, dst, shuffleMaskPtr); |
816 | |
817 | // epilogue |
818 | for (size_t _i = 0; i < bytes && _i < sizeof(__m128i); i += sizeof(T), _i += sizeof(T)) |
819 | qbswap(qFromUnaligned<T>(src + i), dst + i); |
820 | |
821 | // return the total, so the bswapLoop below does nothing |
822 | return bytes; |
823 | } |
824 | #elif defined(__SSE2__) |
825 | template <typename T> static |
826 | size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept |
827 | { |
828 | // no generic version: we can't do 32- and 64-bit swaps easily, |
829 | // so we won't try |
830 | return 0; |
831 | } |
832 | |
833 | template <> size_t simdSwapLoop<quint16>(const uchar *src, size_t bytes, uchar *dst) noexcept |
834 | { |
835 | auto swapEndian = [](__m128i &data) { |
836 | __m128i lows = _mm_srli_epi16(data, 8); |
837 | __m128i highs = _mm_slli_epi16(data, 8); |
838 | data = _mm_xor_si128(lows, highs); |
839 | }; |
840 | |
841 | size_t i = 0; |
842 | for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) { |
843 | __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i)); |
844 | __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1); |
845 | swapEndian(data1); |
846 | swapEndian(data2); |
847 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1); |
848 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2); |
849 | } |
850 | |
851 | if (i + sizeof(__m128i) <= bytes) { |
852 | __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i)); |
853 | swapEndian(data); |
854 | _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data); |
855 | i += sizeof(__m128i); |
856 | } |
857 | |
858 | // epilogue |
859 | for (size_t _i = 0 ; i < bytes && _i < sizeof(__m128i); i += sizeof(quint16), _i += sizeof(quint16)) |
860 | qbswap(qFromUnaligned<quint16>(src + i), dst + i); |
861 | |
862 | // return the total, so the bswapLoop below does nothing |
863 | return bytes; |
864 | } |
865 | #else |
866 | template <typename T> static Q_ALWAYS_INLINE |
867 | size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept |
868 | { |
869 | return 0; |
870 | } |
871 | #endif |
872 | |
873 | template <typename T> static Q_ALWAYS_INLINE |
874 | void *bswapLoop(const uchar *src, size_t n, uchar *dst) noexcept |
875 | { |
876 | // Buffers cannot partially overlap: either they're identical or totally |
877 | // disjoint (note: they can be adjacent). |
878 | if (src != dst) { |
879 | quintptr s = quintptr(src); |
880 | quintptr d = quintptr(dst); |
881 | if (s < d) |
882 | Q_ASSERT(s + n <= d); |
883 | else |
884 | Q_ASSERT(d + n <= s); |
885 | } |
886 | |
887 | size_t i = simdSwapLoop<T>(src, n, dst); |
888 | |
889 | for (; i < n; i += sizeof(T)) |
890 | qbswap(qFromUnaligned<T>(src + i), dst + i); |
891 | return dst + i; |
892 | } |
893 | |
894 | template<> |
895 | void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept |
896 | { |
897 | const uchar *src = reinterpret_cast<const uchar *>(source); |
898 | uchar *dst = reinterpret_cast<uchar *>(dest); |
899 | |
900 | return bswapLoop<quint16>(src, n << 1, dst); |
901 | } |
902 | |
903 | template<> |
904 | void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept |
905 | { |
906 | const uchar *src = reinterpret_cast<const uchar *>(source); |
907 | uchar *dst = reinterpret_cast<uchar *>(dest); |
908 | |
909 | return bswapLoop<quint32>(src, n << 2, dst); |
910 | } |
911 | |
912 | template<> |
913 | void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept |
914 | { |
915 | const uchar *src = reinterpret_cast<const uchar *>(source); |
916 | uchar *dst = reinterpret_cast<uchar *>(dest); |
917 | |
918 | return bswapLoop<quint64>(src, n << 3, dst); |
919 | } |
920 | |
921 | QT_END_NAMESPACE |
922 | |