4d22b66c952b6035687fd1fd8bce5b26e02a2185
[platform/upstream/connectedhomeip.git] / src / lib / support / BitFlags.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2013-2017 Nest Labs, Inc.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *      This file defines functions for manipulating Boolean flags in
22  *      a bitfield.
23  *
24  */
25
26 #pragma once
27
28 #include <stdint.h>
29
30 #include <utility>
31
32 namespace chip {
33
34 /**
35  * Stores bit flags in a type safe manner.
36  *
37  * @tparam StorageType is the underlying storage type (like uint16_t, uint32_t etc.)
38  * @tparam FlagsEnum is the typesafe flags setting
39  */
40 template <typename StorageType, typename FlagsEnum>
41 class BitFlags
42 {
43 public:
44     static_assert(sizeof(StorageType) >= sizeof(FlagsEnum), "All flags should fit in the storage type");
45
46     BitFlags() {}
47     BitFlags(const BitFlags &) = default;
48     BitFlags & operator=(const BitFlags &) = default;
49
50     explicit BitFlags(FlagsEnum v) { Set(v); }
51
52     explicit BitFlags(StorageType value) { SetRaw(value); }
53
54     BitFlags & Set(FlagsEnum v)
55     {
56         mValue = static_cast<StorageType>(mValue | static_cast<StorageType>(v));
57         return *this;
58     }
59
60     BitFlags & Clear(FlagsEnum v)
61     {
62         mValue &= static_cast<StorageType>(~static_cast<StorageType>(v));
63         return *this;
64     }
65
66     BitFlags & Set(FlagsEnum v, bool isSet) { return isSet ? Set(v) : Clear(v); }
67
68     bool Has(FlagsEnum v) const { return (mValue & static_cast<StorageType>(v)) != 0; }
69
70     bool Has(StorageType other) const { return (mValue & other) == other; }
71
72     BitFlags & Set(const BitFlags & other)
73     {
74         mValue |= other.mValue;
75         return *this;
76     }
77
78     StorageType Raw() const { return mValue; }
79     BitFlags & SetRaw(StorageType value)
80     {
81         mValue = value;
82         return *this;
83     }
84
85     /** Check that no flags outside the arguments are set.*/
86     template <typename... Args>
87     bool HasOnly(Args &&... args) const
88     {
89         return IsZeroAfterClearing(mValue, std::forward<Args>(args)...);
90     }
91
92 private:
93     StorageType mValue = 0;
94
95     template <typename... Args>
96     static bool IsZeroAfterClearing(StorageType value, FlagsEnum flagToClear, Args &&... args)
97     {
98         value &= static_cast<StorageType>(~static_cast<StorageType>(flagToClear));
99         return IsZeroAfterClearing(value, std::forward<Args>(args)...);
100     }
101
102     static bool IsZeroAfterClearing(StorageType value) { return value == 0; }
103 };
104
105 /**
106  * @deprecated Use typesafe BitFlags class instead.
107  */
108 template <typename FlagsT, typename FlagT>
109 inline bool GetFlag(const FlagsT & inFlags, const FlagT inFlag)
110 {
111     return (inFlags & static_cast<FlagsT>(inFlag)) != 0;
112 }
113
114 /**
115  * @deprecated Use typesafe BitFlags class instead.
116  */
117 template <typename FlagsT, typename FlagT>
118 inline void ClearFlag(FlagsT & inFlags, const FlagT inFlag)
119 {
120     inFlags &= static_cast<FlagsT>(~static_cast<FlagsT>(inFlag));
121 }
122
123 /**
124  * @deprecated Use typesafe BitFlags class instead.
125  */
126 template <typename FlagsT, typename FlagT>
127 inline void SetFlag(FlagsT & inFlags, const FlagT inFlag)
128 {
129     inFlags = static_cast<FlagsT>(inFlags | static_cast<FlagsT>(inFlag));
130 }
131
132 /**
133  * @deprecated Use typesafe BitFlags class instead.
134  */
135 template <typename FlagsT, typename FlagT>
136 inline void SetFlag(FlagsT & inFlags, const FlagT inFlag, const bool inValue)
137 {
138     if (inValue)
139     {
140         SetFlag(inFlags, inFlag);
141     }
142     else
143     {
144         ClearFlag(inFlags, inFlag);
145     }
146 }
147
148 } // namespace chip