1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef META_BASE_BIT_FIELD_H
17 #define META_BASE_BIT_FIELD_H
18
19 #include <stdint.h>
20
21 #include <base/containers/type_traits.h>
22
23 #include <meta/base/namespace.h>
24
META_BEGIN_NAMESPACE()25 META_BEGIN_NAMESPACE()
26
27 /**
28 * @brief The BitField class encapsulates a bit field value.
29 */
30 class BitField {
31 public:
32 using BaseValueType = uint64_t;
33
34 constexpr BitField() noexcept = default;
35 constexpr BitField(const BaseValueType& value) noexcept : value_(value) {}
36 constexpr bool operator==(const BitField& other) const noexcept
37 {
38 return value_ == other.value_;
39 }
40 constexpr bool operator!=(const BitField& other) const noexcept
41 {
42 return !operator==(other);
43 }
44 constexpr BitField& operator|=(BaseValueType value) noexcept
45 {
46 value_ |= value;
47 return *this;
48 }
49 constexpr BitField operator|(BaseValueType value) const noexcept
50 {
51 return BitField(value_ | value);
52 }
53 constexpr BitField& operator&=(BaseValueType value) noexcept
54 {
55 value_ &= value;
56 return *this;
57 }
58 constexpr BitField operator&(BaseValueType value) const noexcept
59 {
60 return BitField(value_ & value);
61 }
62 constexpr BitField& operator^=(BaseValueType value) noexcept
63 {
64 value_ ^= value;
65 return *this;
66 }
67 constexpr BitField operator^(BaseValueType value) const noexcept
68 {
69 return BitField(value_ ^ value);
70 }
71 constexpr BitField operator~() const noexcept
72 {
73 return BitField(~value_);
74 }
75 explicit constexpr operator bool() const noexcept
76 {
77 return value_ != 0;
78 }
79 constexpr BaseValueType GetValue() const noexcept
80 {
81 return value_;
82 }
83
84 protected:
85 BaseValueType value_ {};
86 };
87
88 /**
89 * @brief The EnumBitField class is a wrapper for a bit flag enum type, allowing
90 * the usage of binary operations with the enum flags as if they were regular integers.
91 */
92 template<class EnumType, class ValueType = BASE_NS::underlying_type_t<EnumType>, size_t BitBeginOffset = 0,
93 size_t BitCount = sizeof(ValueType) * 8>
94 class EnumBitField : public BitField {
95 static_assert(BASE_NS::is_integral_v<ValueType>, "EnumBitField value type must be integral");
96 static_assert(BitBeginOffset < sizeof(ValueType) * 8, "too big begin offset");
97
98 public:
99 constexpr static size_t BEGIN_OFFSET = BitBeginOffset;
100
101 using BaseValueType = BitField::BaseValueType;
102
103 ~EnumBitField() = default;
104 constexpr EnumBitField() noexcept = default;
105 constexpr EnumBitField(EnumBitField&& other) noexcept = default;
106 constexpr EnumBitField(const EnumBitField& other) noexcept = default;
EnumBitField(const EnumType & value)107 constexpr EnumBitField(const EnumType& value) noexcept
108 {
109 SetValueFromEnum(value);
110 }
EnumBitField(const BaseValueType & value)111 constexpr EnumBitField(const BaseValueType& value) noexcept
112 {
113 SetValueFromBase(value);
114 }
115 constexpr EnumBitField& operator=(const EnumBitField& other) noexcept = default;
116 constexpr EnumBitField& operator=(EnumBitField&& other) noexcept = default;
117 constexpr EnumBitField& operator=(EnumType value) noexcept
118 {
119 SetValueFromEnum(value);
120 return *this;
121 }
122 constexpr EnumBitField& operator=(ValueType value) noexcept
123 {
124 value_ = value;
125 return *this;
126 }
IsSet(const EnumType & bits)127 constexpr bool IsSet(const EnumType& bits) const noexcept
128 {
129 return (*this & bits).GetValue() != 0;
130 }
Set(const EnumType & bits)131 constexpr void Set(const EnumType& bits)
132 {
133 *this |= bits;
134 }
Clear(const EnumType & bits)135 constexpr void Clear(const EnumType& bits)
136 {
137 value_ &= ~static_cast<BaseValueType>(EnumBitField(bits).GetValue());
138 }
Clear()139 constexpr void Clear()
140 {
141 value_ = {};
142 }
EnumType()143 constexpr operator EnumType() const noexcept
144 {
145 return static_cast<EnumType>(GetEnumValue());
146 }
147 constexpr bool operator==(EnumType value) const noexcept
148 {
149 return this->BitField::operator==(EnumBitField(value));
150 }
151 constexpr bool operator!=(EnumType value) const noexcept
152 {
153 return !operator==(value);
154 }
155 /** | operator */
156 constexpr EnumBitField& operator|=(const EnumBitField& other) noexcept
157 {
158 BitField::operator|=(other.value_);
159 return *this;
160 }
161 constexpr EnumBitField& operator|=(EnumType value) noexcept
162 {
163 BitField::operator|=(EnumBitField(value).GetValue());
164 return *this;
165 }
166 constexpr EnumBitField operator|(const EnumBitField& other) const noexcept
167 {
168 return EnumBitField(*this).operator|=(other);
169 }
170 constexpr EnumBitField operator|(EnumType value) const noexcept
171 {
172 return EnumBitField(*this).operator|=(value);
173 }
174 /** & operator */
175 constexpr EnumBitField& operator&=(const EnumBitField& other) noexcept
176 {
177 BitField::operator&=(other.value_);
178 return *this;
179 }
180 constexpr EnumBitField& operator&=(EnumType value) noexcept
181 {
182 BitField::operator&=(EnumBitField(value).GetValue());
183 return *this;
184 }
185 constexpr EnumBitField operator&(const EnumBitField& other) const noexcept
186 {
187 return EnumBitField(*this).operator&=(other);
188 }
189 constexpr EnumBitField operator&(EnumType value) const noexcept
190 {
191 return EnumBitField(*this).operator&=(value);
192 }
193 /** ^ operator */
194 constexpr EnumBitField& operator^=(const EnumBitField& other) noexcept
195 {
196 BitField::operator^=(other.value_);
197 return *this;
198 }
199 constexpr EnumBitField& operator^=(EnumType value) noexcept
200 {
201 BitField::operator^=(EnumBitField(value).GetValue());
202 return *this;
203 }
204 constexpr EnumBitField operator^(const EnumBitField& other) const noexcept
205 {
206 return EnumBitField(*this).operator^=(other);
207 }
208 constexpr EnumBitField operator^(EnumType value) const noexcept
209 {
210 return EnumBitField(*this).operator^=(value);
211 }
212 /** ~ operator */
213 constexpr EnumBitField operator~() const noexcept
214 {
215 return EnumBitField(static_cast<EnumType>(~GetEnumValue()));
216 }
217
218 template<class SubEnumType, size_t SubBitBeginOffset, size_t SubBitCount>
SetSubBits(EnumBitField<SubEnumType,ValueType,SubBitBeginOffset,SubBitCount> sub)219 EnumBitField& SetSubBits(EnumBitField<SubEnumType, ValueType, SubBitBeginOffset, SubBitCount> sub)
220 {
221 EnumBitField<SubEnumType, ValueType, SubBitBeginOffset, SubBitCount> empty;
222 auto bits = ~empty;
223 EnumBitField mask = bits.GetValue();
224 value_ &= ~mask.value_;
225 value_ |= sub.GetValue();
226 return *this;
227 }
228
229 private:
230 constexpr static BaseValueType BITMASK = BaseValueType(-1) >> (sizeof(ValueType) * 8 - BitCount);
231
SetValueFromBase(BaseValueType t)232 constexpr void SetValueFromBase(BaseValueType t)
233 {
234 value_ = (static_cast<BaseValueType>(t >> BitBeginOffset) & BITMASK) << BitBeginOffset;
235 }
236
SetValueFromEnum(EnumType t)237 constexpr void SetValueFromEnum(EnumType t)
238 {
239 value_ = (static_cast<BaseValueType>(t) & BITMASK) << BitBeginOffset;
240 }
241
GetEnumValue()242 constexpr BaseValueType GetEnumValue() const
243 {
244 return (value_ >> BitBeginOffset) & BITMASK;
245 }
246 };
247
248 /**
249 * @brief Converts enum values to start from bit offset to be used as sub-EnumBitField
250 */
251 template<class EnumType, class TopEnumBitField, size_t Offset, size_t Count>
252 class SubEnumBitField : public EnumBitField<EnumType, typename TopEnumBitField::BaseValueType, Offset, Count> {
253 using Super = EnumBitField<EnumType, typename TopEnumBitField::BaseValueType, Offset, Count>;
254 static_assert(
255 Offset + Count < sizeof(typename TopEnumBitField::BaseValueType) * 8, // 8 : size
256 "invalid bit offset and/or count");
257
258 public:
259 using Super::Super;
SubEnumBitField(Super s)260 constexpr SubEnumBitField(Super s) : Super(s) {}
SubEnumBitField(TopEnumBitField e)261 constexpr SubEnumBitField(TopEnumBitField e) : Super(e.GetValue()) {}
262
263 constexpr SubEnumBitField(const SubEnumBitField&) = default;
264 constexpr SubEnumBitField(SubEnumBitField&&) = default;
265 constexpr SubEnumBitField& operator=(const SubEnumBitField&) = default;
266 constexpr SubEnumBitField& operator=(SubEnumBitField&&) = default;
267 ~SubEnumBitField() = default;
268
TopEnumBitField()269 constexpr operator TopEnumBitField() const
270 {
271 return TopEnumBitField(this->GetValue());
272 }
273 };
274
275 META_END_NAMESPACE()
276
277 #endif // META_BASE_BIT_FIELD_H
278