File indexing completed on 2026-07-24 09:20:29
0001
0002
0003
0004
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
0019 #include <stdlib.h>
0020 #include <string.h>
0021
0022 #ifdef min
0023 #undef min
0024 #undef max
0025 #endif
0026
0027 QT_BEGIN_NAMESPACE
0028
0029
0030
0031
0032
0033
0034
0035 template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
0036 {
0037
0038
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
0062
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
0099
0100
0101
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
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
0127 template<typename Float>
0128 Float qbswapFloatHelper(Float source)
0129 {
0130
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
0153
0154
0155
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
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
0218
0219
0220
0221
0222
0223
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
0236
0237
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