1 /* 2 * Copyright (c) 2021 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_VERIFICATION_UTIL_FLAGS_H_ 17 #define PANDA_VERIFICATION_UTIL_FLAGS_H_ 18 19 #include "macros.h" 20 21 #include <cstdint> 22 23 namespace panda::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 bit_mask,const UInt & given_flags)32 ConstBit(UInt bit_mask, const UInt &given_flags) : mask {bit_mask}, flags {given_flags} {}; 33 ConstBit() = delete; 34 ConstBit(const ConstBit &) = delete; 35 ConstBit(ConstBit &&) = delete; 36 ~ConstBit() = default; 37 operator bool() const 38 { 39 return (flags & mask) != 0; 40 } 41 42 protected: 43 const UInt mask; 44 const UInt &flags; 45 }; 46 47 class Bit : public ConstBit { 48 public: Bit(UInt bit_mask,UInt & given_flags)49 Bit(UInt bit_mask, UInt &given_flags) : ConstBit {bit_mask, given_flags} {}; 50 ~Bit() = default; 51 Bit &operator=(bool b) 52 { 53 UInt &proper_flags = const_cast<UInt &>(ConstBit::flags); 54 if (b) { 55 proper_flags |= ConstBit::mask; 56 } else { 57 proper_flags &= ~ConstBit::mask; 58 } 59 return *this; 60 } 61 }; 62 63 template <typename Handler> EnumerateFlags(Handler && handler)64 void EnumerateFlags(Handler &&handler) const 65 { 66 if (ConstBit {mask, flags_} == true) { 67 handler(Flag); 68 } 69 } 70 71 #ifndef NDEBUG 72 ConstBit operator[](Enum f) const 73 { 74 ASSERT(f == Flag); 75 return {mask, flags_}; 76 } 77 78 Bit operator[](Enum f) 79 { 80 ASSERT(f == Flag); 81 return {mask, flags_}; 82 } 83 #else 84 ConstBit operator[](Enum /* unused */) const 85 { 86 return {mask, flags_}; 87 } 88 89 Bit operator[](Enum /* unused */) 90 { 91 return {mask, flags_}; 92 } 93 #endif 94 protected: 95 constexpr static UInt mask = static_cast<UInt>(1); 96 UInt flags_ {0}; 97 }; 98 99 template <typename UInt, typename Enum, Enum Flag, Enum... Rest> 100 class FlagsForEnum<UInt, Enum, Flag, Rest...> : public FlagsForEnum<UInt, Enum, Rest...> { 101 using Base = FlagsForEnum<UInt, Enum, Rest...>; 102 103 public: 104 typename Base::ConstBit operator[](Enum f) const 105 { 106 if (f == Flag) { 107 return {mask, Base::flags_}; 108 } 109 return Base::operator[](f); 110 } 111 112 typename Base::Bit operator[](Enum f) 113 { 114 if (f == Flag) { 115 return {mask, Base::flags_}; 116 } 117 return Base::operator[](f); 118 } 119 120 template <typename Handler> EnumerateFlags(Handler && handler)121 void EnumerateFlags(Handler &&handler) const 122 { 123 if (typename Base::ConstBit {mask, Base::flags_} == true && !handler(Flag)) { 124 return; 125 } 126 Base::template EnumerateFlags<Handler>(std::move(handler)); 127 } 128 129 protected: 130 constexpr static UInt mask = Base::mask << static_cast<UInt>(1); 131 static_assert(mask != 0, "too many flags for UInt size"); 132 }; 133 } // namespace panda::verifier 134 135 #endif // PANDA_VERIFICATION_UTIL_FLAGS_H_ 136