Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qendian.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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