mfbt/EnumSet.h
author Jeff Walden <jwalden@mit.edu>
Thu, 29 May 2014 16:01:21 -0700
changeset 199363 c5a58d90da90ee36323c5fba7720f2db52eb611e
parent 152836 95fda0cdd9da6a6ce4dba2a09d00406896958e00
child 201579 ad9f8d5ba0cf9678404a285d985ae65211241ad5
permissions -rw-r--r--
Bug 999651, bug 995679, bug 1009952, bug 1011007, bug 991981. r=sfink, r=shu, r=jandem, r=jdm, r=luke, r=bbouvier, r=nmatsakis, r=bz, r=ehsan, r=jgilbert, r=smaug, r=sicking, r=terrence, r=bholley, r=bent, r=efaust, r=jorendorff, a=lsblakk

/* -*- 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 <stdint.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_*/