diff options
Diffstat (limited to 'src/common/bit_field.h')
| -rw-r--r-- | src/common/bit_field.h | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 21e07925d..902e668e3 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <limits> | 34 | #include <limits> |
| 35 | #include <type_traits> | 35 | #include <type_traits> |
| 36 | #include "common/common_funcs.h" | 36 | #include "common/common_funcs.h" |
| 37 | #include "common/swap.h" | ||
| 37 | 38 | ||
| 38 | /* | 39 | /* |
| 39 | * Abstract bitfield class | 40 | * Abstract bitfield class |
| @@ -108,15 +109,9 @@ | |||
| 108 | * symptoms. | 109 | * symptoms. |
| 109 | */ | 110 | */ |
| 110 | #pragma pack(1) | 111 | #pragma pack(1) |
| 111 | template <std::size_t Position, std::size_t Bits, typename T> | 112 | template <std::size_t Position, std::size_t Bits, typename T, typename EndianTag = LETag> |
| 112 | struct BitField { | 113 | struct BitField { |
| 113 | private: | 114 | private: |
| 114 | // We hide the copy assigment operator here, because the default copy | ||
| 115 | // assignment would copy the full storage value, rather than just the bits | ||
| 116 | // relevant to this particular bit field. | ||
| 117 | // We don't delete it because we want BitField to be trivially copyable. | ||
| 118 | constexpr BitField& operator=(const BitField&) = default; | ||
| 119 | |||
| 120 | // UnderlyingType is T for non-enum types and the underlying type of T if | 115 | // UnderlyingType is T for non-enum types and the underlying type of T if |
| 121 | // T is an enumeration. Note that T is wrapped within an enable_if in the | 116 | // T is an enumeration. Note that T is wrapped within an enable_if in the |
| 122 | // former case to workaround compile errors which arise when using | 117 | // former case to workaround compile errors which arise when using |
| @@ -127,6 +122,8 @@ private: | |||
| 127 | // We store the value as the unsigned type to avoid undefined behaviour on value shifting | 122 | // We store the value as the unsigned type to avoid undefined behaviour on value shifting |
| 128 | using StorageType = std::make_unsigned_t<UnderlyingType>; | 123 | using StorageType = std::make_unsigned_t<UnderlyingType>; |
| 129 | 124 | ||
| 125 | using StorageTypeWithEndian = typename AddEndian<StorageType, EndianTag>::type; | ||
| 126 | |||
| 130 | public: | 127 | public: |
| 131 | /// Constants to allow limited introspection of fields if needed | 128 | /// Constants to allow limited introspection of fields if needed |
| 132 | static constexpr std::size_t position = Position; | 129 | static constexpr std::size_t position = Position; |
| @@ -163,16 +160,20 @@ public: | |||
| 163 | BitField(T val) = delete; | 160 | BitField(T val) = delete; |
| 164 | BitField& operator=(T val) = delete; | 161 | BitField& operator=(T val) = delete; |
| 165 | 162 | ||
| 166 | // Force default constructor to be created | 163 | constexpr BitField() noexcept = default; |
| 167 | // so that we can use this within unions | 164 | |
| 168 | constexpr BitField() = default; | 165 | constexpr BitField(const BitField&) noexcept = default; |
| 166 | constexpr BitField& operator=(const BitField&) noexcept = default; | ||
| 167 | |||
| 168 | constexpr BitField(BitField&&) noexcept = default; | ||
| 169 | constexpr BitField& operator=(BitField&&) noexcept = default; | ||
| 169 | 170 | ||
| 170 | constexpr FORCE_INLINE operator T() const { | 171 | constexpr FORCE_INLINE operator T() const { |
| 171 | return Value(); | 172 | return Value(); |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | constexpr FORCE_INLINE void Assign(const T& value) { | 175 | constexpr FORCE_INLINE void Assign(const T& value) { |
| 175 | storage = (storage & ~mask) | FormatValue(value); | 176 | storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value); |
| 176 | } | 177 | } |
| 177 | 178 | ||
| 178 | constexpr T Value() const { | 179 | constexpr T Value() const { |
| @@ -184,7 +185,7 @@ public: | |||
| 184 | } | 185 | } |
| 185 | 186 | ||
| 186 | private: | 187 | private: |
| 187 | StorageType storage; | 188 | StorageTypeWithEndian storage; |
| 188 | 189 | ||
| 189 | static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); | 190 | static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); |
| 190 | 191 | ||
| @@ -195,3 +196,6 @@ private: | |||
| 195 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField"); | 196 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField"); |
| 196 | }; | 197 | }; |
| 197 | #pragma pack() | 198 | #pragma pack() |
| 199 | |||
| 200 | template <std::size_t Position, std::size_t Bits, typename T> | ||
| 201 | using BitFieldBE = BitField<Position, Bits, T, BETag>; | ||