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_SATURATED_ENUM_H_ 17 #define PANDA_VERIFIER_UTIL_SATURATED_ENUM_H_ 18 19 #include "macros.h" 20 21 #include <utility> 22 23 namespace ark::verifier { 24 25 /* 26 NOTE: default value? 27 possible options: 28 1. initial value UNDEFINED and any op will lead to fatal error, add constructors etc for proper initialization 29 pros: more safety and robustness to programmer errors, cons: more code, more complexity, etc 30 2. initial value is least significant one. 31 pros: simplicity, cons: less robust, does not help to detect logic errors in program 32 */ 33 34 template <typename Enum, Enum...> 35 class SaturatedEnum; 36 37 template <typename Enum, Enum E> 38 class SaturatedEnum<Enum, E> { 39 public: 40 SaturatedEnum &operator=(Enum e) 41 { 42 value_ = e; 43 return *this; 44 } 45 46 SaturatedEnum &operator|=(Enum e) 47 { 48 Set(e); 49 return *this; 50 } 51 52 bool operator[](Enum e) const 53 { 54 return Check(e, false); 55 } 56 57 // NOLINTNEXTLINE(google-explicit-constructor) Enum()58 operator Enum() const 59 { 60 return value_; 61 } 62 63 template <typename Handler> EnumerateValues(Handler && handler)64 void EnumerateValues(Handler &&handler) const 65 { 66 Enumerate(std::forward<Handler>(handler), false); 67 } 68 69 protected: 70 #ifndef NDEBUG Check(Enum e,bool prevSet)71 bool Check(Enum e, bool prevSet) const 72 #else 73 bool Check([[maybe_unused]] Enum e, bool prevSet) const 74 #endif 75 { 76 // to catch missed enum members 77 ASSERT(e == E); 78 return prevSet || value_ == E; 79 } 80 Set(Enum e)81 void Set(Enum e) 82 { 83 ASSERT(e == E); 84 value_ = e; 85 } 86 87 template <typename Handler> Enumerate(Handler && handler,bool prevSet)88 void Enumerate(Handler &&handler, bool prevSet) const 89 { 90 prevSet = prevSet || (value_ == E); 91 if (prevSet) { 92 handler(E); 93 } 94 } 95 96 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 97 Enum value_ {E}; 98 }; 99 100 template <typename Enum, Enum E, Enum... REST> 101 class SaturatedEnum<Enum, E, REST...> : public SaturatedEnum<Enum, REST...> { 102 using Base = SaturatedEnum<Enum, REST...>; 103 104 public: 105 SaturatedEnum &operator=(Enum e) 106 { 107 Base::operator=(e); 108 return *this; 109 } 110 111 SaturatedEnum &operator|=(Enum e) 112 { 113 Set(e); 114 return *this; 115 } 116 117 bool operator[](Enum e) const 118 { 119 return Check(e, false); 120 } 121 122 // NOLINTNEXTLINE(google-explicit-constructor) Enum()123 operator Enum() const 124 { 125 return Base::value_; 126 } 127 128 template <typename Handler> EnumerateValues(Handler && handler)129 void EnumerateValues(Handler &&handler) const 130 { 131 Enumerate(std::forward<Handler>(handler), false); 132 } 133 134 protected: Check(Enum e,bool prevSet)135 bool Check(Enum e, bool prevSet) const 136 { 137 prevSet = prevSet || (Base::value_ == E); 138 if (e == E) { 139 return prevSet; 140 } 141 return Base::Check(e, prevSet); 142 } 143 Set(Enum e)144 void Set(Enum e) 145 { 146 if (Base::value_ == E) { 147 return; 148 } 149 if (e == E) { 150 Base::operator=(e); 151 return; 152 } 153 Base::Set(e); 154 } 155 156 template <typename Handler> Enumerate(Handler && handler,bool prevSet)157 void Enumerate(Handler &&handler, bool prevSet) const 158 { 159 prevSet = prevSet || (Base::value_ == E); 160 if (prevSet && !handler(E)) { 161 return; 162 } 163 Base::template Enumerate<Handler>(std::forward<Handler>(handler), prevSet); 164 } 165 }; 166 167 } // namespace ark::verifier 168 169 #endif // PANDA_VERIFIER_UTIL_SATURATED_ENUM_H_ 170