Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common/bitfield.h
4223 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "types.h"
7
8
#include <type_traits>
9
10
template<typename BackingDataType, typename DataType, unsigned BitIndex, unsigned BitCount>
11
struct BitField
12
{
13
static_assert(!std::is_same_v<DataType, bool> || BitCount == 1, "Boolean bitfields should only be 1 bit");
14
15
ALWAYS_INLINE constexpr BackingDataType GetMask() const
16
{
17
return ((static_cast<BackingDataType>(~0)) >> (8 * sizeof(BackingDataType) - BitCount)) << BitIndex;
18
}
19
20
ALWAYS_INLINE constexpr operator DataType() const { return GetValue(); }
21
22
ALWAYS_INLINE constexpr BitField& operator=(DataType value)
23
{
24
SetValue(value);
25
return *this;
26
}
27
28
ALWAYS_INLINE constexpr DataType operator++()
29
{
30
DataType value = GetValue() + 1;
31
SetValue(value);
32
return GetValue();
33
}
34
35
ALWAYS_INLINE constexpr DataType operator++(int)
36
{
37
DataType value = GetValue();
38
SetValue(value + 1);
39
return value;
40
}
41
42
ALWAYS_INLINE constexpr DataType operator--()
43
{
44
DataType value = GetValue() - 1;
45
SetValue(value);
46
return GetValue();
47
}
48
49
ALWAYS_INLINE constexpr DataType operator--(int)
50
{
51
DataType value = GetValue();
52
SetValue(value - 1);
53
return value;
54
}
55
56
ALWAYS_INLINE constexpr BitField& operator+=(DataType rhs)
57
{
58
SetValue(GetValue() + rhs);
59
return *this;
60
}
61
62
ALWAYS_INLINE constexpr BitField& operator-=(DataType rhs)
63
{
64
SetValue(GetValue() - rhs);
65
return *this;
66
}
67
68
ALWAYS_INLINE constexpr BitField& operator*=(DataType rhs)
69
{
70
SetValue(GetValue() * rhs);
71
return *this;
72
}
73
74
ALWAYS_INLINE constexpr BitField& operator/=(DataType rhs)
75
{
76
SetValue(GetValue() / rhs);
77
return *this;
78
}
79
80
ALWAYS_INLINE constexpr BitField& operator&=(DataType rhs)
81
{
82
SetValue(GetValue() & rhs);
83
return *this;
84
}
85
86
ALWAYS_INLINE constexpr BitField& operator|=(DataType rhs)
87
{
88
SetValue(GetValue() | rhs);
89
return *this;
90
}
91
92
ALWAYS_INLINE constexpr BitField& operator^=(DataType rhs)
93
{
94
SetValue(GetValue() ^ rhs);
95
return *this;
96
}
97
98
ALWAYS_INLINE constexpr BitField& operator<<=(DataType rhs)
99
{
100
SetValue(GetValue() << rhs);
101
return *this;
102
}
103
104
ALWAYS_INLINE constexpr BitField& operator>>=(DataType rhs)
105
{
106
SetValue(GetValue() >> rhs);
107
return *this;
108
}
109
110
ALWAYS_INLINE constexpr DataType GetValue() const
111
{
112
if constexpr (std::is_same_v<DataType, bool>)
113
{
114
return static_cast<DataType>(!!((data & GetMask()) >> BitIndex));
115
}
116
else if constexpr (std::is_signed_v<DataType>)
117
{
118
constexpr int shift = 8 * sizeof(DataType) - BitCount;
119
return (static_cast<DataType>(data >> BitIndex) << shift) >> shift;
120
}
121
else
122
{
123
return static_cast<DataType>((data & GetMask()) >> BitIndex);
124
}
125
}
126
127
ALWAYS_INLINE constexpr void SetValue(DataType value)
128
{
129
data = (data & ~GetMask()) | ((static_cast<BackingDataType>(value) << BitIndex) & GetMask());
130
}
131
132
BackingDataType data;
133
};
134
135