Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
bitset_iterator.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <type_traits>
6
7namespace gaia {
8 namespace cnt {
13 template <typename TBitset, bool IsFwd, bool IsInverse>
15 public:
19 using size_type = typename TBitset::size_type;
20
21 private:
22 const TBitset* m_bitset = nullptr;
23 value_type m_pos = 0;
24
25 GAIA_NODISCARD size_type item(uint32_t wordIdx) const noexcept {
26 if constexpr (IsInverse)
27 return ~m_bitset->data(wordIdx);
28 else
29 return m_bitset->data(wordIdx);
30 }
31
32 GAIA_NODISCARD bool check_bit(uint32_t pos) const noexcept {
33 if constexpr (IsInverse)
34 return !m_bitset->test(pos);
35 else
36 return m_bitset->test(pos);
37 }
38
39 GAIA_NODISCARD uint32_t find_next_set_bit(uint32_t pos) const noexcept {
40 value_type wordIndex = pos / TBitset::BitsPerItem;
41 const auto item_count = m_bitset->items();
42 GAIA_ASSERT(wordIndex < item_count);
43 size_type word = 0;
44
45 const size_type posInWord = pos % TBitset::BitsPerItem + 1;
46 if GAIA_LIKELY (posInWord < TBitset::BitsPerItem) {
47 const size_type mask = (size_type(1) << posInWord) - 1;
48 word = item(wordIndex) & (~mask);
49 }
50
51 GAIA_MSVC_WARNING_PUSH()
52 GAIA_MSVC_WARNING_DISABLE(4244)
53 while (true) {
54 if (word != 0) {
55 if constexpr (TBitset::BitsPerItem == 32)
56 return wordIndex * TBitset::BitsPerItem + GAIA_FFS(word) - 1;
57 else
58 return wordIndex * TBitset::BitsPerItem + GAIA_FFS64(word) - 1;
59 }
60
61 // No set bit in the current word, move to the next one
62 if (++wordIndex >= item_count)
63 return pos;
64
65 word = item(wordIndex);
66 }
67 GAIA_MSVC_WARNING_POP()
68 }
69
70 GAIA_NODISCARD uint32_t find_prev_set_bit(uint32_t pos) const noexcept {
71 value_type wordIndex = pos / TBitset::BitsPerItem;
72 GAIA_ASSERT(wordIndex < m_bitset->items());
73
74 const size_type posInWord = pos % TBitset::BitsPerItem;
75 const size_type mask = (size_type(1) << posInWord) - 1;
76 size_type word = item(wordIndex) & mask;
77
78 GAIA_MSVC_WARNING_PUSH()
79 GAIA_MSVC_WARNING_DISABLE(4244)
80 while (true) {
81 if (word != 0) {
82 if constexpr (TBitset::BitsPerItem == 32)
83 return TBitset::BitsPerItem * (wordIndex + 1) - GAIA_CTZ(word) - 1;
84 else
85 return TBitset::BitsPerItem * (wordIndex + 1) - GAIA_CTZ64(word) - 1;
86 }
87
88 // No set bit in the current word, move to the previous one
89 if (wordIndex == 0)
90 return pos;
91
92 word = item(--wordIndex);
93 }
94 GAIA_MSVC_WARNING_POP()
95 }
96
97 public:
98 bitset_const_iterator() = default;
99
103 bitset_const_iterator(const TBitset& bitset, value_type pos, bool fwd): m_bitset(&bitset), m_pos(pos) {
104 if (fwd) {
105 if constexpr (!IsFwd) {
106 // Find the first set bit
107 if (pos != 0 || !check_bit(0)) {
108 pos = find_next_set_bit(m_pos);
109 // Point before the last item if no set bit was found
110 if (pos == m_pos)
111 pos = (value_type)-1;
112 else
113 --pos;
114 } else
115 --pos;
116 } else {
117 // Find the first set bit
118 if (pos != 0 || !check_bit(0)) {
119 pos = find_next_set_bit(m_pos);
120 // Point beyond the last item if no set bit was found
121 if (pos == m_pos)
122 pos = bitset.size();
123 }
124 }
125 m_pos = pos;
126 } else {
127 const auto bitsetSize = bitset.size();
128 const auto lastBit = bitsetSize - 1;
129
130 // Stay inside bounds
131 if (pos >= bitsetSize)
132 pos = bitsetSize - 1;
133
134 if constexpr (!IsFwd) {
135 // Find the last set bit
136 if (pos != lastBit || !check_bit(pos)) {
137 const auto newPos = find_prev_set_bit(pos);
138 // Point one beyond the last found bit
139 pos = (newPos == pos) ? bitsetSize - 1 : newPos;
140 }
141 } else {
142 // Find the last set bit
143 if (pos != lastBit || !check_bit(pos)) {
144 const auto newPos = find_prev_set_bit(pos);
145 // Point one beyond the last found bit
146 pos = (newPos == pos) ? bitsetSize : newPos + 1;
147 }
148 // Point one beyond the last found bit
149 else
150 ++pos;
151 }
152
153 m_pos = pos;
154 }
155 }
156
159 GAIA_NODISCARD value_type operator*() const {
160 return m_pos;
161 }
162
165 GAIA_NODISCARD value_type operator->() const {
166 return m_pos;
167 }
168
171 GAIA_NODISCARD value_type index() const {
172 return m_pos;
173 }
174
178 if constexpr (!IsFwd) {
179 if (m_pos == (value_type)-1)
180 return *this;
181
182 auto newPos = find_prev_set_bit(m_pos);
183 // Point one past the last item if no new bit was found
184 if (newPos == m_pos)
185 --newPos;
186 m_pos = newPos;
187 } else {
188 auto newPos = find_next_set_bit(m_pos);
189 // Point one past the last item if no new bit was found
190 if (newPos == m_pos)
191 ++newPos;
192 m_pos = newPos;
193 }
194
195 return *this;
196 }
197
200 GAIA_NODISCARD bitset_const_iterator operator++(int) {
202 ++*this;
203 return temp;
204 }
205
209 GAIA_NODISCARD bool operator==(const bitset_const_iterator& other) const {
210 return m_pos == other.m_pos;
211 }
212
216 GAIA_NODISCARD bool operator!=(const bitset_const_iterator& other) const {
217 return m_pos != other.m_pos;
218 }
219 };
220
223 template <typename TBitset>
224 using const_iterator = bitset_const_iterator<TBitset, true, false>;
227 template <typename TBitset>
228 using const_iterator_inverse = bitset_const_iterator<TBitset, true, true>;
231 template <typename TBitset>
232 using const_reverse_iterator = bitset_const_iterator<TBitset, false, false>;
235 template <typename TBitset>
236 using const_reverse_inverse_iterator = bitset_const_iterator<TBitset, false, true>;
237 } // namespace cnt
238} // namespace gaia
Bitset iterator.
Definition bitset_iterator.h:14
GAIA_NODISCARD bool operator!=(const bitset_const_iterator &other) const
Compares iterator positions.
Definition bitset_iterator.h:216
typename TBitset::size_type size_type
Backing-word type used by the parent bit set.
Definition bitset_iterator.h:19
GAIA_NODISCARD value_type operator->() const
Returns the current bit index for arrow-style access.
Definition bitset_iterator.h:165
GAIA_NODISCARD value_type index() const
Returns the current bit index.
Definition bitset_iterator.h:171
GAIA_NODISCARD bool operator==(const bitset_const_iterator &other) const
Compares iterator positions.
Definition bitset_iterator.h:209
uint32_t value_type
Bit-index value type.
Definition bitset_iterator.h:17
GAIA_NODISCARD value_type operator*() const
Returns the current bit index.
Definition bitset_iterator.h:159
GAIA_NODISCARD bitset_const_iterator operator++(int)
Advances to the next matching bit in the iterator's direction.
Definition bitset_iterator.h:200
bitset_const_iterator(const TBitset &bitset, value_type pos, bool fwd)
Definition bitset_iterator.h:103
bitset_const_iterator & operator++()
Advances to the next matching bit in the iterator's direction.
Definition bitset_iterator.h:177
Fixed-size bit set.
Definition bitset.h:14
GAIA_NODISCARD constexpr uint32_t size() const
Returns the number of bits the bitset can hold.
Definition bitset.h:314
Array with variable size of elements of type.
Definition darray_impl.h:27
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_impl.h:193