• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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