• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 panda::verifier {
24 
25 /*
26  TODO: 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 
Enum()57     operator Enum() const
58     {
59         return value_;
60     }
61 
62     template <typename Handler>
EnumerateValues(Handler && handler)63     void EnumerateValues(Handler &&handler) const
64     {
65         Enumerate(std::move(handler), false);
66     }
67 
68 protected:
69 #ifndef NDEBUG
Check(Enum e,bool prev_set)70     bool Check(Enum e, bool prev_set) const
71 #else
72     bool Check([[maybe_unused]] Enum e, bool prev_set) const
73 #endif
74     {
75         // to catch missed enum members
76         ASSERT(e == E);
77         return prev_set || value_ == E;
78     }
79 
Set(Enum e)80     void Set(Enum e)
81     {
82         ASSERT(e == E);
83         value_ = e;
84     }
85 
86     template <typename Handler>
Enumerate(Handler && handler,bool prev_set)87     void Enumerate(Handler &&handler, bool prev_set) const
88     {
89         prev_set = prev_set || (value_ == E);
90         if (prev_set) {
91             handler(E);
92         }
93     }
94 
95     Enum value_ {E};
96 };
97 
98 template <typename Enum, Enum E, Enum... Rest>
99 class SaturatedEnum<Enum, E, Rest...> : public SaturatedEnum<Enum, Rest...> {
100     using Base = SaturatedEnum<Enum, Rest...>;
101 
102 public:
103     SaturatedEnum &operator=(Enum e)
104     {
105         Base::operator=(e);
106         return *this;
107     }
108 
109     SaturatedEnum &operator|=(Enum e)
110     {
111         Set(e);
112         return *this;
113     }
114 
115     bool operator[](Enum e) const
116     {
117         return Check(e, false);
118     }
119 
Enum()120     operator Enum() const
121     {
122         return Base::value_;
123     }
124 
125     template <typename Handler>
EnumerateValues(Handler && handler)126     void EnumerateValues(Handler &&handler) const
127     {
128         Enumerate(std::move(handler), false);
129     }
130 
131 protected:
Check(Enum e,bool prev_set)132     bool Check(Enum e, bool prev_set) const
133     {
134         prev_set = prev_set || (Base::value_ == E);
135         if (e == E) {
136             return prev_set;
137         }
138         return Base::Check(e, prev_set);
139     }
140 
Set(Enum e)141     void Set(Enum e)
142     {
143         if (Base::value_ == E) {
144             return;
145         }
146         if (e == E) {
147             Base::operator=(e);
148             return;
149         }
150         Base::Set(e);
151     }
152 
153     template <typename Handler>
Enumerate(Handler && handler,bool prev_set)154     void Enumerate(Handler &&handler, bool prev_set) const
155     {
156         prev_set = prev_set || (Base::value_ == E);
157         if (prev_set && !handler(E)) {
158             return;
159         }
160         Base::template Enumerate<Handler>(std::move(handler), prev_set);
161     }
162 };
163 
164 }  // namespace panda::verifier
165 
166 #endif  //! PANDA_VERIFIER_UTIL_SATURATED_ENUM_H__
167