• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PeterCDMcLean / BitLib / 16782263096

06 Aug 2025 04:07PM UTC coverage: 75.79% (+1.0%) from 74.757%
16782263096

Pull #27

github

web-flow
Merge 9a655e0cd into 3fead7b1b
Pull Request #27: Minor tweaks and improvements

3322 of 5072 branches covered (65.5%)

Branch coverage included in aggregate %.

36 of 44 new or added lines in 5 files covered. (81.82%)

4 existing lines in 2 files now uncovered.

2551 of 2677 relevant lines covered (95.29%)

29025127.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.28
/include/bitlib/bit-iterator/bit_iterator.hpp
1
// ============================== BIT ITERATOR ============================== //
2
// Project:         The C++ Bit Library
3
// Name:            bit_iterator.hpp
4
// Description:     A class representing an iterator on bit sequences
5
// Creator:         Vincent Reverdy
6
// Contributor(s):  Vincent Reverdy [2015-2017]
7
// License:         BSD 3-Clause License
8
// ========================================================================== //
9
#ifndef _BIT_ITERATOR_HPP_INCLUDED
10
#define _BIT_ITERATOR_HPP_INCLUDED
11
// ========================================================================== //
12

13

14

15
// ================================ PREAMBLE ================================ //
16
// C++ standard library
17
#include <compare>
18
#include <concepts>
19
#include <cstddef>
20
#include <iterator>
21
#include <type_traits>
22

23
#include "bitlib/bit-containers/bit_bitsof.hpp"
24
#include "bitlib/bit_concepts.hpp"
25
// Project sources
26
#include "bit_details.hpp"
27
#include "bit_reference.hpp"
28
// Third-party libraries
29
// Miscellaneous
30
namespace bit {
31

32
/* ****************************** BIT ITERATOR ****************************** */
33

34
template <typename target_word_ptr, typename source_word_ptr>
35
class bit_word_pointer_adapter;
36

37
// Bit iterator class definition
38
template <class Iterator>
39
class bit_iterator
40
{
41
  template <class>
42
  friend class bit_iterator;
43

44
  // Assertions
45
 private:
46
  using _traits_t = _cv_iterator_traits<Iterator>;
47
  static_assert(binary_digits<std::iter_value_t<Iterator>>::value, "");
48

49
  // Types
50
 public:
51
  using iterator_type = Iterator;
52
  using word_type = std::iter_value_t<Iterator>;
53
  using iterator_category = typename _traits_t::iterator_category;
54
  using value_type = bit_value;
55
  using difference_type = std::ptrdiff_t;
56
  using pointer = bit_pointer<word_type>;
57
  using reference = bit_reference<typename _traits_t::reference>;  // typename _traits_t::reference;
58
  using size_type = std::size_t;
59
  using mask_type = std::make_unsigned_t<std::remove_cv_t<word_type>>;
60

61
  // Lifecycle
62
 public:
63
  constexpr bit_iterator();
64
  constexpr bit_iterator(const bit_iterator<Iterator>& other);
65
  template <class T>
66
  constexpr bit_iterator(const bit_iterator<T>& other)
67
    requires std::constructible_from<iterator_type, T>;
68
  explicit constexpr bit_iterator(iterator_type i);
69
  constexpr bit_iterator(iterator_type i, size_type pos);
70
  explicit constexpr bit_iterator(const pointer& ptr)
71
    requires std::constructible_from<iterator_type, word_type*>;
72

73
  template <typename T>
74
  constexpr bit_iterator(const bit_iterator<bit_word_pointer_adapter<T, Iterator>>& other);
75

76
  // Assignment
77
 public:
78
  constexpr bit_iterator& operator=(const bit_iterator<Iterator>& other);
79
  template <class T>
80
  constexpr bit_iterator& operator=(const bit_iterator<T>& other);
81

82
  // Access
83
 public:
84
  constexpr reference operator*() const noexcept;
85
  constexpr pointer operator->() const noexcept;
86
  constexpr reference operator[](difference_type n) const;
87

88
  // Increment and decrement operators
89
 public:
90
  constexpr bit_iterator& operator++();
91
  constexpr bit_iterator& operator--();
92
  constexpr bit_iterator operator++(int);
93
  constexpr bit_iterator operator--(int);
94
  constexpr bit_iterator operator+(difference_type n) const;
95
  constexpr bit_iterator operator-(difference_type n) const;
96
  constexpr bit_iterator& operator+=(difference_type n);
97
  constexpr bit_iterator& operator-=(difference_type n);
98
  constexpr difference_type operator-(const bit_iterator&) const;
99

100
  // Underlying details
101
 public:
102
  constexpr iterator_type base() const;
103
  constexpr iterator_type address() const;
104
  constexpr size_type position() const noexcept;
105

106
  auto operator<=>(const bit_iterator&) const = default;
107
  // Implementation details: data members
108
 private:
109
  iterator_type _current;
110
  size_type _position;
111

112
  // Non-member arithmetic operators
113
  template <class T>
114
  friend constexpr bit_iterator<T> operator+(
115
      typename bit_iterator<T>::difference_type n,
116
      const bit_iterator<T>& i);
117
  template <class T, class U>
118
  friend constexpr typename std::common_type<
119
      typename bit_iterator<T>::difference_type,
120
      typename bit_iterator<U>::difference_type>::type
121
  operator-(
122
      const bit_iterator<T>& lhs,
123
      const bit_iterator<U>& rhs);
124
};
125
/* ************************************************************************** */
126

127

128

129
// ------------------------ BIT ITERATOR: LIFECYCLE ------------------------- //
130
// Implicitly default constructs a bit iterator
131
template <class Iterator>
132
constexpr bit_iterator<Iterator>::bit_iterator()
133
    : _current(), _position() {
134
}
135

136
// Implicitly constructs a bit iterator from another bit iterator
137
template <class Iterator>
138
constexpr bit_iterator<Iterator>::bit_iterator(const bit_iterator<Iterator>& other)
7,629,485✔
139
    : _current(other.base()), _position(other.position()) {
15,951,050✔
140
  assert(_position < bitsof<word_type>());
15,951,050!
141
}
15,951,050✔
142

143
template <class Iterator>
144
template <class T>
145
constexpr bit_iterator<Iterator>::bit_iterator(const bit_iterator<T>& other)
51,284✔
146
  requires std::constructible_from<iterator_type, T>
147
    : _current(other.base()), _position(other.position()) {
101,206✔
148
  assert(_position < bitsof<word_type>());
101,206!
149
}
101,206✔
150

151
// Explicitly constructs an aligned bit iterator from an iterator
152
template <class Iterator>
153
constexpr bit_iterator<Iterator>::bit_iterator(const iterator_type i)
12,953,092✔
154
    : _current(i), _position(0) {
25,907,051✔
155
}
25,907,051✔
156

157
// Explicitly constructs an unaligned bit iterator from an iterator
158
template <class Iterator>
159
constexpr bit_iterator<Iterator>::bit_iterator(const iterator_type i, size_type pos)
1,621,610✔
160
    : _current(i), _position((assert(pos < binary_digits<word_type>::value), pos)) {
3,486,449!
161
}
3,486,449✔
162

163
// Explicitly constructs an unaligned bit iterator from a pointer
164
template <class Iterator>
165
constexpr bit_iterator<Iterator>::bit_iterator(const pointer& ptr)
755✔
166
  requires std::constructible_from<iterator_type, word_type*>
167
    : _current(ptr._current), _position(ptr.position()) {
1,554✔
168
  assert(_position < bitsof<word_type>());
1,554!
169
}
1,554✔
170

171
template <class Iterator>
172
template <typename T>
173
constexpr bit_iterator<Iterator>::bit_iterator(const bit_iterator<bit_word_pointer_adapter<T, Iterator>>& other)
2,266✔
174
    : _current(other.base().base()), _position(other.base().index() * bitsof<typename bit_word_pointer_adapter<T, Iterator>::value_type>() + other.position()) {
4,532✔
175
  assert(_position < bitsof<word_type>());
4,532!
176
}
4,532✔
177
// -------------------------------------------------------------------------- //
178

179

180

181
// ------------------------ BIT ITERATOR: ASSIGNMENT ------------------------ //
182
// Assigns a bit iterator to the bit iterator
183
template <class Iterator>
184
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator=(
112,334✔
185
    const bit_iterator<Iterator>& other) {
122,102✔
186
  _current = other._current;
234,436✔
187
  _position = other._position;
234,436✔
188
  assert(_position < bitsof<word_type>());
234,436!
189
  return *this;
234,436✔
190
}
122,102✔
191

192
// Assigns a bit iterator to the bit iterator
193
template <class Iterator>
194
template <class T>
195
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator=(
196
    const bit_iterator<T>& other) {
197
  _current = other._current;
198
  _position = other._position;
199
  assert(_position < bitsof<word_type>());
200
  return *this;
201
}
202
// -------------------------------------------------------------------------- //
203

204

205

206
// -------------------------- BIT ITERATOR: ACCESS -------------------------- //
207
// Gets a bit reference from the bit iterator
208
template <class Iterator>
209
constexpr typename bit_iterator<Iterator>::reference
210
bit_iterator<Iterator>::operator*() const noexcept {
4,294,967,294✔
211
  return reference(*_current, _position);
4,294,967,294✔
212
}
2,147,483,647✔
213

214
// Gets a pointer to a bit
215
template <class Iterator>
216
constexpr typename bit_iterator<Iterator>::pointer bit_iterator<Iterator>::operator->() const noexcept {
217
  return pointer(&*_current, _position);
218
}
219

220
// Gets a bit reference, decrementing or incrementing the iterator
221
template <class Iterator>
222
constexpr typename bit_iterator<Iterator>::reference bit_iterator<Iterator>::operator[](difference_type n) const {
22,487,760✔
223
  constexpr difference_type digits = binary_digits<word_type>::value;
22,487,760✔
224
  const difference_type sum = _position + n;
22,487,760✔
225
  difference_type diff = sum / digits;
22,487,760✔
226
  if (sum < 0 && diff * digits != sum) {
22,487,760!
UNCOV
227
    --diff;
×
UNCOV
228
  }
229
  return reference(*std::next(_current, diff), sum - diff * digits);
44,975,520✔
230
}
11,243,880✔
231
// -------------------------------------------------------------------------- //
232

233
// ------------- BIT ITERATOR: INCREMENT AND DECREMENT OPERATORS ------------ //
234
// Increments the bit iterator and returns it
235
template <class Iterator>
236
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator++() {
4,294,967,294✔
237
  constexpr auto digits = binary_digits<word_type>::value;
4,294,967,294✔
238
  _position = (_position + 1) % digits;
4,294,967,294✔
239
  if (0 == _position) {
4,294,967,294!
240
    ++_current;
188,012,483✔
241
  }
93,897,898✔
242
  return *this;
4,294,967,294✔
243
}
2,147,483,647✔
244

245
// Decrements the bit iterator and returns it
246
template <class Iterator>
247
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator--() {
248
  constexpr size_type digits = binary_digits<word_type>::value;
249
  if (0 == _position) {
250
    --_current;
251
  }
252
  _position = (_position - 1) % digits;
253
  return *this;
254
}
255

256
// Increments the bit iterator and returns the old one
257
template <class Iterator>
258
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator++(int) {
259
  bit_iterator old = *this;
260
  ++(*this);
261
  return old;
262
}
263

264
// Decrements the bit iterator and returns the old one
265
template <class Iterator>
266
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator--(int) {
267
  bit_iterator old = *this;
268
  --(*this);
269
  return old;
270
}
271

272
// Looks forward several bits and gets an iterator at this position
273
template <class Iterator>
274
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator+(difference_type n) const {
2,264,331✔
275
  constexpr difference_type digits = binary_digits<word_type>::value;
2,264,331✔
276
  const difference_type sum = _position + n;
2,264,331✔
277
  const difference_type diff = (sum - (n < 0) * (digits - 1)) / digits;
2,264,331✔
278
  const size_type new_pos = static_cast<size_t>(sum) % static_cast<size_t>(digits);
2,264,331✔
279
  return bit_iterator(std::next(_current, diff), new_pos);
4,551,665✔
280
}
1,120,664✔
281

282
// Looks backward several bits and gets an iterator at this position
283
template <class Iterator>
284
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator-(difference_type n) const {
893,285✔
285
  constexpr difference_type digits = binary_digits<word_type>::value;
893,285✔
286
  const difference_type sum = _position - n;
893,285✔
287
  const difference_type diff = (sum - (n > 0) * (digits - 1)) / digits;
893,285✔
288
  const size_type new_pos = static_cast<size_t>(sum) % static_cast<size_t>(digits);
893,285✔
289
  return bit_iterator(std::next(_current, diff), new_pos);
1,520,555✔
290
}
579,650✔
291

292
// Increments the iterator by several bits and returns it
293
template <class Iterator>
294
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator+=(difference_type n) {
4,283,077✔
295
  constexpr difference_type digits = binary_digits<word_type>::value;
4,283,077✔
296
  const difference_type sum = _position + n;
4,283,077✔
297
  const difference_type diff = (sum - (n < 0) * (digits - 1)) / digits;
4,283,077✔
298
  const size_type new_pos = static_cast<size_t>(sum) % static_cast<size_t>(digits);
4,283,077✔
299
  _current = std::next(_current, diff);
7,421,534✔
300
  _position = new_pos;
4,283,077✔
301
  return *this;
7,421,534✔
302
}
1,144,620✔
303

304
// Decrements the iterator by several bits and returns it
305
template <class Iterator>
306
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator-=(difference_type n) {
281,256✔
307
  constexpr difference_type digits = binary_digits<word_type>::value;
281,256✔
308
  const difference_type sum = _position - n;
281,256✔
309
  const difference_type diff = (sum - (n > 0) * (digits - 1)) / digits;
281,256✔
310
  const size_type new_pos = static_cast<size_t>(sum) % static_cast<size_t>(digits);
281,256✔
311
  _current = std::next(_current, diff);
423,738✔
312
  _position = new_pos;
281,256✔
313
  return *this;
423,738✔
314
}
138,774✔
315
// -------------------------------------------------------------------------- //
316

317
template <class Iterator>
318
constexpr bit_iterator<Iterator>::difference_type
319
bit_iterator<Iterator>::operator-(const bit_iterator<Iterator>& other) const {
2,073,403✔
320
  constexpr difference_type digits = binary_digits<word_type>::value;
2,073,403✔
321
  return (_current - other._current) * digits + (_position - other._position);
2,073,403✔
322
}
1,029,117✔
323

324
// -------------------- BIT ITERATOR: UNDERLYING DETAILS -------------------- //
325
// Returns a copy of the underlying iterator
326
template <class Iterator>
327
constexpr typename bit_iterator<Iterator>::iterator_type bit_iterator<Iterator>::base() const {
72,164,922✔
328
  return _current;
72,164,922✔
329
}
35,233,894✔
330

331
template <class Iterator>
332
constexpr typename bit_iterator<Iterator>::iterator_type bit_iterator<Iterator>::address() const {
333
  return _current;
334
}
335

336
// Returns the position of the bit within the underlying word
337
template <class Iterator>
338
constexpr typename bit_iterator<Iterator>::size_type bit_iterator<Iterator>::position() const noexcept {
50,825,499✔
339
  return _position;
50,825,499✔
340
}
23,818,181✔
341

342
// -------------- BIT ITERATOR: NON-MEMBER ARITHMETIC OPERATORS ------------- //
343
// Advances the bit iterator several times
344
template <class T>
345
constexpr bit_iterator<T> operator+(typename bit_iterator<T>::difference_type n, const bit_iterator<T>& i) {
346
  return i + n;
347
}
348

349
// Computes the distance in bits separating two bit iterators
350
template <class T, class U>
351
constexpr typename std::common_type<
352
    typename bit_iterator<T>::difference_type,
353
    typename bit_iterator<U>::difference_type>::type
354
operator-(const bit_iterator<T>& lhs, const bit_iterator<U>& rhs) {
355
  using lhs_utype = typename bit_iterator<T>::word_type;
356
  using rhs_utype = typename bit_iterator<U>::word_type;
357
  using lhs_type = typename bit_iterator<T>::difference_type;
358
  using rhs_type = typename bit_iterator<U>::difference_type;
359
  using difference_type = typename std::common_type<lhs_type, rhs_type>::type;
360
  constexpr difference_type lhs_digits = binary_digits<lhs_utype>::value;
361
  constexpr difference_type rhs_digits = binary_digits<rhs_utype>::value;
362
  constexpr difference_type digits = rhs_digits;
363
  static_assert(lhs_digits == rhs_digits, "");
364
  const difference_type main = lhs._current - rhs._current;
365
  return main * digits + (lhs._position - rhs._position);
366
}
367

368
static_assert(bit_iterator_c<bit_iterator<uint8_t*>>, "bit_iterator does not satisfy bit_iterator_c concept!");
369
static_assert(bit_pointer_c<bit_pointer<uint8_t>, bit_reference<uint8_t&>>, "bit_pointer does not satisfy bit_pointer_c concept!");
370
static_assert(bit_iterator_c<bit_pointer<uint8_t>>, "bit_pointer does not satisfy bit_iterator_c concept!");
371

372
// ========================================================================== //
373
} // namespace bit
374
#endif // _BIT_ITERATOR_HPP_INCLUDED
375
// ========================================================================== //
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc