/* -*- 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/. */ #ifndef mozilla_BitSet_h #define mozilla_BitSet_h #include "mozilla/Array.h" #include "mozilla/Span.h" namespace mozilla { /** * An object like std::bitset but which provides access to the underlying * storage. * * The limited API is due to expedience only; feel free to flesh out any * std::bitset-like members. */ template class BitSet { private: static constexpr size_t kBitsPerWord = 8 * sizeof(Word); static constexpr size_t kNumWords = N == 0 ? 0 : (N - 1) / kBitsPerWord + 1; // The zeroth bit in the bitset is the least significant bit of mStorage[0]. Array mStorage; public: class Reference { public: Reference(BitSet& aBitSet, size_t aPos) : mBitSet(aBitSet), mPos(aPos) {} Reference& operator=(bool aValue) { auto bit = Word(1) << (mPos % kBitsPerWord); auto& word = mBitSet.mStorage[mPos / kBitsPerWord]; word = (word & ~bit) | (aValue ? bit : 0); return *this; } MOZ_IMPLICIT operator bool() const { return mBitSet.Test(mPos); } private: BitSet& mBitSet; size_t mPos; }; BitSet() { PodArrayZero(mStorage); } BitSet(const BitSet& aOther) { *this = aOther; } BitSet& operator=(const BitSet& aOther) { PodCopy(mStorage.begin(), aOther.mStorage.begin(), kNumWords); return *this; } explicit BitSet(Span aStorage) { PodCopy(mStorage.begin(), aStorage.begin(), kNumWords); } constexpr bool Test(size_t aPos) const { MOZ_ASSERT(aPos < N); return mStorage[aPos / kBitsPerWord] & (Word(1) << (aPos % kBitsPerWord)); } constexpr bool operator[](size_t aPos) const { return Test(aPos); } Reference operator[](size_t aPos) { MOZ_ASSERT(aPos < N); return {*this, aPos}; } BitSet operator|(const BitSet& aOther) { BitSet result = *this; result |= aOther; return result; } BitSet& operator|=(const BitSet& aOther) { for (size_t i = 0; i < ArrayLength(mStorage); i++) { mStorage[i] |= aOther.mStorage[i]; } return *this; } Span Storage() { return mStorage; } Span Storage() const { return mStorage; } }; } // namespace mozilla #endif // mozilla_BitSet_h