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