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

PeterCDMcLean / BitLib / 15670359432

16 Jun 2025 02:23AM UTC coverage: 54.034% (+0.5%) from 53.519%
15670359432

Pull #12

github

web-flow
Merge c9a3aeb47 into 0f0b787a1
Pull Request #12: Add a bounds type for SystemVerilog style slicing

10319 of 19098 branches covered (54.03%)

Branch coverage included in aggregate %.

94 of 110 new or added lines in 3 files covered. (85.45%)

143 existing lines in 11 files now uncovered.

6061 of 11216 relevant lines covered (54.04%)

7713859.73 hits per line

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

56.91
/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,657,484✔
139
    : _current(other.base()), _position(other.position()) {
16,006,210✔
140
  assert(_position < bitsof<word_type>());
16,006,210!
141
}
16,006,210✔
142

143
template <class Iterator>
144
template <class T>
145
constexpr bit_iterator<Iterator>::bit_iterator(const bit_iterator<T>& other)
50,614✔
146
  requires std::constructible_from<iterator_type, T>
147
    : _current(other.base()), _position(other.position()) {
100,536✔
148
  assert(_position < bitsof<word_type>());
100,536!
149
}
100,536✔
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,946,874✔
154
    : _current(i), _position(0) {
25,895,042✔
155
}
25,895,042✔
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,635,065✔
160
    : _current(i), _position((assert(pos < binary_digits<word_type>::value), pos)) {
3,513,380!
161
}
3,513,380✔
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)
274✔
166
  requires std::constructible_from<iterator_type, word_type*>
167
    : _current(ptr._current), _position(ptr.position()) {
592✔
168
  assert(_position < bitsof<word_type>());
592!
169
}
592✔
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,262✔
174
    : _current(other.base().base()), _position(other.base().index() * bitsof<typename bit_word_pointer_adapter<T, Iterator>::value_type>() + other.position()) {
4,524✔
175
  assert(_position < bitsof<word_type>());
4,524!
176
}
4,524✔
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,333✔
185
    const bit_iterator<Iterator>& other) {
122,101✔
186
  _current = other._current;
234,434✔
187
  _position = other._position;
234,434✔
188
  assert(_position < bitsof<word_type>());
234,434!
189
  return *this;
234,434✔
190
}
122,101✔
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,019✔
223
  constexpr difference_type digits = binary_digits<word_type>::value;
22,487,019✔
224
  const difference_type sum = _position + n;
22,487,019✔
225
  difference_type diff = sum / digits;
22,487,019✔
226
  if (sum < 0 && diff * digits != sum) {
22,487,019!
227
    --diff;
×
UNCOV
228
  }
229
  return reference(*std::next(_current, diff), sum - diff * digits);
44,973,557✔
230
}
11,243,750✔
231
// -------------------------------------------------------------------------- //
232

233

234

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

249
// Decrements the bit iterator and returns it
250
template <class Iterator>
251
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator--() {
252
  constexpr size_type digits = binary_digits<word_type>::value;
253
  if (_position) {
254
    --_position;
255
  } else {
256
    --_current;
257
    _position = digits - 1;
258
  }
259
  return *this;
260
}
261

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

270
// Decrements the bit iterator and returns the old one
271
template <class Iterator>
272
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator--(int) {
273
  bit_iterator old = *this;
274
  --(*this);
275
  return old;
276
}
277

278
// Looks forward several bits and gets an iterator at this position
279
template <class Iterator>
280
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator+(difference_type n) const {
2,252,884✔
281
  constexpr difference_type digits = binary_digits<word_type>::value;
2,252,884✔
282
  const difference_type sum = _position + n;
2,252,884✔
283
  difference_type diff = sum / digits;
2,252,884✔
284
  if (sum < 0 && diff * digits != sum) {
2,252,884!
285
    --diff;
×
UNCOV
286
  }
287
  return bit_iterator(std::next(_current, diff), sum - diff * digits);
4,528,798✔
288
}
1,114,927✔
289

290
// Looks backward several bits and gets an iterator at this position
291
template <class Iterator>
292
constexpr bit_iterator<Iterator> bit_iterator<Iterator>::operator-(difference_type n) const {
931,673✔
293
  constexpr difference_type digits = binary_digits<word_type>::value;
931,673✔
294
  const difference_type sum = _position - n;
931,673✔
295
  difference_type diff = sum / digits;
931,673✔
296
  if (sum < 0 && diff * digits != sum) {
931,673✔
297
    --diff;
713,630✔
298
  }
489,545✔
299
  return bit_iterator(std::next(_current, diff), sum - diff * digits);
1,597,283✔
300
}
598,868✔
301

302
// Increments the iterator by several bits and returns it
303
template <class Iterator>
304
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator+=(difference_type n) {
4,283,123✔
305
  constexpr difference_type digits = binary_digits<word_type>::value;
4,283,123✔
306
  const difference_type sum = _position + n;
4,283,123✔
307
  difference_type diff = sum / digits;
4,283,123✔
308
  if (sum < 0 && diff * digits != sum) {
4,283,123!
309
    --diff;
525,362✔
310
  }
393,922✔
311
  _current = std::next(_current, diff);
7,421,589✔
312
  _position = (sum - diff * digits);
4,283,123✔
313
  return *this;
7,421,589✔
314
}
1,144,657✔
315

316
// Decrements the iterator by several bits and returns it
317
template <class Iterator>
318
constexpr bit_iterator<Iterator>& bit_iterator<Iterator>::operator-=(difference_type n) {
281,092✔
319
  constexpr difference_type digits = binary_digits<word_type>::value;
281,092✔
320
  const difference_type sum = _position - n;
281,092✔
321
  difference_type diff = sum / digits;
281,092✔
322
  if (sum < 0 && diff * digits != sum) {
281,092✔
323
    --diff;
196,971✔
324
  }
97,488✔
325
  _current = std::next(_current, diff);
423,506✔
326
  _position = (sum - diff * digits);
281,092✔
327
  return *this;
423,506✔
328
}
138,678✔
329
// -------------------------------------------------------------------------- //
330

331
template <class Iterator>
332
constexpr bit_iterator<Iterator>::difference_type
333
bit_iterator<Iterator>::operator-(const bit_iterator<Iterator>& other) const {
2,064,568✔
334
  constexpr difference_type digits = binary_digits<word_type>::value;
2,064,568✔
335
  return (_current - other._current) * digits + (_position - other._position);
2,064,568✔
336
}
1,024,684✔
337

338
// -------------------- BIT ITERATOR: UNDERLYING DETAILS -------------------- //
339
// Returns a copy of the underlying iterator
340
template <class Iterator>
341
constexpr typename bit_iterator<Iterator>::iterator_type bit_iterator<Iterator>::base() const {
71,310,578✔
342
  return _current;
71,310,578✔
343
}
34,807,182✔
344

345
template <class Iterator>
346
constexpr typename bit_iterator<Iterator>::iterator_type bit_iterator<Iterator>::address() const {
347
  return _current;
348
}
349

350
// Returns the position of the bit within the underlying word
351
template <class Iterator>
352
constexpr typename bit_iterator<Iterator>::size_type bit_iterator<Iterator>::position() const noexcept {
50,857,151✔
353
  return _position;
50,857,151✔
354
}
23,833,894✔
355

356
// -------------- BIT ITERATOR: NON-MEMBER ARITHMETIC OPERATORS ------------- //
357
// Advances the bit iterator several times
358
template <class T>
359
constexpr bit_iterator<T> operator+(typename bit_iterator<T>::difference_type n, const bit_iterator<T>& i) {
360
  return i + n;
361
}
362

363
// Computes the distance in bits separating two bit iterators
364
template <class T, class U>
365
constexpr typename std::common_type<
366
    typename bit_iterator<T>::difference_type,
367
    typename bit_iterator<U>::difference_type>::type
368
operator-(const bit_iterator<T>& lhs, const bit_iterator<U>& rhs) {
369
  using lhs_utype = typename bit_iterator<T>::word_type;
370
  using rhs_utype = typename bit_iterator<U>::word_type;
371
  using lhs_type = typename bit_iterator<T>::difference_type;
372
  using rhs_type = typename bit_iterator<U>::difference_type;
373
  using difference_type = typename std::common_type<lhs_type, rhs_type>::type;
374
  constexpr difference_type lhs_digits = binary_digits<lhs_utype>::value;
375
  constexpr difference_type rhs_digits = binary_digits<rhs_utype>::value;
376
  constexpr difference_type digits = rhs_digits;
377
  static_assert(lhs_digits == rhs_digits, "");
378
  const difference_type main = lhs._current - rhs._current;
379
  return main * digits + (lhs._position - rhs._position);
380
}
381

382
static_assert(bit_iterator_c<bit_iterator<uint8_t*>>, "bit_iterator does not satisfy bit_iterator_c concept!");
383
static_assert(bit_pointer_c<bit_pointer<uint8_t>, bit_reference<uint8_t&>>, "bit_pointer does not satisfy bit_pointer_c concept!");
384
static_assert(bit_iterator_c<bit_pointer<uint8_t>>, "bit_pointer does not satisfy bit_iterator_c concept!");
385

386
// ========================================================================== //
387
} // namespace bit
388
#endif // _BIT_ITERATOR_HPP_INCLUDED
389
// ========================================================================== //
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

© 2025 Coveralls, Inc