gecko/mfbt/EnumSet.h

177 lines
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_*/