1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* A set abstraction for enumeration values. */
9 #ifndef mozilla_EnumSet_h
10 #define mozilla_EnumSet_h
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Attributes.h"
15 #include <initializer_list>
16 #include <type_traits>
23 * EnumSet<T, U> is a set of values defined by an enumeration. It is implemented
24 * using a bit mask with the size of U for each value. It works both for enum
25 * and enum class types.
27 template <typename T
, typename Serialized
= typename
std::make_unsigned
<
28 typename
std::underlying_type
<T
>::type
>::type
>
33 constexpr EnumSet() : mBitField(0) {}
35 constexpr MOZ_IMPLICIT
EnumSet(T aEnum
) : mBitField(bitFor(aEnum
)) {}
37 constexpr EnumSet(T aEnum1
, T aEnum2
)
38 : mBitField(bitFor(aEnum1
) | bitFor(aEnum2
)) {}
40 constexpr EnumSet(T aEnum1
, T aEnum2
, T aEnum3
)
41 : mBitField(bitFor(aEnum1
) | bitFor(aEnum2
) | bitFor(aEnum3
)) {}
43 constexpr EnumSet(T aEnum1
, T aEnum2
, T aEnum3
, T aEnum4
)
44 : mBitField(bitFor(aEnum1
) | bitFor(aEnum2
) | bitFor(aEnum3
) |
47 constexpr MOZ_IMPLICIT
EnumSet(std::initializer_list
<T
> list
) : mBitField(0) {
48 for (auto value
: list
) {
53 constexpr EnumSet(const EnumSet
& aEnumSet
) : mBitField(aEnumSet
.mBitField
) {}
58 constexpr void operator+=(T aEnum
) {
60 mBitField
|= bitFor(aEnum
);
66 constexpr EnumSet
operator+(T aEnum
) const {
67 EnumSet
result(*this);
75 void operator+=(const EnumSet
& aEnumSet
) {
77 mBitField
|= aEnumSet
.mBitField
;
83 EnumSet
operator+(const EnumSet
& aEnumSet
) const {
84 EnumSet
result(*this);
92 void operator-=(T aEnum
) {
94 mBitField
&= ~(bitFor(aEnum
));
100 EnumSet
operator-(T aEnum
) const {
101 EnumSet
result(*this);
107 * Remove a set of elements
109 void operator-=(const EnumSet
& aEnumSet
) {
111 mBitField
&= ~(aEnumSet
.mBitField
);
115 * Remove a set of elements
117 EnumSet
operator-(const EnumSet
& aEnumSet
) const {
118 EnumSet
result(*this);
134 void operator&=(const EnumSet
& aEnumSet
) {
136 mBitField
&= aEnumSet
.mBitField
;
142 EnumSet
operator&(const EnumSet
& aEnumSet
) const {
143 EnumSet
result(*this);
151 bool operator==(const EnumSet
& aEnumSet
) const {
152 return mBitField
== aEnumSet
.mBitField
;
158 bool operator==(T aEnum
) const { return mBitField
== bitFor(aEnum
); }
163 bool operator!=(const EnumSet
& aEnumSet
) const {
164 return !operator==(aEnumSet
);
170 bool operator!=(T aEnum
) const { return !operator==(aEnum
); }
173 * Test is an element is contained in the set.
175 bool contains(T aEnum
) const { return mBitField
& bitFor(aEnum
); }
178 * Test if a set is contained in the set.
180 bool contains(const EnumSet
& aEnumSet
) const {
181 return (mBitField
& aEnumSet
.mBitField
) == aEnumSet
.mBitField
;
185 * Return the number of elements in the set.
187 uint8_t size() const {
189 for (Serialized bitField
= mBitField
; bitField
; bitField
>>= 1) {
197 bool isEmpty() const { return mBitField
== 0; }
199 Serialized
serialize() const { return mBitField
; }
201 void deserialize(Serialized aValue
) {
206 class ConstIterator
{
213 void checkVersion() const {
214 // Check that the set has not been modified while being iterated.
215 MOZ_ASSERT_IF(mSet
, mSet
->mVersion
== mVersion
);
219 ConstIterator(const EnumSet
& aSet
, uint32_t aPos
)
220 : mSet(&aSet
), mPos(aPos
) {
222 mVersion
= mSet
->mVersion
;
224 MOZ_ASSERT(aPos
<= kMaxBits
);
225 if (aPos
!= kMaxBits
&& !mSet
->contains(T(mPos
))) ++*this;
228 ConstIterator(const ConstIterator
& aOther
)
229 : mSet(aOther
.mSet
), mPos(aOther
.mPos
) {
231 mVersion
= aOther
.mVersion
;
236 ConstIterator(ConstIterator
&& aOther
)
237 : mSet(aOther
.mSet
), mPos(aOther
.mPos
) {
239 mVersion
= aOther
.mVersion
;
242 aOther
.mSet
= nullptr;
245 ~ConstIterator() { checkVersion(); }
247 bool operator==(const ConstIterator
& other
) const {
248 MOZ_ASSERT(mSet
== other
.mSet
);
250 return mPos
== other
.mPos
;
253 bool operator!=(const ConstIterator
& other
) const {
254 return !(*this == other
);
257 T
operator*() const {
259 MOZ_ASSERT(mPos
< kMaxBits
);
260 MOZ_ASSERT(mSet
->contains(T(mPos
)));
265 ConstIterator
& operator++() {
267 MOZ_ASSERT(mPos
< kMaxBits
);
271 } while (mPos
< kMaxBits
&& !mSet
->contains(T(mPos
)));
276 ConstIterator
begin() const { return ConstIterator(*this, 0); }
278 ConstIterator
end() const { return ConstIterator(*this, kMaxBits
); }
281 constexpr static Serialized
bitFor(T aEnum
) {
282 auto bitNumber
= static_cast<Serialized
>(aEnum
);
283 MOZ_DIAGNOSTIC_ASSERT(bitNumber
< kMaxBits
);
284 return static_cast<Serialized
>(Serialized
{1} << bitNumber
);
287 constexpr void incVersion() {
293 static const size_t kMaxBits
= sizeof(Serialized
) * 8;
295 Serialized mBitField
;
298 uint64_t mVersion
= 0;
302 } // namespace mozilla
304 #endif /* mozilla_EnumSet_h_*/