summaryrefslogtreecommitdiffstats
path: root/mfbt/BitSet.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /mfbt/BitSet.h
parentInitial commit. (diff)
downloadfirefox-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.h115
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