/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* A set abstraction for enumeration values. */ #ifndef mozilla_EnumSet_h #define mozilla_EnumSet_h #include "mozilla/Assertions.h" #include "mozilla/StandardInteger.h" namespace mozilla { /** * EnumSet<T> is a set of values defined by an enumeration. It is implemented * using a 32 bit mask for each value so it will only work for enums with an int * representation less than 32. It works both for enum and enum class types. */ template<typename T> class EnumSet { public: EnumSet() : mBitField(0) { } EnumSet(T aEnum) : mBitField(aEnum) { } EnumSet(T aEnum1, T aEnum2) : mBitField(bitFor(aEnum1) | bitFor(aEnum2)) { } EnumSet(T aEnum1, T aEnum2, T aEnum3) : mBitField(bitFor(aEnum1) | bitFor(aEnum2) | bitFor(aEnum3)) { } EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4) : mBitField(bitFor(aEnum1) | bitFor(aEnum2) | bitFor(aEnum3) | bitFor(aEnum4)) { } EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) { } /** * Add an element */ void operator+=(T aEnum) { mBitField |= bitFor(aEnum); } /** * Add an element */ EnumSet<T> operator+(T aEnum) const { EnumSet<T> result(*this); result += aEnum; return result; } /** * Union */ void operator+=(const EnumSet<T> aEnumSet) { mBitField |= aEnumSet.mBitField; } /** * Union */ EnumSet<T> operator+(const EnumSet<T> aEnumSet) const { EnumSet<T> result(*this); result += aEnumSet; return result; } /** * Remove an element */ void operator-=(T aEnum) { mBitField &= ~(bitFor(aEnum)); } /** * Remove an element */ EnumSet<T> operator-(T aEnum) const { EnumSet<T> result(*this); result -= aEnum; return result; } /** * Remove a set of elements */ void operator-=(const EnumSet<T> aEnumSet) { mBitField &= ~(aEnumSet.mBitField); } /** * Remove a set of elements */ EnumSet<T> operator-(const EnumSet<T> aEnumSet) const { EnumSet<T> result(*this); result -= aEnumSet; return result; } /** * Intersection */ void operator&=(const EnumSet<T> aEnumSet) { mBitField &= aEnumSet.mBitField; } /** * Intersection */ EnumSet<T> operator&(const EnumSet<T> aEnumSet) const { EnumSet<T> result(*this); result &= aEnumSet; return result; } /** * Equality */ bool operator==(const EnumSet<T> aEnumSet) const { return mBitField == aEnumSet.mBitField; } /** * Test is an element is contained in the set */ bool contains(T aEnum) const { return mBitField & bitFor(aEnum); } /** * Return the number of elements in the set */ uint8_t size() { uint8_t count = 0; for (uint32_t bitField = mBitField; bitField; bitField >>= 1) { if (bitField & 1) count++; } return count; } private: static uint32_t bitFor(T aEnum) { uint32_t bitNumber(aEnum); MOZ_ASSERT(bitNumber < 32); return 1U << bitNumber; } uint32_t mBitField; }; } // namespace mozilla #endif // mozilla_EnumSet_h_