blob: 874f50f3ce8768bae4b4d27c22f7187a494ba5b1 [file] [log] [blame]
Jamie Madill6b2a0b02015-08-03 14:15:08 -04001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// BitSetIterator:
7// A helper class to quickly bitscan bitsets for set bits.
8//
9
10#ifndef COMMON_BITSETITERATOR_H_
11#define COMMON_BITSETITERATOR_H_
12
13#include <stdint.h>
14
15#include <bitset>
16
17#include "common/angleutils.h"
18#include "common/debug.h"
19#include "common/mathutil.h"
20#include "common/platform.h"
21
22namespace angle
23{
24template <size_t N>
25class BitSetIterator final
26{
27 public:
28 BitSetIterator(const std::bitset<N> &bitset);
29 BitSetIterator(const BitSetIterator &other);
30 BitSetIterator &operator=(const BitSetIterator &other);
31
32 class Iterator final
33 {
34 public:
35 Iterator(const std::bitset<N> &bits);
36 Iterator &operator++();
37
38 bool operator==(const Iterator &other) const;
39 bool operator!=(const Iterator &other) const;
40 unsigned long operator*() const { return mCurrentBit; }
41
42 private:
43 unsigned long getNextBit();
44
45 static const size_t BitsPerWord = sizeof(unsigned long) * 8;
46 std::bitset<N> mBits;
47 unsigned long mCurrentBit;
48 unsigned long mOffset;
49 };
50
51 Iterator begin() const { return Iterator(mBits); }
52 Iterator end() const { return Iterator(std::bitset<N>(0)); }
53
54 private:
Jamie Madillb3a60aa2015-08-14 14:44:06 -040055 const std::bitset<N> mBits;
Jamie Madill6b2a0b02015-08-03 14:15:08 -040056};
57
58template <size_t N>
59BitSetIterator<N>::BitSetIterator(const std::bitset<N> &bitset)
60 : mBits(bitset)
61{
62}
63
64template <size_t N>
65BitSetIterator<N>::BitSetIterator(const BitSetIterator &other)
66 : mBits(other.mBits)
67{
68}
69
70template <size_t N>
71BitSetIterator<N> &BitSetIterator<N>::operator=(const BitSetIterator &other)
72{
73 mBits = other.mBits;
74 return *this;
75}
76
77template <size_t N>
78BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
79 : mBits(bits), mCurrentBit(0), mOffset(0)
80{
81 if (bits.any())
82 {
83 mCurrentBit = getNextBit();
84 }
85 else
86 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070087 mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
Jamie Madill6b2a0b02015-08-03 14:15:08 -040088 }
89}
90
91template <size_t N>
92typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
93{
94 ASSERT(mBits.any());
95 mBits.set(mCurrentBit - mOffset, 0);
96 mCurrentBit = getNextBit();
97 return *this;
98}
99
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400100template <size_t N>
101bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
102{
103 return mOffset == other.mOffset && mBits == other.mBits;
104}
105
106template <size_t N>
107bool BitSetIterator<N>::Iterator::operator!=(const Iterator &other) const
108{
109 return !(*this == other);
110}
111
112template <size_t N>
113unsigned long BitSetIterator<N>::Iterator::getNextBit()
114{
115 static std::bitset<N> wordMask(std::numeric_limits<unsigned long>::max());
116
117 while (mOffset < N)
118 {
119 unsigned long wordBits = (mBits & wordMask).to_ulong();
120 if (wordBits != 0ul)
121 {
Olli Etuaho9250cb22017-01-21 10:51:27 +0000122 return gl::ScanForward(wordBits) + mOffset;
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400123 }
124
125 mBits >>= BitsPerWord;
126 mOffset += BitsPerWord;
127 }
128 return 0;
129}
130
131// Helper to avoid needing to specify the template parameter size
132template <size_t N>
133BitSetIterator<N> IterateBitSet(const std::bitset<N> &bitset)
134{
135 return BitSetIterator<N>(bitset);
136}
137
138} // angle
139
140#endif // COMMON_BITSETITERATOR_H_