3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * This file defines functions for manipulating Boolean flags in
30 #include <type_traits>
36 * Stores bit flags in a type safe manner.
38 * @tparam FlagsEnum is an `enum` or (preferably) `enum class` type.
39 * @tparam StorageType is the underlying storage type (like uint16_t, uint32_t etc.)
40 * and defaults to the underlying storage type of `FlagsEnum`.
42 template <typename FlagsEnum, typename StorageType = typename std::underlying_type_t<FlagsEnum>>
46 static_assert(sizeof(StorageType) >= sizeof(FlagsEnum), "All flags should fit in the storage type");
47 using IntegerType = StorageType;
49 BitFlags() : mValue(0) {}
50 BitFlags(const BitFlags & other) = default;
51 BitFlags & operator=(const BitFlags &) = default;
53 explicit BitFlags(FlagsEnum value) : mValue(static_cast<IntegerType>(value)) {}
54 explicit BitFlags(IntegerType value) : mValue(value) {}
56 template <typename... Args>
57 BitFlags(FlagsEnum flag, Args &&... args) : mValue(Or(flag, std::forward<Args>(args)...))
60 template <typename... Args>
61 BitFlags(const BitFlags<FlagsEnum> & flags, Args &&... args) : mValue(Or(flags, std::forward<Args>(args)...))
64 template <typename... Args>
65 BitFlags(IntegerType value, Args &&... args) : mValue(value | Or(std::forward<Args>(args)...))
71 * @param other Flag(s) to set. Any flags not set in @a other are unaffected.
73 BitFlags & Set(const BitFlags & other)
75 mValue |= other.mValue;
82 * @param flag Typed flag(s) to set. Any flags not in @a v are unaffected.
84 BitFlags & Set(FlagsEnum flag)
86 mValue |= static_cast<IntegerType>(flag);
91 * Set or clear flag(s).
93 * @param flag Typed flag(s) to set or clear. Any flags not in @a flag are unaffected.
94 * @param isSet If true, set the flag; if false, clear it.
96 BitFlags & Set(FlagsEnum flag, bool isSet) { return isSet ? Set(flag) : Clear(flag); }
101 * @param other Typed flag(s) to clear. Any flags not in @a other are unaffected.
103 BitFlags & Clear(const BitFlags & other)
105 mValue &= ~other.mValue;
112 * @param flag Typed flag(s) to clear. Any flags not in @a flag are unaffected.
114 BitFlags & Clear(FlagsEnum flag)
116 mValue &= static_cast<IntegerType>(~static_cast<IntegerType>(flag));
123 BitFlags & ClearAll()
130 * Check whether flag(s) are set.
132 * @param flag Flag(s) to test.
133 * @returns True if any flag in @a flag is set, otherwise false.
135 bool Has(FlagsEnum flag) const { return (mValue & static_cast<IntegerType>(flag)) != 0; }
138 * Check that no flags outside the arguments are set.
140 * @param args Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
141 * @returns True if no flag is set other than those passed.
142 * False if any flag is set other than those passed.
144 * @note Flags passed need not be set; this test only requires that no *other* flags be set.
146 template <typename... Args>
147 bool HasOnly(Args &&... args) const
149 return (mValue & Or(std::forward<Args>(args)...)) == mValue;
153 * Check that all given flags are set.
155 * @param args Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
156 * @returns True if all given flags are set.
157 * False if any given flag is not set.
159 template <typename... Args>
160 bool HasAll(Args &&... args) const
162 const IntegerType all = Or(std::forward<Args>(args)...);
163 return (mValue & all) == all;
167 * Check that at least one of the given flags is set.
169 * @param args Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
170 * @returns True if all given flags are set.
171 * False if any given flag is not set.
173 template <typename... Args>
174 bool HasAny(Args &&... args) const
176 return (mValue & Or(std::forward<Args>(args)...)) != 0;
180 * Check that at least one flag is set.
182 * @returns True if any flag is set, false otherwise.
184 bool HasAny() const { return mValue != 0; }
187 * Find the logical intersection of flags.
189 * @param lhs Some flags.
190 * @param rhs Some flags.
191 * @returns Flags set in both @a lhs and @a rhs.
193 * @note: A multi-argument `BitFlags` constructor serves the function of `operator|`.
195 friend BitFlags<FlagsEnum> operator&(BitFlags<FlagsEnum> lhs, const BitFlags<FlagsEnum> & rhs)
197 return BitFlags<FlagsEnum>(lhs.mValue & rhs.mValue);
201 * Get the flags as the type FlagsEnum.
203 * @note This allows easily storing flags as a base FlagsEnum in a POD type,
204 * and enables equality comparisons.
206 operator FlagsEnum() const { return static_cast<FlagsEnum>(mValue); }
209 * Set and/or clear all flags with a value of the underlying storage type.
211 * @param value New storage value.
213 BitFlags & SetRaw(IntegerType value)
220 * Get the flags as the underlying integer type.
222 * @note This is intended to be used only to store flags into a raw binary record.
224 IntegerType Raw() const { return mValue; }
227 * Get the address of the flags as a pointer to the underlying integer type.
229 * @note This is intended to be used only to read flags from a raw binary record.
231 StorageType * RawStorage() { return &mValue; }
234 // Find the union of BitFlags and/or FlagsEnum values.
235 template <typename... Args>
236 static constexpr IntegerType Or(FlagsEnum flag, Args &&... args)
238 return static_cast<IntegerType>(flag) | Or(std::forward<Args>(args)...);
240 template <typename... Args>
241 static constexpr IntegerType Or(const BitFlags<FlagsEnum> & flags, Args &&... args)
243 return flags.mValue | Or(std::forward<Args>(args)...);
245 static constexpr IntegerType Or(FlagsEnum value) { return static_cast<IntegerType>(value); }
246 static constexpr IntegerType Or(const BitFlags<FlagsEnum> & flags) { return flags.Raw(); }
248 StorageType mValue = 0;