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