Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-24 09:20:29

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // Copyright (C) 2021 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 // Qt-Security score:significant reason:default
0005 
0006 #ifndef QENDIAN_H
0007 #define QENDIAN_H
0008 
0009 #if 0
0010 #pragma qt_class(QtEndian)
0011 #endif
0012 
0013 #include <QtCore/qfloat16.h>
0014 #include <QtCore/qglobal.h>
0015 
0016 #include <limits>
0017 
0018 // include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
0019 #include <stdlib.h>
0020 #include <string.h>
0021 
0022 #ifdef min // MSVC
0023 #undef min
0024 #undef max
0025 #endif
0026 
0027 QT_BEGIN_NAMESPACE
0028 
0029 /*
0030  * ENDIAN FUNCTIONS
0031 */
0032 
0033 // Used to implement a type-safe and alignment-safe copy operation
0034 // If you want to avoid the memcpy, you must write specializations for these functions
0035 template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
0036 {
0037     // Using sizeof(T) inside memcpy function produces internal compiler error with
0038     // MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
0039     const size_t size = sizeof(T);
0040 #if __has_builtin(__builtin_memcpy)
0041     __builtin_memcpy
0042 #else
0043     memcpy
0044 #endif
0045             (dest, &src, size);
0046 }
0047 
0048 template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
0049 {
0050     T dest;
0051     const size_t size = sizeof(T);
0052 #if __has_builtin(__builtin_memcpy)
0053     __builtin_memcpy
0054 #else
0055     memcpy
0056 #endif
0057             (&dest, src, size);
0058     return dest;
0059 }
0060 
0061 // These definitions are written so that they are recognized by most compilers
0062 // as bswap and replaced with single instruction builtins if available.
0063 inline constexpr quint64 qbswap_helper(quint64 source)
0064 {
0065     return 0
0066         | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
0067         | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
0068         | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
0069         | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
0070         | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
0071         | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
0072         | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
0073         | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
0074 }
0075 
0076 inline constexpr quint32 qbswap_helper(quint32 source)
0077 {
0078     return 0
0079         | ((source & 0x000000ff) << 24)
0080         | ((source & 0x0000ff00) << 8)
0081         | ((source & 0x00ff0000) >> 8)
0082         | ((source & 0xff000000) >> 24);
0083 }
0084 
0085 inline constexpr quint16 qbswap_helper(quint16 source)
0086 {
0087     return quint16( 0
0088                     | ((source & 0x00ff) << 8)
0089                     | ((source & 0xff00) >> 8) );
0090 }
0091 
0092 inline constexpr quint8 qbswap_helper(quint8 source)
0093 {
0094     return source;
0095 }
0096 
0097 /*
0098  * T qbswap(T source).
0099  * Changes the byte order of a value from big-endian to little-endian or vice versa.
0100  * This function can be used if you are not concerned about alignment issues,
0101  * and it is therefore a bit more convenient and in most cases more efficient.
0102 */
0103 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
0104 inline constexpr T qbswap(T source)
0105 {
0106     return T(qbswap_helper(typename QIntegerForSizeof<T>::Unsigned(source)));
0107 }
0108 
0109 #ifdef QT_SUPPORTS_INT128
0110 // extra definitions for q(u)int128, in case std::is_integral_v<~~> == false
0111 inline constexpr quint128 qbswap(quint128 source)
0112 {
0113     quint128 result = {};
0114     result = qbswap_helper(quint64(source));
0115     result <<= 64;
0116     result |= qbswap_helper(quint64(source >> 64));
0117     return result;
0118 }
0119 
0120 inline constexpr qint128 qbswap(qint128 source)
0121 {
0122     return qint128(qbswap(quint128(source)));
0123 }
0124 #endif
0125 
0126 // floating specializations
0127 template<typename Float>
0128 Float qbswapFloatHelper(Float source)
0129 {
0130     // memcpy call in qFromUnaligned is recognized by optimizer as a correct way of type prunning
0131     auto temp = qFromUnaligned<typename QIntegerForSizeof<Float>::Unsigned>(&source);
0132     temp = qbswap(temp);
0133     return qFromUnaligned<Float>(&temp);
0134 }
0135 
0136 inline qfloat16 qbswap(qfloat16 source)
0137 {
0138     return qbswapFloatHelper(source);
0139 }
0140 
0141 inline float qbswap(float source)
0142 {
0143     return qbswapFloatHelper(source);
0144 }
0145 
0146 inline double qbswap(double source)
0147 {
0148     return qbswapFloatHelper(source);
0149 }
0150 
0151 /*
0152  * qbswap(const T src, const void *dest);
0153  * Changes the byte order of \a src from big-endian to little-endian or vice versa
0154  * and stores the result in \a dest.
0155  * There is no alignment requirements for \a dest.
0156 */
0157 template <typename T> inline void qbswap(const T src, void *dest)
0158 {
0159     qToUnaligned<T>(qbswap(src), dest);
0160 }
0161 
0162 template <int Size> void *qbswap(const void *source, qsizetype count, void *dest) noexcept;
0163 template<> inline void *qbswap<1>(const void *source, qsizetype count, void *dest) noexcept
0164 {
0165     return source != dest ? memcpy(dest, source, size_t(count)) : dest;
0166 }
0167 template<> Q_CORE_EXPORT void *qbswap<2>(const void *source, qsizetype count, void *dest) noexcept;
0168 template<> Q_CORE_EXPORT void *qbswap<4>(const void *source, qsizetype count, void *dest) noexcept;
0169 template<> Q_CORE_EXPORT void *qbswap<8>(const void *source, qsizetype count, void *dest) noexcept;
0170 
0171 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
0172 
0173 template <typename T> inline constexpr T qToBigEndian(T source)
0174 { return source; }
0175 template <typename T> inline constexpr T qFromBigEndian(T source)
0176 { return source; }
0177 template <typename T> inline constexpr T qToLittleEndian(T source)
0178 { return qbswap(source); }
0179 template <typename T> inline constexpr T qFromLittleEndian(T source)
0180 { return qbswap(source); }
0181 template <typename T> inline void qToBigEndian(T src, void *dest)
0182 { qToUnaligned<T>(src, dest); }
0183 template <typename T> inline void qToLittleEndian(T src, void *dest)
0184 { qbswap<T>(src, dest); }
0185 
0186 template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
0187 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
0188 template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
0189 { qbswap<sizeof(T)>(source, count, dest); }
0190 template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
0191 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
0192 template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
0193 { qbswap<sizeof(T)>(source, count, dest); }
0194 #else // Q_LITTLE_ENDIAN
0195 
0196 template <typename T> inline constexpr T qToBigEndian(T source)
0197 { return qbswap(source); }
0198 template <typename T> inline constexpr T qFromBigEndian(T source)
0199 { return qbswap(source); }
0200 template <typename T> inline constexpr T qToLittleEndian(T source)
0201 { return source; }
0202 template <typename T> inline constexpr T qFromLittleEndian(T source)
0203 { return source; }
0204 template <typename T> inline void qToBigEndian(T src, void *dest)
0205 { qbswap<T>(src, dest); }
0206 template <typename T> inline void qToLittleEndian(T src, void *dest)
0207 { qToUnaligned<T>(src, dest); }
0208 
0209 template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
0210 { qbswap<sizeof(T)>(source, count, dest); }
0211 template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
0212 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
0213 template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
0214 { qbswap<sizeof(T)>(source, count, dest); }
0215 template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
0216 { if (source != dest) memcpy(dest, source, count * sizeof(T)); }
0217 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
0218 
0219 
0220 /* T qFromLittleEndian(const void *src)
0221  * This function will read a little-endian encoded value from \a src
0222  * and return the value in host-endian encoding.
0223  * There is no requirement that \a src must be aligned.
0224 */
0225 template <typename T> inline T qFromLittleEndian(const void *src)
0226 {
0227     return qFromLittleEndian(qFromUnaligned<T>(src));
0228 }
0229 
0230 template <> inline quint8 qFromLittleEndian<quint8>(const void *src)
0231 { return static_cast<const quint8 *>(src)[0]; }
0232 template <> inline qint8 qFromLittleEndian<qint8>(const void *src)
0233 { return static_cast<const qint8 *>(src)[0]; }
0234 
0235 /* This function will read a big-endian (also known as network order) encoded value from \a src
0236  * and return the value in host-endian encoding.
0237  * There is no requirement that \a src must be aligned.
0238 */
0239 template <class T> inline T qFromBigEndian(const void *src)
0240 {
0241     return qFromBigEndian(qFromUnaligned<T>(src));
0242 }
0243 
0244 template <> inline quint8 qFromBigEndian<quint8>(const void *src)
0245 { return static_cast<const quint8 *>(src)[0]; }
0246 template <> inline qint8 qFromBigEndian<qint8>(const void *src)
0247 { return static_cast<const qint8 *>(src)[0]; }
0248 
0249 template<class S>
0250 class QSpecialInteger
0251 {
0252     typedef typename S::StorageType T;
0253     T val;
0254 public:
0255     QSpecialInteger() = default;
0256     explicit constexpr QSpecialInteger(T i) : val(S::toSpecial(i)) {}
0257 
0258     QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
0259     operator T() const { return S::fromSpecial(val); }
0260 
0261     bool operator ==(QSpecialInteger<S> i) const { return val == i.val; }
0262     bool operator !=(QSpecialInteger<S> i) const { return val != i.val; }
0263 
0264     QSpecialInteger &operator +=(T i)
0265     {   return (*this = S::fromSpecial(val) + i); }
0266     QSpecialInteger &operator -=(T i)
0267     {   return (*this = S::fromSpecial(val) - i); }
0268     QSpecialInteger &operator *=(T i)
0269     {   return (*this = S::fromSpecial(val) * i); }
0270     QSpecialInteger &operator >>=(T i)
0271     {   return (*this = S::fromSpecial(val) >> i); }
0272     QSpecialInteger &operator <<=(T i)
0273     {   return (*this = S::fromSpecial(val) << i); }
0274     QSpecialInteger &operator /=(T i)
0275     {   return (*this = S::fromSpecial(val) / i); }
0276     QSpecialInteger &operator %=(T i)
0277     {   return (*this = S::fromSpecial(val) % i); }
0278     QSpecialInteger &operator |=(T i)
0279     {   return (*this = S::fromSpecial(val) | i); }
0280     QSpecialInteger &operator &=(T i)
0281     {   return (*this = S::fromSpecial(val) & i); }
0282     QSpecialInteger &operator ^=(T i)
0283     {   return (*this = S::fromSpecial(val) ^ i); }
0284     QSpecialInteger &operator ++()
0285     {   return (*this = S::fromSpecial(val) + 1); }
0286     QSpecialInteger &operator --()
0287     {   return (*this = S::fromSpecial(val) - 1); }
0288     QSpecialInteger operator ++(int)
0289     {
0290         QSpecialInteger<S> pre = *this;
0291         *this += 1;
0292         return pre;
0293     }
0294     QSpecialInteger operator --(int)
0295     {
0296         QSpecialInteger<S> pre = *this;
0297         *this -= 1;
0298         return pre;
0299     }
0300 
0301     static constexpr QSpecialInteger max()
0302     { return QSpecialInteger((std::numeric_limits<T>::max)()); }
0303     static constexpr QSpecialInteger min()
0304     { return QSpecialInteger((std::numeric_limits<T>::min)()); }
0305 };
0306 
0307 template<typename T>
0308 class QLittleEndianStorageType {
0309 public:
0310     typedef T StorageType;
0311     static constexpr T toSpecial(T source) { return qToLittleEndian(source); }
0312     static constexpr T fromSpecial(T source) { return qFromLittleEndian(source); }
0313 };
0314 
0315 template<typename T>
0316 class QBigEndianStorageType {
0317 public:
0318     typedef T StorageType;
0319     static constexpr T toSpecial(T source) { return qToBigEndian(source); }
0320     static constexpr T fromSpecial(T source) { return qFromBigEndian(source); }
0321 };
0322 
0323 #ifdef Q_QDOC
0324 template<typename T>
0325 class QLEInteger {
0326 public:
0327     explicit constexpr QLEInteger(T i);
0328     QLEInteger &operator =(T i);
0329     operator T() const;
0330     bool operator ==(QLEInteger i) const;
0331     bool operator !=(QLEInteger i) const;
0332     QLEInteger &operator +=(T i);
0333     QLEInteger &operator -=(T i);
0334     QLEInteger &operator *=(T i);
0335     QLEInteger &operator >>=(T i);
0336     QLEInteger &operator <<=(T i);
0337     QLEInteger &operator /=(T i);
0338     QLEInteger &operator %=(T i);
0339     QLEInteger &operator |=(T i);
0340     QLEInteger &operator &=(T i);
0341     QLEInteger &operator ^=(T i);
0342     QLEInteger &operator ++();
0343     QLEInteger &operator --();
0344     QLEInteger operator ++(int);
0345     QLEInteger operator --(int);
0346 
0347     static constexpr QLEInteger max();
0348     static constexpr QLEInteger min();
0349 };
0350 
0351 template<typename T>
0352 class QBEInteger {
0353 public:
0354     explicit constexpr QBEInteger(T i);
0355     QBEInteger &operator =(T i);
0356     operator T() const;
0357     bool operator ==(QBEInteger i) const;
0358     bool operator !=(QBEInteger i) const;
0359     QBEInteger &operator +=(T i);
0360     QBEInteger &operator -=(T i);
0361     QBEInteger &operator *=(T i);
0362     QBEInteger &operator >>=(T i);
0363     QBEInteger &operator <<=(T i);
0364     QBEInteger &operator /=(T i);
0365     QBEInteger &operator %=(T i);
0366     QBEInteger &operator |=(T i);
0367     QBEInteger &operator &=(T i);
0368     QBEInteger &operator ^=(T i);
0369     QBEInteger &operator ++();
0370     QBEInteger &operator --();
0371     QBEInteger operator ++(int);
0372     QBEInteger operator --(int);
0373 
0374     static constexpr QBEInteger max();
0375     static constexpr QBEInteger min();
0376 };
0377 #else
0378 
0379 template<typename T>
0380 using QLEInteger = QSpecialInteger<QLittleEndianStorageType<T>>;
0381 
0382 template<typename T>
0383 using QBEInteger = QSpecialInteger<QBigEndianStorageType<T>>;
0384 #endif
0385 template <typename T>
0386 class QTypeInfo<QLEInteger<T> >
0387     : public QTypeInfoMerger<QLEInteger<T>, T> {};
0388 
0389 template <typename T>
0390 class QTypeInfo<QBEInteger<T> >
0391     : public QTypeInfoMerger<QBEInteger<T>, T> {};
0392 
0393 typedef QLEInteger<qint16> qint16_le;
0394 typedef QLEInteger<qint32> qint32_le;
0395 typedef QLEInteger<qint64> qint64_le;
0396 typedef QLEInteger<quint16> quint16_le;
0397 typedef QLEInteger<quint32> quint32_le;
0398 typedef QLEInteger<quint64> quint64_le;
0399 
0400 typedef QBEInteger<qint16> qint16_be;
0401 typedef QBEInteger<qint32> qint32_be;
0402 typedef QBEInteger<qint64> qint64_be;
0403 typedef QBEInteger<quint16> quint16_be;
0404 typedef QBEInteger<quint32> quint32_be;
0405 typedef QBEInteger<quint64> quint64_be;
0406 
0407 QT_END_NAMESPACE
0408 
0409 #endif // QENDIAN_H