Bug 1734943 [wpt PR 31170] - Correct scrolling contents cull rect, a=testonly
[gecko.git] / mfbt / EnumSet.h
blobf635ec51ffbf9f07637a964868936be188644525
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 #ifdef DEBUG
54 constexpr EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) {}
56 constexpr EnumSet& operator=(const EnumSet& aEnumSet) {
57 mBitField = aEnumSet.mBitField;
58 incVersion();
59 return *this;
61 #endif
63 /**
64 * Add an element
66 constexpr void operator+=(T aEnum) {
67 incVersion();
68 mBitField |= bitFor(aEnum);
71 /**
72 * Add an element
74 constexpr EnumSet operator+(T aEnum) const {
75 EnumSet result(*this);
76 result += aEnum;
77 return result;
80 /**
81 * Union
83 void operator+=(const EnumSet& aEnumSet) {
84 incVersion();
85 mBitField |= aEnumSet.mBitField;
88 /**
89 * Union
91 EnumSet operator+(const EnumSet& aEnumSet) const {
92 EnumSet result(*this);
93 result += aEnumSet;
94 return result;
97 /**
98 * Remove an element
100 void operator-=(T aEnum) {
101 incVersion();
102 mBitField &= ~(bitFor(aEnum));
106 * Remove an element
108 EnumSet operator-(T aEnum) const {
109 EnumSet result(*this);
110 result -= aEnum;
111 return result;
115 * Remove a set of elements
117 void operator-=(const EnumSet& aEnumSet) {
118 incVersion();
119 mBitField &= ~(aEnumSet.mBitField);
123 * Remove a set of elements
125 EnumSet operator-(const EnumSet& aEnumSet) const {
126 EnumSet result(*this);
127 result -= aEnumSet;
128 return result;
132 * Clear
134 void clear() {
135 incVersion();
136 mBitField = 0;
140 * Intersection
142 void operator&=(const EnumSet& aEnumSet) {
143 incVersion();
144 mBitField &= aEnumSet.mBitField;
148 * Intersection
150 EnumSet operator&(const EnumSet& aEnumSet) const {
151 EnumSet result(*this);
152 result &= aEnumSet;
153 return result;
157 * Equality
159 bool operator==(const EnumSet& aEnumSet) const {
160 return mBitField == aEnumSet.mBitField;
164 * Equality
166 bool operator==(T aEnum) const { return mBitField == bitFor(aEnum); }
169 * Not equal
171 bool operator!=(const EnumSet& aEnumSet) const {
172 return !operator==(aEnumSet);
176 * Not equal
178 bool operator!=(T aEnum) const { return !operator==(aEnum); }
181 * Test is an element is contained in the set.
183 bool contains(T aEnum) const { return mBitField & bitFor(aEnum); }
186 * Test if a set is contained in the set.
188 bool contains(const EnumSet& aEnumSet) const {
189 return (mBitField & aEnumSet.mBitField) == aEnumSet.mBitField;
193 * Return the number of elements in the set.
195 uint8_t size() const {
196 uint8_t count = 0;
197 for (Serialized bitField = mBitField; bitField; bitField >>= 1) {
198 if (bitField & 1) {
199 count++;
202 return count;
205 bool isEmpty() const { return mBitField == 0; }
207 Serialized serialize() const { return mBitField; }
209 void deserialize(Serialized aValue) {
210 incVersion();
211 mBitField = aValue;
214 class ConstIterator {
215 const EnumSet* mSet;
216 uint32_t mPos;
217 #ifdef DEBUG
218 uint64_t mVersion;
219 #endif
221 void checkVersion() const {
222 // Check that the set has not been modified while being iterated.
223 MOZ_ASSERT_IF(mSet, mSet->mVersion == mVersion);
226 public:
227 ConstIterator(const EnumSet& aSet, uint32_t aPos)
228 : mSet(&aSet), mPos(aPos) {
229 #ifdef DEBUG
230 mVersion = mSet->mVersion;
231 #endif
232 MOZ_ASSERT(aPos <= kMaxBits);
233 if (aPos != kMaxBits && !mSet->contains(T(mPos))) ++*this;
236 ConstIterator(const ConstIterator& aOther)
237 : mSet(aOther.mSet), mPos(aOther.mPos) {
238 #ifdef DEBUG
239 mVersion = aOther.mVersion;
240 checkVersion();
241 #endif
244 ConstIterator(ConstIterator&& aOther)
245 : mSet(aOther.mSet), mPos(aOther.mPos) {
246 #ifdef DEBUG
247 mVersion = aOther.mVersion;
248 checkVersion();
249 #endif
250 aOther.mSet = nullptr;
253 ~ConstIterator() { checkVersion(); }
255 bool operator==(const ConstIterator& other) const {
256 MOZ_ASSERT(mSet == other.mSet);
257 checkVersion();
258 return mPos == other.mPos;
261 bool operator!=(const ConstIterator& other) const {
262 return !(*this == other);
265 T operator*() const {
266 MOZ_ASSERT(mSet);
267 MOZ_ASSERT(mPos < kMaxBits);
268 MOZ_ASSERT(mSet->contains(T(mPos)));
269 checkVersion();
270 return T(mPos);
273 ConstIterator& operator++() {
274 MOZ_ASSERT(mSet);
275 MOZ_ASSERT(mPos < kMaxBits);
276 checkVersion();
277 do {
278 mPos++;
279 } while (mPos < kMaxBits && !mSet->contains(T(mPos)));
280 return *this;
284 ConstIterator begin() const { return ConstIterator(*this, 0); }
286 ConstIterator end() const { return ConstIterator(*this, kMaxBits); }
288 private:
289 constexpr static Serialized bitFor(T aEnum) {
290 auto bitNumber = static_cast<Serialized>(aEnum);
291 MOZ_DIAGNOSTIC_ASSERT(bitNumber < kMaxBits);
292 return static_cast<Serialized>(Serialized{1} << bitNumber);
295 constexpr void incVersion() {
296 #ifdef DEBUG
297 mVersion++;
298 #endif
301 static const size_t kMaxBits = sizeof(Serialized) * 8;
303 Serialized mBitField;
305 #ifdef DEBUG
306 uint64_t mVersion = 0;
307 #endif
310 } // namespace mozilla
312 #endif /* mozilla_EnumSet_h_*/