1 /** 2 * Copyright (c) 2021-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 PANDA_VERIFIER_UTIL_FLAGS_H_ 17 #define PANDA_VERIFIER_UTIL_FLAGS_H_ 18 19 #include "macros.h" 20 21 #include <cstdint> 22 23 namespace ark::verifier { 24 template <typename UInt, typename Enum, Enum...> 25 class FlagsForEnum; 26 27 template <typename UInt, typename Enum, Enum FLAG> 28 class FlagsForEnum<UInt, Enum, FLAG> { 29 public: 30 class ConstBit { 31 public: ConstBit(UInt bitMask, const UInt &givenFlags)32 ConstBit(UInt bitMask, const UInt &givenFlags) : mask_ {bitMask}, flags_ {givenFlags} {}; 33 ConstBit() = delete; 34 ~ConstBit() = default; 35 36 NO_COPY_SEMANTIC(ConstBit); 37 NO_MOVE_SEMANTIC(ConstBit); 38 39 // NOLINTNEXTLINE(google-explicit-constructor) operator bool() const40 operator bool() const 41 { 42 return (flags_ & mask_) != 0; 43 } 44 45 protected: 46 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 47 const UInt mask_; 48 const UInt &flags_; 49 // NOLINTEND(misc-non-private-member-variables-in-classes) 50 }; 51 52 class Bit : public ConstBit { 53 public: Bit(UInt bitMask, UInt &givenFlags)54 Bit(UInt bitMask, UInt &givenFlags) : ConstBit {bitMask, givenFlags} {}; 55 ~Bit() = default; 56 NO_COPY_SEMANTIC(Bit); 57 NO_MOVE_SEMANTIC(Bit); 58 operator =(bool b)59 Bit &operator=(bool b) 60 { 61 UInt &properFlags = const_cast<UInt &>(ConstBit::flags_); 62 if (b) { 63 properFlags |= ConstBit::mask_; 64 } else { 65 properFlags &= ~ConstBit::mask_; 66 } 67 return *this; 68 } 69 }; 70 71 template <typename Handler> EnumerateFlags(Handler &&handler) const72 void EnumerateFlags(Handler &&handler) const 73 { 74 if (ConstBit {MASK, flags_}) { 75 handler(FLAG); 76 } 77 } 78 79 #ifndef NDEBUG operator [](Enum f) const80 ConstBit operator[](Enum f) const 81 { 82 ASSERT(f == FLAG); 83 return {MASK, flags_}; 84 } 85 operator [](Enum f)86 Bit operator[](Enum f) 87 { 88 ASSERT(f == FLAG); 89 return {MASK, flags_}; 90 } 91 #else operator [](Enum ) const92 ConstBit operator[](Enum /* unused */) const 93 { 94 return {MASK, flags_}; 95 } 96 operator [](Enum )97 Bit operator[](Enum /* unused */) 98 { 99 return {MASK, flags_}; 100 } 101 #endif 102 103 protected: 104 constexpr static UInt MASK = static_cast<UInt>(1); 105 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 106 UInt flags_ {0}; 107 }; 108 109 template <typename UInt, typename Enum, Enum FLAG, Enum... REST> 110 class FlagsForEnum<UInt, Enum, FLAG, REST...> : public FlagsForEnum<UInt, Enum, REST...> { 111 using Base = FlagsForEnum<UInt, Enum, REST...>; 112 113 public: operator [](Enum f) const114 typename Base::ConstBit operator[](Enum f) const 115 { 116 if (f == FLAG) { 117 return {MASK, Base::flags_}; 118 } 119 return Base::operator[](f); 120 } 121 operator [](Enum f)122 typename Base::Bit operator[](Enum f) 123 { 124 if (f == FLAG) { 125 return {MASK, Base::flags_}; 126 } 127 return Base::operator[](f); 128 } 129 130 template <typename Handler> EnumerateFlags(Handler &&handler) const131 void EnumerateFlags(Handler &&handler) const 132 { 133 if (typename Base::ConstBit {MASK, Base::flags_} && !handler(FLAG)) { 134 return; 135 } 136 Base::template EnumerateFlags<Handler>(std::forward<Handler>(handler)); 137 } 138 139 protected: 140 constexpr static UInt MASK = Base::MASK << static_cast<UInt>(1); 141 static_assert(MASK != 0, "too many flags for UInt size"); 142 }; 143 } // namespace ark::verifier 144 145 #endif // PANDA_VERIFIER_UTIL_FLAGS_H_ 146