Bug 1601406 [wpt PR 20618] - Advertise DocumentPolicy & Network Err when receive...
[gecko.git] / mfbt / EnumSet.h
blobae4364034e266d2c464f58088f0bf055eddf7394
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>
18 #include <stdint.h>
20 namespace mozilla {
22 /**
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>
29 class EnumSet {
30 public:
31 typedef T valueType;
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) |
45 bitFor(aEnum4)) {}
47 constexpr MOZ_IMPLICIT EnumSet(std::initializer_list<T> list) : mBitField(0) {
48 for (auto value : list) {
49 (*this) += value;
53 constexpr EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) {}
55 /**
56 * Add an element
58 constexpr void operator+=(T aEnum) {
59 incVersion();
60 mBitField |= bitFor(aEnum);
63 /**
64 * Add an element
66 constexpr EnumSet operator+(T aEnum) const {
67 EnumSet result(*this);
68 result += aEnum;
69 return result;
72 /**
73 * Union
75 void operator+=(const EnumSet& aEnumSet) {
76 incVersion();
77 mBitField |= aEnumSet.mBitField;
80 /**
81 * Union
83 EnumSet operator+(const EnumSet& aEnumSet) const {
84 EnumSet result(*this);
85 result += aEnumSet;
86 return result;
89 /**
90 * Remove an element
92 void operator-=(T aEnum) {
93 incVersion();
94 mBitField &= ~(bitFor(aEnum));
97 /**
98 * Remove an element
100 EnumSet operator-(T aEnum) const {
101 EnumSet result(*this);
102 result -= aEnum;
103 return result;
107 * Remove a set of elements
109 void operator-=(const EnumSet& aEnumSet) {
110 incVersion();
111 mBitField &= ~(aEnumSet.mBitField);
115 * Remove a set of elements
117 EnumSet operator-(const EnumSet& aEnumSet) const {
118 EnumSet result(*this);
119 result -= aEnumSet;
120 return result;
124 * Clear
126 void clear() {
127 incVersion();
128 mBitField = 0;
132 * Intersection
134 void operator&=(const EnumSet& aEnumSet) {
135 incVersion();
136 mBitField &= aEnumSet.mBitField;
140 * Intersection
142 EnumSet operator&(const EnumSet& aEnumSet) const {
143 EnumSet result(*this);
144 result &= aEnumSet;
145 return result;
149 * Equality
151 bool operator==(const EnumSet& aEnumSet) const {
152 return mBitField == aEnumSet.mBitField;
156 * Equality
158 bool operator==(T aEnum) const { return mBitField == bitFor(aEnum); }
161 * Not equal
163 bool operator!=(const EnumSet& aEnumSet) const {
164 return !operator==(aEnumSet);
168 * Not equal
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 {
188 uint8_t count = 0;
189 for (Serialized bitField = mBitField; bitField; bitField >>= 1) {
190 if (bitField & 1) {
191 count++;
194 return count;
197 bool isEmpty() const { return mBitField == 0; }
199 Serialized serialize() const { return mBitField; }
201 void deserialize(Serialized aValue) {
202 incVersion();
203 mBitField = aValue;
206 class ConstIterator {
207 const EnumSet* mSet;
208 uint32_t mPos;
209 #ifdef DEBUG
210 uint64_t mVersion;
211 #endif
213 void checkVersion() const {
214 // Check that the set has not been modified while being iterated.
215 MOZ_ASSERT_IF(mSet, mSet->mVersion == mVersion);
218 public:
219 ConstIterator(const EnumSet& aSet, uint32_t aPos)
220 : mSet(&aSet), mPos(aPos) {
221 #ifdef DEBUG
222 mVersion = mSet->mVersion;
223 #endif
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) {
230 #ifdef DEBUG
231 mVersion = aOther.mVersion;
232 checkVersion();
233 #endif
236 ConstIterator(ConstIterator&& aOther)
237 : mSet(aOther.mSet), mPos(aOther.mPos) {
238 #ifdef DEBUG
239 mVersion = aOther.mVersion;
240 checkVersion();
241 #endif
242 aOther.mSet = nullptr;
245 ~ConstIterator() { checkVersion(); }
247 bool operator==(const ConstIterator& other) const {
248 MOZ_ASSERT(mSet == other.mSet);
249 checkVersion();
250 return mPos == other.mPos;
253 bool operator!=(const ConstIterator& other) const {
254 return !(*this == other);
257 T operator*() const {
258 MOZ_ASSERT(mSet);
259 MOZ_ASSERT(mPos < kMaxBits);
260 MOZ_ASSERT(mSet->contains(T(mPos)));
261 checkVersion();
262 return T(mPos);
265 ConstIterator& operator++() {
266 MOZ_ASSERT(mSet);
267 MOZ_ASSERT(mPos < kMaxBits);
268 checkVersion();
269 do {
270 mPos++;
271 } while (mPos < kMaxBits && !mSet->contains(T(mPos)));
272 return *this;
276 ConstIterator begin() const { return ConstIterator(*this, 0); }
278 ConstIterator end() const { return ConstIterator(*this, kMaxBits); }
280 private:
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() {
288 #ifdef DEBUG
289 mVersion++;
290 #endif
293 static const size_t kMaxBits = sizeof(Serialized) * 8;
295 Serialized mBitField;
297 #ifdef DEBUG
298 uint64_t mVersion = 0;
299 #endif
302 } // namespace mozilla
304 #endif /* mozilla_EnumSet_h_*/