summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2017-05-26 17:59:57 +0200
committerGitHub <noreply@github.com>2017-05-26 17:59:57 +0200
commit61decd84cc5308bded75eae62c3247a66b3698d8 (patch)
treebbe05121af1a971bc295cb81baeea63f8c54f407 /src/common
parentMerge pull request #2697 from wwylele/proctex (diff)
parentFS: Remove unused result definition (diff)
downloadyuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar.gz
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar.bz2
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar.lz
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar.xz
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.tar.zst
yuzu-61decd84cc5308bded75eae62c3247a66b3698d8.zip
Diffstat (limited to 'src/common')
-rw-r--r--src/common/bit_field.h65
1 files changed, 42 insertions, 23 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 030f7caeb..0cc0a1be0 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -108,7 +108,7 @@
* symptoms.
*/
#pragma pack(1)
-template <std::size_t position, std::size_t bits, typename T>
+template <std::size_t Position, std::size_t Bits, typename T>
struct BitField {
private:
// We hide the copy assigment operator here, because the default copy
@@ -117,7 +117,45 @@ private:
// We don't delete it because we want BitField to be trivially copyable.
BitField& operator=(const BitField&) = default;
+ // StorageType is T for non-enum types and the underlying type of T if
+ // T is an enumeration. Note that T is wrapped within an enable_if in the
+ // former case to workaround compile errors which arise when using
+ // std::underlying_type<T>::type directly.
+ using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>,
+ std::enable_if<true, T>>::type;
+
+ // Unsigned version of StorageType
+ using StorageTypeU = std::make_unsigned_t<StorageType>;
+
public:
+ /// Constants to allow limited introspection of fields if needed
+ static constexpr size_t position = Position;
+ static constexpr size_t bits = Bits;
+ static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position;
+
+ /**
+ * Formats a value by masking and shifting it according to the field parameters. A value
+ * containing several bitfields can be assembled by formatting each of their values and ORing
+ * the results together.
+ */
+ static constexpr FORCE_INLINE StorageType FormatValue(const T& value) {
+ return ((StorageType)value << position) & mask;
+ }
+
+ /**
+ * Extracts a value from the passed storage. In most situations prefer use the member functions
+ * (such as Value() or operator T), but this can be used to extract a value from a bitfield
+ * union in a constexpr context.
+ */
+ static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) {
+ if (std::numeric_limits<T>::is_signed) {
+ std::size_t shift = 8 * sizeof(T) - bits;
+ return (T)((storage << (shift - position)) >> shift);
+ } else {
+ return (T)((storage & mask) >> position);
+ }
+ }
+
// This constructor and assignment operator might be considered ambiguous:
// Would they initialize the storage or just the bitfield?
// Hence, delete them. Use the Assign method to set bitfield values!
@@ -126,23 +164,18 @@ public:
// Force default constructor to be created
// so that we can use this within unions
- BitField() = default;
+ constexpr BitField() = default;
FORCE_INLINE operator T() const {
return Value();
}
FORCE_INLINE void Assign(const T& value) {
- storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask());
+ storage = (storage & ~mask) | FormatValue(value);
}
FORCE_INLINE T Value() const {
- if (std::numeric_limits<T>::is_signed) {
- std::size_t shift = 8 * sizeof(T) - bits;
- return (T)((storage << (shift - position)) >> shift);
- } else {
- return (T)((storage & GetMask()) >> position);
- }
+ return ExtractValue(storage);
}
// TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
@@ -151,20 +184,6 @@ public:
}
private:
- // StorageType is T for non-enum types and the underlying type of T if
- // T is an enumeration. Note that T is wrapped within an enable_if in the
- // former case to workaround compile errors which arise when using
- // std::underlying_type<T>::type directly.
- typedef typename std::conditional<std::is_enum<T>::value, std::underlying_type<T>,
- std::enable_if<true, T>>::type::type StorageType;
-
- // Unsigned version of StorageType
- typedef typename std::make_unsigned<StorageType>::type StorageTypeU;
-
- FORCE_INLINE StorageType GetMask() const {
- return (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position;
- }
-
StorageType storage;
static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range");