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