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

PeterCDMcLean / BitLib / 15696616722

17 Jun 2025 02:29AM UTC coverage: 54.11% (+0.6%) from 53.519%
15696616722

Pull #17

github

web-flow
Merge caf45e877 into 0f0b787a1
Pull Request #17: Truncation policy

10137 of 18710 branches covered (54.18%)

Branch coverage included in aggregate %.

212 of 251 new or added lines in 13 files covered. (84.46%)

214 existing lines in 11 files now uncovered.

6062 of 11227 relevant lines covered (53.99%)

7736453.1 hits per line

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

56.63
/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,658,231✔
139
    : _current(other.base()), _position(other.position()) {
16,007,772✔
140
  assert(_position < bitsof<word_type>());
16,007,772!
141
}
16,007,772✔
142

143
template <class Iterator>
144
template <class T>
145
constexpr bit_iterator<Iterator>::bit_iterator(const bit_iterator<T>& other)
50,689✔
146
  requires std::constructible_from<iterator_type, T>
147
    : _current(other.base()), _position(other.position()) {
100,611✔
148
  assert(_position < bitsof<word_type>());
100,611!
149
}
100,611✔
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,741✔
154
    : _current(i), _position(0) {
25,894,291✔
155
}
25,894,291✔
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,151✔
160
    : _current(i), _position((assert(pos < binary_digits<word_type>::value), pos)) {
3,513,550!
161
}
3,513,550✔
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)
249✔
166
  requires std::constructible_from<iterator_type, word_type*>
167
    : _current(ptr._current), _position(ptr.position()) {
542✔
168
  assert(_position < bitsof<word_type>());
542!
169
}
542✔
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,261✔
174
    : _current(other.base().base()), _position(other.base().index() * bitsof<typename bit_word_pointer_adapter<T, Iterator>::value_type>() + other.position()) {
4,522✔
175
  assert(_position < bitsof<word_type>());
4,522!
176
}
4,522✔
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,486,076✔
223
  constexpr difference_type digits = binary_digits<word_type>::value;
22,486,076✔
224
  const difference_type sum = _position + n;
22,486,076✔
225
  difference_type diff = sum / digits;
22,486,076✔
226
  if (sum < 0 && diff * digits != sum) {
22,486,076!
227
    --diff;
×
UNCOV
228
  }
229
  return reference(*std::next(_current, diff), sum - diff * digits);
44,972,152✔
230
}
11,243,038✔
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,483✔
244
    _position = 0;
188,012,483✔
245
  }
93,897,898✔
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,253,042✔
281
  constexpr difference_type digits = binary_digits<word_type>::value;
2,253,042✔
282
  const difference_type sum = _position + n;
2,253,042✔
283
  difference_type diff = sum / digits;
2,253,042✔
284
  if (sum < 0 && diff * digits != sum) {
2,253,042!
285
    --diff;
×
UNCOV
286
  }
287
  return bit_iterator(std::next(_current, diff), sum - diff * digits);
4,529,116✔
288
}
1,115,005✔
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,681✔
293
  constexpr difference_type digits = binary_digits<word_type>::value;
931,681✔
294
  const difference_type sum = _position - n;
931,681✔
295
  difference_type diff = sum / digits;
931,681✔
296
  if (sum < 0 && diff * digits != sum) {
931,681!
297
    --diff;
713,632✔
298
  }
489,546✔
299
  return bit_iterator(std::next(_current, diff), sum - diff * digits);
1,597,299✔
300
}
598,872✔
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,175✔
305
  constexpr difference_type digits = binary_digits<word_type>::value;
4,283,175✔
306
  const difference_type sum = _position + n;
4,283,175✔
307
  difference_type diff = sum / digits;
4,283,175✔
308
  if (sum < 0 && diff * digits != sum) {
4,283,175!
309
    --diff;
525,362✔
310
  }
393,922✔
311
  _current = std::next(_current, diff);
7,421,667✔
312
  _position = (sum - diff * digits);
4,283,175✔
313
  return *this;
7,421,667✔
314
}
1,144,683✔
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,729✔
334
  constexpr difference_type digits = binary_digits<word_type>::value;
2,064,729✔
335
  return (_current - other._current) * digits + (_position - other._position);
2,064,729✔
336
}
1,024,765✔
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,312,553✔
342
  return _current;
71,312,553✔
343
}
34,808,166✔
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,859,270✔
353
  return _position;
50,859,270✔
354
}
23,834,950✔
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