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

PeterCDMcLean / BitLib / 14987214130

13 May 2025 03:02AM UTC coverage: 49.385% (-46.9%) from 96.333%
14987214130

Pull #7

github

web-flow
Merge aad228108 into 09dd4e61e
Pull Request #7: Add github workflow targets for warnings

5155 of 10638 branches covered (48.46%)

Branch coverage included in aggregate %.

39 of 70 new or added lines in 1 file covered. (55.71%)

128 existing lines in 10 files now uncovered.

5325 of 10583 relevant lines covered (50.32%)

3238286.52 hits per line

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

81.82
/include/bitlib/bit-containers/bit_array.hpp
1
// ================================= BIT_ARRAY =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        bit_array.hpp
4
// Description: Implementation of bit_array
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9
#ifndef _BIT_ARRAY_HPP_INCLUDED
10
#define _BIT_ARRAY_HPP_INCLUDED
11
// ========================================================================== //
12

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

24
// Project sources
25
#include "bitlib/bit-algorithms/bit_algorithm.hpp"
26
#include "bitlib/bit-containers/bit_array_base.hpp"
27
#include "bitlib/bit-containers/bit_bitsof.hpp"
28
#include "bitlib/bit-containers/bit_span.hpp"
29
#include "bitlib/bit-iterator/bit.hpp"
30
#include "bitlib/bit_concepts.hpp"
31

32
namespace bit {
33
// ========================================================================== //
34

35
namespace detail {
36

37
template <typename value_type, typename word_type, std::size_t N>
UNCOV
38
constexpr size_t Words() { return (N * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>(); }
×
39

40
template <typename value_type, typename word_type, std::size_t N>
41
using bit_array_d_it = typename std::conditional<std::is_same_v<value_type, bit_value>,
42
                                                 bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>,
43
                                                 typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>::type;
44

45
template <typename value_type, typename word_type, std::size_t N>
46
using bit_array_d_cit = typename std::conditional<std::is_same_v<value_type, bit_value>,
47
                                                  bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::const_iterator>,
48
                                                  typename std::array<const word_type, Words<value_type, word_type, N>()>::const_iterator>::type;
49
}  // namespace detail
50

51
template <typename T = bit_value,
52
          std::size_t N = std::dynamic_extent,
53
          std::align_val_t V = std::align_val_t(alignof(T)),
54
          typename W = std::conditional_t<std::is_same_v<T, bit_value>, uint8_t, T>>
55
class bit_array : public bit_array_base<bit_array<T, N, V, W>, T, W, detail::bit_array_d_it<T, W, N>, detail::bit_array_d_cit<T, W, N>> {
56
 public:
57
  using base = bit_array_base<bit_array<T, N, V, W>, T, W, detail::bit_array_d_it<T, W, N>, detail::bit_array_d_cit<T, W, N>>;
58
  using base::end;
59
  using typename base::const_iterator;
60
  using typename base::const_pointer;
61
  using typename base::const_reference;
62
  using typename base::difference_type;
63
  using typename base::iterator;
64
  using typename base::pointer;
65
  using typename base::reference;
66
  using typename base::size_type;
67
  using typename base::value_type;
68
  using typename base::word_type;
69

70
  static constexpr std::size_t bits = N * bitsof<T>();
71

72
 protected:
UNCOV
73
  static constexpr std::size_t Words(std::size_t size_) {
×
UNCOV
74
    return (size_ * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>();
×
UNCOV
75
  }
×
76

77
 private:
78
  static constexpr std::size_t Words_ = Words(N);
79
  static constexpr std::size_t AlignedWords = (((Words_ * sizeof(word_type) + static_cast<size_t>(V) - 1) & ~(static_cast<size_t>(V) - 1)) + sizeof(word_type) - 1) / sizeof(word_type);
80

81
  alignas(static_cast<size_t>(V)) std::array<word_type, AlignedWords> storage;
82

83
 public:
84
  /*
85
  * Constructors, copies and moves...
86
  */
87
  constexpr bit_array() noexcept : storage{} {}
34✔
88

89
  constexpr bit_array(value_type bit_val) : storage{} {
2✔
90
    this->fill(bit_val);
2✔
91
  }
2✔
92

93
  template <std::integral U>
94
  constexpr bit_array(const U& integral)
95
    requires(bitsof<U>() <= bits)
96
  {
97
    std::memcpy(&storage[0], &integral, sizeof(integral));
98

99
    bool sign_extend = false;
100
    if constexpr (std::is_signed_v<U>) {
101
      sign_extend = (integral & (1 << (bitsof<U>() - 1))) ? true : false;
102
    }
103
    if (sign_extend) {
104
      for (auto it = begin() + bitsof<U>(); it != end(); ++it) {
105
        *it = bit1;
106
      }
107
    } else {
108
      for (auto it = begin() + bitsof<U>(); it != end(); ++it) {
109
        *it = bit0;
110
      }
111
    }
112
  }
113

114
  constexpr bit_array(const bit_array<T, N, V, W>& other) = default;
115

116
  constexpr bit_array(const bit_array<T, N, V, W>&& other) noexcept
117
      : storage(other.storage) {}
1✔
118

119
  constexpr bit_array(const bit_sized_range auto& other) {
2✔
120
    if (other.size() != this->size()) [[unlikely]] {
2✔
121
      throw std::invalid_argument("other bit_range contains an invalid number of bits for bit_array.");
1✔
122
    }
1✔
123
    ::bit::copy(other.begin(), other.end(), this->begin());
1✔
124
  };
1✔
125

126
  constexpr bit_array(const std::initializer_list<value_type> init)
127
    requires(!std::is_same_v<value_type, word_type>)
128
  {
8✔
129
    if (init.size() != bitsof(*this)) [[unlikely]] {
8!
130
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
1✔
131
    }
1✔
132
    std::copy(init.begin(), init.end(), this->begin());
7✔
133
  }
7✔
134

135
  constexpr bit_array(const std::initializer_list<bool> init) {
136
    if (init.size() != bitsof(*this)) [[unlikely]] {
137
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
138
    }
139
    std::copy(init.begin(), init.end(), this->begin());
140
  }
141

142
  constexpr bit_array(const std::initializer_list<word_type> init) : storage{} {
143
    // Make sure we handle the case where init.size() != Words
144
    auto it = init.begin();
145
    for (size_type i = 0; i < std::min(AlignedWords, init.size()); ++i, ++it) {
146
      storage[i] = *it;
147
    }
148
  }
149

150
  constexpr bit_array(const std::string_view s)
151
    requires(std::is_same_v<value_type, bit_value>)
152
  {
2✔
153
    if (bitsof(*this) != static_cast<size_t>(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] {
2!
154
      throw std::invalid_argument("String contains an invalid number of bits for bit_array.");
1✔
155
    };
1✔
156
    size_type i = 0;
1✔
157
    for (char c : s) {
13!
158
      if (c == '0') {
13!
159
        begin()[i++] = bit0;
5✔
160
      } else if (c == '1') {
8!
161
        begin()[i++] = bit1;
6✔
162
      }
6✔
163
    }
13✔
164
  }
1✔
165

166
  ~bit_array() = default;
167
  /*
168
    * Assignment
169
    */
170
  constexpr bit_array& operator=(const bit_array<T, N, V, W>& other) = default;
171

172
  constexpr bit_array& operator=(const bit_sized_range auto& other) {
173
    if (other.size() != this->size()) [[unlikely]] {
174
      throw std::invalid_argument("other bit_sized_range contains an invalid number of bits for bit_array.");
175
    }
176
    ::bit::copy(other.begin(), other.end(), this->begin());
177
    return *this;
178
  };
179

180
  constexpr bit_array& operator=(bit_array<T, N, V, W>&& other) noexcept {
1✔
181
    std::copy(other.storage.begin(), other.storage.end(), storage.begin());
1✔
182
    return *this;
1✔
183
  }
1✔
184

185
  constexpr word_type* data() noexcept {
1✔
186
    return size() ? storage.data() : nullptr;
1!
187
  }
1✔
188

189
  constexpr const word_type* data() const noexcept {
190
    return size() ? storage.data() : nullptr;
191
  }
192

193
  /*
194
    * Iterators
195
    */
196
  constexpr iterator begin() noexcept {
466✔
197
    return iterator(storage.begin());
466✔
198
  }
466✔
199

200
  constexpr const_iterator begin() const noexcept {
37✔
201
    return const_iterator(storage.begin());
37✔
202
  }
37✔
203

204
  /*
205
    * Capacity
206
    */
207
  constexpr size_type size() const noexcept {
454✔
208
    return N;
454✔
209
  }
454✔
210

211
  /*
212
    * Operations
213
    */
214
  constexpr void swap(bit_array<T, N, V, W>& other) noexcept {
1✔
215
    std::swap(this->storage, other.storage);
1✔
216
  }
1✔
217
};
218

219
static_assert(bit_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_range concept!");
220
static_assert(bit_sized_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_sized_range concept!");
221
#ifdef CONTIGUOUS_RANGE
222
static_assert(bit_contiguous_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_range concept!");
223
static_assert(bit_contiguous_sized_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_sized_range concept!");
224
#endif
225

226
#if 0
227
// Class Template Argument Deduction
228
// CTAD guide for the constructor taking a word_type&,
229
// deducing Extent as bitsof<word_type>().
230
template <typename word_type>
231
bit_array(word_type&) -> bit_array<word_type, bitsof<word_type>()>;
232
template <typename word_type>
233
bit_array(word_type*) -> bit_array<word_type, bitsof<word_type>()>;
234

235
// CTAD guide for the constructor taking a word_type* and a size,
236
// which should always be used when Extent is std::dynamic_extent.
237
template <typename word_type>
238
bit_array(word_type&, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
239
template <typename word_type>
240
bit_array(word_type*, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
241
#endif
242

243
}  // namespace bit
244

245
#endif  // _BIT_ARRAY_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