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

PeterCDMcLean / BitLib / 16688832879

02 Aug 2025 02:19AM UTC coverage: 71.949% (-6.5%) from 78.485%
16688832879

Pull #18

github

web-flow
Merge 95e25bd88 into 079daa142
Pull Request #18: From string

3451 of 5352 branches covered (64.48%)

Branch coverage included in aggregate %.

346 of 470 new or added lines in 12 files covered. (73.62%)

28 existing lines in 2 files now uncovered.

2438 of 2833 relevant lines covered (86.06%)

16239128.44 hits per line

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

74.79
/include/bitlib/bit-containers/bit_array_base.hpp
1
// ================================= BIT_ARRAY_BASE =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        bit_array_base.hpp
4
// Description: Base implementation for bit_array variants
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9
#ifndef _BIT_ARRAY_BASE_HPP_INCLUDED
10
#define _BIT_ARRAY_BASE_HPP_INCLUDED
11
// ========================================================================== //
12

13
// ================================ PREAMBLE ================================ //
14
// C++ standard library
15
#include <algorithm>
16
#include <bit>
17
#include <cmath>
18
#include <span>
19
#include <string>
20
#include <type_traits>
21
#include <vector>
22

23
// Project sources
24
#include "bitlib/bit-algorithms/bit_algorithm.hpp"
25
#include "bitlib/bit-containers/bit_bitsof.hpp"
26
#include "bitlib/bit-containers/bit_policy.hpp"
27
#include "bitlib/bit-iterator/bit.hpp"
28

29
namespace bit {
30

31
template <typename T, size_t N, typename W, typename Policy>
32
class array_ref;
33

34
template <typename T,
35
          std::size_t N,
36
          typename W,
37
          typename Policy>
38
class array;
39

40
/**
41
 * @brief Base class template for array implementations
42
 *
43
 * This is a CRTP (Curiously Recurring Template Pattern) base class that provides
44
 * common functionality for array variants.
45
 *
46
 * @tparam Derived The derived class (CRTP pattern)
47
 * @tparam T The value type (typically bit_value)
48
 * @tparam W The word type used for storage
49
 * @tparam N The size of the bit array, or std::dynamic_extent for dynamic size
50
 * @tparam Policy The policy for integral conversion (default is typical)
51
 * @tparam Iterators A struct that provides iterator and const_iterator types
52
 */
53
template <typename Derived, typename T, size_t N, typename W, bool resizable, typename Policy, typename Iterators>
54
class array_base : public detail::container_size_storage<std::size_t, resizable, N> {
55
 protected:
56
  constexpr Derived& derived() noexcept {
2,037✔
57
    return static_cast<Derived&>(*this);
2,037✔
58
  }
2,037✔
59

60
  constexpr const Derived& derived() const noexcept {
86✔
61
    return static_cast<const Derived&>(*this);
86✔
62
  }
86✔
63

64
 public:
65
  using detail::container_size_storage<std::size_t, resizable, N>::size;
66
  using word_type = W;
67
  using value_type = T;
68
  using size_type = std::size_t;
69
  using difference_type = std::ptrdiff_t;
70
  using reference = typename std::conditional<std::is_same_v<T, bit_value>, bit_reference<word_type&>, T&>::type;
71
  using const_reference = typename std::conditional<std::is_same_v<T, bit_value>, const bit_reference<const word_type&>, const T&>::type;
72
  using pointer = typename std::conditional<std::is_same_v<T, bit_value>, bit_pointer<word_type>, T&>::type;
73
  using const_pointer = const pointer;
74
  using iterator = Iterators::iterator;
75
  using const_iterator = Iterators::const_iterator;
76

77
  constexpr array_base() noexcept : detail::container_size_storage<std::size_t, resizable, N>() {}
155✔
78
  constexpr array_base(const size_type& extent) noexcept
79
    requires(N == std::dynamic_extent)
80
      : detail::container_size_storage<std::size_t, resizable, N>(extent) {}
123✔
81

82
  // Element access
83
  constexpr reference operator[](size_type pos) {
1,788✔
84
    return derived().begin()[pos];
1,788✔
85
  }
1,788✔
86

87
  constexpr const_reference operator[](size_type pos) const {
88
    return derived().begin()[pos];
89
  }
90

91
  constexpr reference at(size_type pos) {
13✔
92
    if (pos < size()) {
13!
93
      return derived().begin()[pos];
10✔
94
    } else {
10✔
95
      throw std::out_of_range("Position is out of range");
3✔
96
    }
3✔
97
  }
13✔
98

99
  constexpr const_reference at(size_type pos) const {
100
    if (pos < size()) {
101
      return derived().begin()[pos];
102
    } else {
103
      throw std::out_of_range("Position is out of range");
104
    }
105
  }
106

107
  constexpr reference front() {
3✔
108
    return derived().begin()[0];
3✔
109
  }
3✔
110

111
  constexpr const_reference front() const {
112
    return derived().begin()[0];
113
  }
114

115
  constexpr reference back() {
3✔
116
    return derived().begin()[size() - 1];
3✔
117
  }
3✔
118

119
  constexpr const_reference back() const {
120
    return derived().begin()[size() - 1];
121
  }
122

123
  constexpr iterator end() noexcept {
76✔
124
    return derived().begin() + size();
76✔
125
  }
76✔
126

127
  constexpr const_iterator end() const noexcept {
66✔
128
    return const_iterator(derived().begin()) + size();
66✔
129
  }
66✔
130

131
  constexpr const_iterator cbegin() const noexcept {
132
    return const_iterator(derived().begin());
133
  }
134

135
  constexpr const_iterator cend() const noexcept {
136
    return const_iterator(derived().end());
137
  }
138

139
  // Capacity
140
  constexpr bool empty() const noexcept {
4✔
141
    return 0 == size();
4✔
142
  }
4✔
143

144
  constexpr size_type max_size() const noexcept {
1✔
145
    return size();
1✔
146
  }
1✔
147

148
  // String representation
149
  constexpr std::string debug_string() const {
150
    return debug_string(derived().begin(), derived().end());
151
  }
152

153
  constexpr std::string debug_string(const_iterator first, const_iterator last) const {
154
    std::string ret = "";
155
    auto position = 0;
156
    for (auto it = first; it != last; ++it) {
157
      if (position % bitsof<word_type>() == 0 && position != 0) {
158
        ret += " ";
159
      } else if (position % 8 == 0 && position != 0) {
160
        ret += '.';
161
      }
162
      ret += *it == bit1 ? '1' : '0';
163
      ++position;
164
    }
165
    return ret;
166
  }
167

168
  /**
169
   * @brief Slice operations - returns a array_ref
170
   */
171
  constexpr auto operator()(size_type offset, size_type right) const noexcept {
172
    return array_ref<value_type, std::dynamic_extent, const word_type, Policy>(&this->at(offset), right - offset);
173
  }
174

175
  /**
176
   * @brief Slice operations - returns a array_ref
177
   */
178
  constexpr auto operator()(size_type offset, size_type right) noexcept {
8✔
179
    return array_ref<value_type, std::dynamic_extent, word_type, Policy>(&this->at(offset), right - offset);
8✔
180
  }
8✔
181

182
  // Common operations
183
  constexpr void fill(value_type bit_val) noexcept {
39✔
184
    std::fill(derived().begin(), derived().end(), bit_val);
39✔
185
  }
39✔
186

187
  /**
188
   * @brief Explicit conversion to integral types
189
   */
190
  template <std::integral U>
191
  explicit constexpr operator U() const noexcept {
8✔
192
    assert(size() <= bitsof<U>());
8!
193
    U integral;
8✔
194

195
    if constexpr (N == std::dynamic_extent) {
8✔
196
      if (size() > bitsof<U>()) {
2!
197
        Policy::truncation::template to_integral<U, N>(derived(), integral);
×
198
      } else {
2✔
199
        ::bit::copy(derived().begin(), end(), &integral);
2✔
200
      }
2✔
201
      if (size() < bitsof<U>()) {
2!
NEW
202
        Policy::extension::template to_integral<U, N>(detail::uninitialized, derived(), integral);
×
UNCOV
203
      }
×
204
    } else {
6✔
205
      if constexpr (N > bitsof<U>()) {
206
        Policy::truncation::template to_integral<U, N>(derived(), integral);
207
      } else {
6✔
208
        ::bit::copy(derived().begin(), end(), &integral);
6✔
209
      }
6✔
210
      if constexpr (N < bitsof<U>()) {
6✔
211
        Policy::extension::template to_integral<U, N>(detail::uninitialized, derived(), integral);
5✔
212
      }
5✔
213
    }
6✔
214

215
    return integral;
8✔
216
  }
8✔
217

218
  using compatible_bitarray = array<value_type, N, word_type, Policy>;
219

220
  constexpr compatible_bitarray operator~() {
2✔
221
    compatible_bitarray result(detail::uninitialized, size());
2✔
222
    transform(derived().begin(), derived().end(), result.begin(), [](const word_type& bits) -> word_type { return ~bits; });
2✔
223
    return result;
2✔
224
  }
2✔
225

226
  constexpr compatible_bitarray operator|(const bit_sized_range auto& other) const {
1✔
227
    assert(other.size() == size());
1!
228
    compatible_bitarray result(detail::uninitialized, size());
1✔
229
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
230
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
1✔
231
    return result;
1✔
232
  }
1✔
233
  constexpr Derived& operator|=(bit_sized_range auto& other) {
1✔
234
    assert(other.size() == size());
1!
235
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
236
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
1✔
237
    return derived();
1✔
238
  }
1✔
239
  constexpr compatible_bitarray operator&(const bit_sized_range auto& other) const {
1✔
240
    assert(other.size() == size());
1!
241
    compatible_bitarray result(detail::uninitialized, size());
1✔
242
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
243
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
1✔
244
    return result;
1✔
245
  }
1✔
246
  constexpr Derived& operator&=(bit_sized_range auto& other) {
1✔
247
    assert(other.size() == size());
1!
248
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
249
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
1✔
250
    return derived();
1✔
251
  }
1✔
252
  constexpr compatible_bitarray operator^(const bit_sized_range auto& other) const {
1✔
253
    assert(other.size() == size());
1!
254
    compatible_bitarray result(detail::uninitialized, size());
1✔
255
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
256
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
1✔
257
    return result;
1✔
258
  }
1✔
259
  constexpr Derived& operator^=(bit_sized_range auto& other) {
1✔
260
    assert(other.size() == size());
1!
261
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
262
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
1✔
263
    return derived();
1✔
264
  }
1✔
265

266
  friend std::ostream& operator<<(std::ostream& os, const array_base& cv) {
1✔
267
    // Save stream formatting settings
268
    std::ios_base::fmtflags flags = os.flags();
1✔
269
    char fill = os.fill();
1✔
270
    std::streamsize width = os.width();
1✔
271

272
    std::string content;
1✔
273
    switch (flags & std::ios_base::basefield) {
1✔
NEW
274
      case std::ios_base::hex:
×
NEW
275
        content = ::bit::to_string(cv.derived(), ::bit::string::typical(16));
×
NEW
276
        break;
×
NEW
277
      case std::ios_base::oct:
×
NEW
278
        content = ::bit::to_string(cv.derived(), ::bit::string::typical(8));
×
NEW
279
        break;
×
280
      case std::ios_base::dec:
1!
281
        content = ::bit::to_string(cv.derived(), ::bit::string::typical(10));
1✔
282
        break;
1✔
NEW
283
      default:
×
NEW
284
        content = ::bit::to_string(cv.derived(), ::bit::string::typical(2));
×
NEW
285
        break;
×
286
    }
1✔
287

288
    // Clear width to avoid affecting next output
289
    os.width(0);
1✔
290

291
    // Apply padding manually if needed
292
    if (width > static_cast<std::streamsize>(content.size())) {
1!
NEW
293
      std::streamsize pad = width - content.size();
×
NEW
294
      bool left = (flags & std::ios_base::adjustfield) == std::ios_base::left;
×
295

NEW
296
      if (!left) {
×
NEW
297
        os << std::string(pad, fill);
×
NEW
298
      }
×
299

NEW
300
      os << content;
×
301

NEW
302
      if (left) {
×
NEW
303
        os << std::string(pad, fill);
×
NEW
304
      }
×
305
    } else {
1✔
306
      os << content;
1✔
307
    }
1✔
308

309
    return os;
1✔
310
  }
1✔
311

312
 protected:
313
  template <typename U>
314
  constexpr void from_integral(const U& integral) {
63✔
315
    if constexpr (N == std::dynamic_extent) {
316
      if ((size() * bitsof<value_type>()) < bitsof<U>()) {
317
        Policy::truncation::template from_integral<U, N>(derived(), integral);
318
      } else {
319
        ::bit::copy(&integral, &integral + 1, derived().begin());
320
      }
321
      if (bitsof<U>() < (size() * bitsof<value_type>())) {
322
        Policy::extension::template from_integral<U, N>(detail::uninitialized, derived(), integral);
323
      }
324
    } else {
63✔
325
      if constexpr ((N * bitsof<value_type>()) < bitsof<U>()) {
63✔
326
        Policy::truncation::template from_integral<U, N>(derived(), integral);
39✔
327
      } else {
39✔
328
        ::bit::copy(&integral, &integral + 1, derived().begin());
24✔
329
      }
24✔
330
      if constexpr (bitsof<U>() < (N * bitsof<value_type>())) {
331
        Policy::extension::template from_integral<U, N>(detail::uninitialized, derived(), integral);
332
      }
333
    }
63✔
334
  }
63✔
335
};
336

337
constexpr bool operator==(const bit_sized_range auto& lhs, const bit_sized_range auto& rhs) {
40✔
338
  if (lhs.size() != rhs.size()) {
40!
339
    return false;
2✔
340
  }
2✔
341
  return ::bit::equal(lhs.begin(), lhs.end(), rhs.begin());
38✔
342
}
40✔
343

344
}  // namespace bit
345

346
#endif  // _BIT_ARRAY_BASE_HPP_INCLUDED
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