Bug 1885602 - Part 4: Implement navigating to the settings from the menu header for...
[gecko.git] / mfbt / BitSet.h
blob7c03fb87ce6b9b0a8a9c1bf6900702c44643ba41
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_BitSet_h
8 #define mozilla_BitSet_h
10 #include "mozilla/Array.h"
11 #include "mozilla/ArrayUtils.h"
12 #include "mozilla/MathAlgorithms.h"
13 #include "mozilla/PodOperations.h"
14 #include "mozilla/Span.h"
16 namespace mozilla {
18 /**
19 * An object like std::bitset but which provides access to the underlying
20 * storage.
22 * The limited API is due to expedience only; feel free to flesh out any
23 * std::bitset-like members.
25 template <size_t N, typename Word = size_t>
26 class BitSet {
27 static_assert(std::is_unsigned_v<Word>,
28 "The Word type must be an unsigned integral type");
30 private:
31 static constexpr size_t kBitsPerWord = 8 * sizeof(Word);
32 static constexpr size_t kNumWords = (N + kBitsPerWord - 1) / kBitsPerWord;
33 static constexpr size_t kPaddingBits = (kNumWords * kBitsPerWord) - N;
34 static constexpr Word kPaddingMask = Word(-1) >> kPaddingBits;
36 // The zeroth bit in the bitset is the least significant bit of mStorage[0].
37 Array<Word, kNumWords> mStorage;
39 constexpr void ResetPaddingBits() {
40 if constexpr (kPaddingBits != 0) {
41 mStorage[kNumWords - 1] &= kPaddingMask;
45 public:
46 class Reference {
47 public:
48 Reference(BitSet<N, Word>& aBitSet, size_t aPos)
49 : mBitSet(aBitSet), mPos(aPos) {}
51 Reference& operator=(bool aValue) {
52 auto bit = Word(1) << (mPos % kBitsPerWord);
53 auto& word = mBitSet.mStorage[mPos / kBitsPerWord];
54 word = (word & ~bit) | (aValue ? bit : 0);
55 return *this;
58 MOZ_IMPLICIT operator bool() const { return mBitSet.Test(mPos); }
60 private:
61 BitSet<N, Word>& mBitSet;
62 size_t mPos;
65 constexpr BitSet() : mStorage() {}
67 BitSet(const BitSet& aOther) { *this = aOther; }
69 BitSet& operator=(const BitSet& aOther) {
70 PodCopy(mStorage.begin(), aOther.mStorage.begin(), kNumWords);
71 return *this;
74 explicit BitSet(Span<Word, kNumWords> aStorage) {
75 PodCopy(mStorage.begin(), aStorage.Elements(), kNumWords);
78 static constexpr size_t Size() { return N; }
80 constexpr bool Test(size_t aPos) const {
81 MOZ_ASSERT(aPos < N);
82 return mStorage[aPos / kBitsPerWord] & (Word(1) << (aPos % kBitsPerWord));
85 constexpr bool IsEmpty() const {
86 for (const Word& word : mStorage) {
87 if (word) {
88 return false;
91 return true;
94 explicit constexpr operator bool() { return !IsEmpty(); }
96 constexpr bool operator[](size_t aPos) const { return Test(aPos); }
98 Reference operator[](size_t aPos) {
99 MOZ_ASSERT(aPos < N);
100 return {*this, aPos};
103 BitSet operator|(const BitSet<N, Word>& aOther) {
104 BitSet result = *this;
105 result |= aOther;
106 return result;
109 BitSet& operator|=(const BitSet<N, Word>& aOther) {
110 for (size_t i = 0; i < ArrayLength(mStorage); i++) {
111 mStorage[i] |= aOther.mStorage[i];
113 return *this;
116 BitSet operator~() const {
117 BitSet result = *this;
118 result.Flip();
119 return result;
122 BitSet& operator&=(const BitSet<N, Word>& aOther) {
123 for (size_t i = 0; i < ArrayLength(mStorage); i++) {
124 mStorage[i] &= aOther.mStorage[i];
126 return *this;
129 BitSet operator&(const BitSet<N, Word>& aOther) const {
130 BitSet result = *this;
131 result &= aOther;
132 return result;
135 bool operator==(const BitSet<N, Word>& aOther) const {
136 return mStorage == aOther.mStorage;
139 size_t Count() const {
140 size_t count = 0;
142 for (const Word& word : mStorage) {
143 if constexpr (kBitsPerWord > 32) {
144 count += CountPopulation64(word);
145 } else {
146 count += CountPopulation32(word);
150 return count;
153 // Set all bits to false.
154 void ResetAll() { PodArrayZero(mStorage); }
156 // Set all bits to true.
157 void SetAll() {
158 memset(mStorage.begin(), 0xff, kNumWords * sizeof(Word));
159 ResetPaddingBits();
162 void Flip() {
163 for (Word& word : mStorage) {
164 word = ~word;
167 ResetPaddingBits();
170 Span<Word> Storage() { return mStorage; }
172 Span<const Word> Storage() const { return mStorage; }
175 } // namespace mozilla
177 #endif // mozilla_BitSet_h