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