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/. */
6 
7 /* A set abstraction for enumeration values. */
8 
9 #ifndef mozilla_EnumSet_h
10 #define mozilla_EnumSet_h
11 
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Attributes.h"
14 
15 #include <stdint.h>
16 
17 namespace mozilla {
18 
19 /**
20  * EnumSet<T> is a set of values defined by an enumeration. It is implemented
21  * using a 32 bit mask for each value so it will only work for enums with an int
22  * representation less than 32. It works both for enum and enum class types.
23  */
24 template<typename T>
25 class EnumSet
26 {
27 public:
EnumSet()28   EnumSet()
29     : mBitField(0)
30   { }
31 
EnumSet(T aEnum)32   MOZ_IMPLICIT EnumSet(T aEnum)
33     : mBitField(bitFor(aEnum))
34   { }
35 
EnumSet(T aEnum1,T aEnum2)36   EnumSet(T aEnum1, T aEnum2)
37     : mBitField(bitFor(aEnum1) |
38                 bitFor(aEnum2))
39   { }
40 
EnumSet(T aEnum1,T aEnum2,T aEnum3)41   EnumSet(T aEnum1, T aEnum2, T aEnum3)
42     : mBitField(bitFor(aEnum1) |
43                 bitFor(aEnum2) |
44                 bitFor(aEnum3))
45   { }
46 
EnumSet(T aEnum1,T aEnum2,T aEnum3,T aEnum4)47   EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
48    : mBitField(bitFor(aEnum1) |
49                bitFor(aEnum2) |
50                bitFor(aEnum3) |
51                bitFor(aEnum4))
52   { }
53 
EnumSet(const EnumSet & aEnumSet)54   EnumSet(const EnumSet& aEnumSet)
55    : mBitField(aEnumSet.mBitField)
56   { }
57 
58   /**
59    * Add an element
60    */
61   void operator+=(T aEnum)
62   {
63     mBitField |= bitFor(aEnum);
64   }
65 
66   /**
67    * Add an element
68    */
69   EnumSet<T> operator+(T aEnum) const
70   {
71     EnumSet<T> result(*this);
72     result += aEnum;
73     return result;
74   }
75 
76   /**
77    * Union
78    */
79   void operator+=(const EnumSet<T> aEnumSet)
80   {
81     mBitField |= aEnumSet.mBitField;
82   }
83 
84   /**
85    * Union
86    */
87   EnumSet<T> operator+(const EnumSet<T> aEnumSet) const
88   {
89     EnumSet<T> result(*this);
90     result += aEnumSet;
91     return result;
92   }
93 
94   /**
95    * Remove an element
96    */
97   void operator-=(T aEnum)
98   {
99     mBitField &= ~(bitFor(aEnum));
100   }
101 
102   /**
103    * Remove an element
104    */
105   EnumSet<T> operator-(T aEnum) const
106   {
107     EnumSet<T> result(*this);
108     result -= aEnum;
109     return result;
110   }
111 
112   /**
113    * Remove a set of elements
114    */
115   void operator-=(const EnumSet<T> aEnumSet)
116   {
117     mBitField &= ~(aEnumSet.mBitField);
118   }
119 
120   /**
121    * Remove a set of elements
122    */
123   EnumSet<T> operator-(const EnumSet<T> aEnumSet) const
124   {
125     EnumSet<T> result(*this);
126     result -= aEnumSet;
127     return result;
128   }
129 
130   /**
131    * Clear
132    */
clear()133   void clear()
134   {
135     mBitField = 0;
136   }
137 
138   /**
139    * Intersection
140    */
141   void operator&=(const EnumSet<T> aEnumSet)
142   {
143     mBitField &= aEnumSet.mBitField;
144   }
145 
146   /**
147    * Intersection
148    */
149   EnumSet<T> operator&(const EnumSet<T> aEnumSet) const
150   {
151     EnumSet<T> result(*this);
152     result &= aEnumSet;
153     return result;
154   }
155 
156   /**
157    * Equality
158    */
159   bool operator==(const EnumSet<T> aEnumSet) const
160   {
161     return mBitField == aEnumSet.mBitField;
162   }
163 
164   /**
165    * Test is an element is contained in the set.
166    */
contains(T aEnum)167   bool contains(T aEnum) const
168   {
169     return mBitField & bitFor(aEnum);
170   }
171 
172   /**
173    * Return the number of elements in the set.
174    */
size()175   uint8_t size()
176   {
177     uint8_t count = 0;
178     for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
179       if (bitField & 1) {
180         count++;
181       }
182     }
183     return count;
184   }
185 
isEmpty()186   bool isEmpty() const
187   {
188     return mBitField == 0;
189   }
190 
serialize()191   uint32_t serialize() const
192   {
193     return mBitField;
194   }
195 
deserialize(uint32_t aValue)196   void deserialize(uint32_t aValue)
197   {
198     mBitField = aValue;
199   }
200 
201 private:
bitFor(T aEnum)202   static uint32_t bitFor(T aEnum)
203   {
204     uint32_t bitNumber = (uint32_t)aEnum;
205     MOZ_ASSERT(bitNumber < 32);
206     return 1U << bitNumber;
207   }
208 
209   uint32_t mBitField;
210 };
211 
212 } // namespace mozilla
213 
214 #endif /* mozilla_EnumSet_h_*/
215