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 Q_DECL_ALIGN(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 
sseSwapLoop(const uchar * src,size_t bytes,uchar * dst,const __m128i * shuffleMaskPtr)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
simdSwapLoop(const uchar * src,size_t bytes,uchar * dst)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
bswapLoop(const uchar * src,size_t n,uchar * dst)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 
qbswap(const void * source,qsizetype n,void * dest)894 template <> void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept
895 {
896     const uchar *src = reinterpret_cast<const uchar *>(source);
897     uchar *dst = reinterpret_cast<uchar *>(dest);
898 
899     return bswapLoop<quint16>(src, n << 1, dst);
900 }
901 
qbswap(const void * source,qsizetype n,void * dest)902 template <> void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept
903 {
904     const uchar *src = reinterpret_cast<const uchar *>(source);
905     uchar *dst = reinterpret_cast<uchar *>(dest);
906 
907     return bswapLoop<quint32>(src, n << 2, dst);
908 }
909 
qbswap(const void * source,qsizetype n,void * dest)910 template <> void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept
911 {
912     const uchar *src = reinterpret_cast<const uchar *>(source);
913     uchar *dst = reinterpret_cast<uchar *>(dest);
914 
915     return bswapLoop<quint64>(src, n << 3, dst);
916 }
917 
918 QT_END_NAMESPACE
919