diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /mfbt/BitSet.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mfbt/BitSet.h')
-rw-r--r-- | mfbt/BitSet.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/mfbt/BitSet.h b/mfbt/BitSet.h new file mode 100644 index 0000000000..2828be4182 --- /dev/null +++ b/mfbt/BitSet.h @@ -0,0 +1,115 @@ +/* -*- 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/PodOperations.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 <size_t N, typename Word = size_t> +class BitSet { + static_assert(std::is_unsigned_v<Word>, + "The Word type must be an unsigned integral type"); + + private: + static constexpr size_t kBitsPerWord = 8 * sizeof(Word); + static constexpr size_t kNumWords = (N + kBitsPerWord - 1) / kBitsPerWord; + + // The zeroth bit in the bitset is the least significant bit of mStorage[0]. + Array<Word, kNumWords> mStorage; + + public: + class Reference { + public: + Reference(BitSet<N, Word>& 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<N, Word>& mBitSet; + size_t mPos; + }; + + BitSet() { ResetAll(); } + + BitSet(const BitSet& aOther) { *this = aOther; } + + BitSet& operator=(const BitSet& aOther) { + PodCopy(mStorage.begin(), aOther.mStorage.begin(), kNumWords); + return *this; + } + + explicit BitSet(Span<Word, kNumWords> aStorage) { + PodCopy(mStorage.begin(), aStorage.Elements(), kNumWords); + } + + constexpr size_t Size() const { return N; } + + 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<N, Word>& aOther) { + BitSet result = *this; + result |= aOther; + return result; + } + + BitSet& operator|=(const BitSet<N, Word>& aOther) { + for (size_t i = 0; i < ArrayLength(mStorage); i++) { + mStorage[i] |= aOther.mStorage[i]; + } + return *this; + } + + // Set all bits to false. + void ResetAll() { PodArrayZero(mStorage); } + + // Set all bits to true. + void SetAll() { + memset(mStorage.begin(), 0xff, kNumWords * sizeof(Word)); + constexpr size_t paddingBits = (kNumWords * kBitsPerWord) - N; + constexpr Word paddingMask = Word(-1) >> paddingBits; + if constexpr (paddingBits != 0) { + mStorage[kNumWords - 1] &= paddingMask; + } + } + + Span<Word> Storage() { return mStorage; } + + Span<const Word> Storage() const { return mStorage; } +}; + +} // namespace mozilla + +#endif // mozilla_BitSet_h |