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 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; value_(value)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; 107 constexpr EnumBitField(const EnumType& value) noexcept 108 { 109 SetValueFromEnum(value); 110 } 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 } 127 constexpr bool IsSet(const EnumType& bits) const noexcept 128 { 129 return (*this & bits).GetValue() != 0; 130 } 131 constexpr void Set(const EnumType& bits) 132 { 133 *this |= bits; 134 } 135 constexpr void Clear(const EnumType& bits) 136 { 137 value_ &= ~static_cast<BaseValueType>(EnumBitField(bits).GetValue()); 138 } 139 constexpr void Clear() 140 { 141 value_ = {}; 142 } 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> 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 232 constexpr void SetValueFromBase(BaseValueType t) 233 { 234 value_ = (static_cast<BaseValueType>(t >> BitBeginOffset) & BITMASK) << BitBeginOffset; 235 } 236 237 constexpr void SetValueFromEnum(EnumType t) 238 { 239 value_ = (static_cast<BaseValueType>(t) & BITMASK) << BitBeginOffset; 240 } 241 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; 260 constexpr SubEnumBitField(Super s) : Super(s) {} 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 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