diff options
Diffstat (limited to 'src/corelib/global/qendian_p.h')
-rw-r--r-- | src/corelib/global/qendian_p.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/corelib/global/qendian_p.h b/src/corelib/global/qendian_p.h index 609b1a97be..cf4e4af5c4 100644 --- a/src/corelib/global/qendian_p.h +++ b/src/corelib/global/qendian_p.h @@ -131,6 +131,187 @@ using qint32_be_bitfield = QBEIntegerBitfield<int, pos, width>; template<int pos, int width> using quint32_be_bitfield = QBEIntegerBitfield<uint, pos, width>; +enum class QSpecialIntegerBitfieldInitializer {}; +constexpr QSpecialIntegerBitfieldInitializer QSpecialIntegerBitfieldZero{}; + +template<class S> +class QSpecialIntegerStorage +{ +public: + using UnsignedStorageType = std::make_unsigned_t<typename S::StorageType>; + + constexpr QSpecialIntegerStorage() = default; + constexpr QSpecialIntegerStorage(QSpecialIntegerBitfieldInitializer) : val(0) {} + constexpr QSpecialIntegerStorage(UnsignedStorageType initial) : val(initial) {} + + UnsignedStorageType val; +}; + +template<class S, int pos, int width, class T = typename S::StorageType> +class QSpecialIntegerAccessor; + +template<class S, int pos, int width, class T = typename S::StorageType> +class QSpecialIntegerConstAccessor +{ + Q_DISABLE_COPY_MOVE(QSpecialIntegerConstAccessor) +public: + using Storage = const QSpecialIntegerStorage<S>; + using Type = T; + using UnsignedType = std::make_unsigned_t<T>; + + operator Type() const noexcept + { + if constexpr (std::is_signed_v<Type>) { + UnsignedType i = S::fromSpecial(storage->val); + i <<= (sizeof(Type) * 8) - width - pos; + Type t = Type(i); + t >>= (sizeof(Type) * 8) - width; + return t; + } + return (S::fromSpecial(storage->val) & mask()) >> pos; + } + + bool operator!() const noexcept { return !(storage->val & S::toSpecial(mask())); } + + static constexpr UnsignedType mask() noexcept + { + return ((UnsignedType(1) << width) - 1) << pos; + } + +private: + template<class Storage, typename... Accessors> + friend class QSpecialIntegerBitfieldUnion; + friend class QSpecialIntegerAccessor<S, pos, width, T>; + + explicit QSpecialIntegerConstAccessor(Storage *storage) : storage(storage) {} + + friend bool operator==(const QSpecialIntegerConstAccessor<S, pos, width, T> &i, + const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept + { + return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) == 0; + } + + friend bool operator!=(const QSpecialIntegerConstAccessor<S, pos, width, T> &i, + const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept + { + return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) != 0; + } + + Storage *storage; +}; + +template<class S, int pos, int width, class T> +class QSpecialIntegerAccessor +{ + Q_DISABLE_COPY_MOVE(QSpecialIntegerAccessor) +public: + using Const = QSpecialIntegerConstAccessor<S, pos, width, T>; + using Storage = QSpecialIntegerStorage<S>; + using Type = T; + using UnsignedType = std::make_unsigned_t<T>; + + QSpecialIntegerAccessor &operator=(Type t) + { + UnsignedType i = S::fromSpecial(storage->val); + i &= ~Const::mask(); + i |= (UnsignedType(t) << pos) & Const::mask(); + storage->val = S::toSpecial(i); + return *this; + } + + operator Const() { return Const(storage); } + +private: + template<class Storage, typename... Accessors> + friend class QSpecialIntegerBitfieldUnion; + + explicit QSpecialIntegerAccessor(Storage *storage) : storage(storage) {} + + Storage *storage; +}; + +template<class S, typename... Accessors> +class QSpecialIntegerBitfieldUnion +{ +public: + constexpr QSpecialIntegerBitfieldUnion() = default; + constexpr QSpecialIntegerBitfieldUnion(QSpecialIntegerBitfieldInitializer initial) + : storage(initial) + {} + + constexpr QSpecialIntegerBitfieldUnion( + typename QSpecialIntegerStorage<S>::UnsignedStorageType initial) + : storage(initial) + {} + + template<typename A> + void set(typename A::Type value) + { + member<A>() = value; + } + + template<typename A> + typename A::Type get() const + { + return member<A>(); + } + + typename QSpecialIntegerStorage<S>::UnsignedStorageType data() const + { + return storage.val; + } + +private: + template<typename A> + static constexpr bool isAccessor = std::disjunction_v<std::is_same<A, Accessors>...>; + + template<typename A> + A member() + { + static_assert(isAccessor<A>); + return A(&storage); + } + + template<typename A> + typename A::Const member() const + { + static_assert(isAccessor<A>); + return typename A::Const(&storage); + } + + QSpecialIntegerStorage<S> storage; +}; + +template<typename T, typename... Accessors> +using QLEIntegerBitfieldUnion + = QSpecialIntegerBitfieldUnion<QLittleEndianStorageType<T>, Accessors...>; + +template<typename T, typename... Accessors> +using QBEIntegerBitfieldUnion + = QSpecialIntegerBitfieldUnion<QBigEndianStorageType<T>, Accessors...>; + +template<typename... Accessors> +using qint32_le_bitfield_union = QLEIntegerBitfieldUnion<int, Accessors...>; +template<typename... Accessors> +using quint32_le_bitfield_union = QLEIntegerBitfieldUnion<uint, Accessors...>; +template<typename... Accessors> +using qint32_be_bitfield_union = QBEIntegerBitfieldUnion<int, Accessors...>; +template<typename... Accessors> +using quint32_be_bitfield_union = QBEIntegerBitfieldUnion<uint, Accessors...>; + +template<int pos, int width, typename T = int> +using qint32_le_bitfield_member + = QSpecialIntegerAccessor<QLittleEndianStorageType<int>, pos, width, T>; +template<int pos, int width, typename T = uint> +using quint32_le_bitfield_member + = QSpecialIntegerAccessor<QLittleEndianStorageType<uint>, pos, width, T>; +template<int pos, int width, typename T = int> +using qint32_be_bitfield_member + = QSpecialIntegerAccessor<QBigEndianStorageType<int>, pos, width, T>; +template<int pos, int width, typename T = uint> +using quint32_be_bitfield_member + = QSpecialIntegerAccessor<QBigEndianStorageType<uint>, pos, width, T>; + QT_END_NAMESPACE #endif // QENDIAN_P_H |