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

PeterCDMcLean / BitLib / 15574317715

11 Jun 2025 02:02AM UTC coverage: 53.774% (+1.0%) from 52.785%
15574317715

Pull #16

github

web-flow
Merge c4534fd50 into a32e9aeba
Pull Request #16: Small buffer optimization

9875 of 18300 branches covered (53.96%)

Branch coverage included in aggregate %.

619 of 655 new or added lines in 16 files covered. (94.5%)

2 existing lines in 1 file now uncovered.

5912 of 11058 relevant lines covered (53.46%)

7914739.4 hits per line

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

64.82
/test/src/test-iterator_adapter.cpp
1
// ============================= TRANSFORM  TESTS =============================== //
2
// Project:         The Experimental Bit Algorithms Library
3
// Description:     Tests for transform algorithms
4
// Contributor(s):  Bryce Kille
5
// License:         BSD 3-Clause License
6
// ========================================================================== //
7

8

9
// ============================== PREAMBLE ================================== //
10
// C++ standard library
11
#include <math.h>
12
#include <algorithm>
13
#include <functional>
14
// Project sources
15
#include "bitlib/bit-algorithms/bit_algorithm.hpp"
16
#include "bitlib/bit-containers/bit-containers.hpp"
17
#include "fixtures.hpp"
18
// Third-party libraries
19
#include "gtest/gtest.h"
20
// Miscellaneous
21
// ========================================================================== //
22
#include "bitlib/bit-iterator/bit_word_pointer_adapter.hpp"
23

24
//
25
// GoogleTest suite for bit::bit_word_pointer_adapter.
26
// Covers both “big‐to‐small” and “small‐to‐large” modes.
27
//
28

29
// Assumes a little‐endian platform (so that reinterpret_cast<…> of bytes
30
// within larger words behaves predictably). If you compile on a big‐endian
31
// machine, these tests will fail.
32
//
33
// Verify that we are on a little‐endian machine:
34
static_assert(std::endian::native == std::endian::little,
35
              "These tests assume little‐endian byte order");
36

37
TEST(IteratorAdapter, Basic) {
1✔
38
    std::vector<uint16_t> base{0x1234, 0x2345, 0x3456, 0x4567};
1✔
39
    bit::bit_word_pointer_adapter<uint8_t*, std::vector<uint16_t>::iterator> adapter(base.begin());
1✔
40
    EXPECT_EQ(*adapter, 0x34);
1!
41
    EXPECT_EQ(*(++adapter), 0x12);
1!
42
    EXPECT_EQ(*(adapter++), 0x12);
1!
43
    EXPECT_EQ(*adapter, 0x45);
1!
44
    adapter += 2;
1✔
45
    EXPECT_EQ(*adapter, 0x56);
1!
46
}
1✔
47

48
// -----------------------------------------------------------------------------
49
// Helper: Convert a 32‐bit word into its 4 individual bytes (little‐endian)
50
// -----------------------------------------------------------------------------
NEW
51
static void split_u32_le(uint32_t value, uint8_t out_bytes[4]) {
×
NEW
52
  out_bytes[0] = static_cast<uint8_t>(value & 0xFFu);
×
NEW
53
  out_bytes[1] = static_cast<uint8_t>((value >> 8) & 0xFFu);
×
NEW
54
  out_bytes[2] = static_cast<uint8_t>((value >> 16) & 0xFFu);
×
NEW
55
  out_bytes[3] = static_cast<uint8_t>((value >> 24) & 0xFFu);
×
NEW
56
}
×
57

58
// -----------------------------------------------------------------------------
59
// TEST SUITE: Big-to-Small Mode (BaseIterator.value_type > Iterator.value_type)
60
// -----------------------------------------------------------------------------
61
TEST(BitIteratorAdapter_BigToSmall, DereferenceAndIncrement) {
1✔
62
  // Base‐words are 32-bit => 4 × 8-bit subwords
63
  constexpr size_t N = 2;
1✔
64
  uint32_t base_arr[N] = {0x04030201u, 0x08070605u};
1✔
65
  // Bytes in memory (little‐endian):
66
  // base_arr[0]: {0x01,0x02,0x03,0x04}
67
  // base_arr[1]: {0x05,0x06,0x07,0x08}
68

69
  // Iterator type: iterate in 8-bit steps over a 32-bit array
70
  using Iter8 = uint8_t*;
1✔
71
  using Base32 = uint32_t*;
1✔
72
  using Adapter8_32 = bit::bit_word_pointer_adapter<Iter8, Base32>;
1✔
73

74
  Adapter8_32 it(base_arr, /*pos=*/0);
1✔
75

76
  // Check that *it sees the first byte = 0x01
77
  EXPECT_EQ(*it, 0x01u);
1!
78

79
  // Advance 1: pos=1, still in base_arr[0]
80
  ++it;
1✔
81
  EXPECT_EQ(it.index(), 1u);
1!
82
  EXPECT_EQ(*it, 0x02u);
1!
83

84
  // Advance to pos=3
85
  it += 2;
1✔
86
  EXPECT_EQ(it.index(), 3u);
1!
87
  EXPECT_EQ(*it, 0x04u);
1!
88

89
  // Next increment should roll over to base_arr[1], pos=0
90
  ++it;
1✔
91
  EXPECT_EQ(it.base(), base_arr + 1);
1!
92
  EXPECT_EQ(it.index(), 0u);
1!
93
  EXPECT_EQ(*it, 0x05u);
1!
94

95
  // Further increments
96
  ++it;  // pos=1
1✔
97
  EXPECT_EQ(it.index(), 1u);
1!
98
  EXPECT_EQ(*it, 0x06u);
1!
99

100
  ++it;  // pos=2
1✔
101
  EXPECT_EQ(it.index(), 2u);
1!
102
  EXPECT_EQ(*it, 0x07u);
1!
103

104
  ++it;  // pos=3
1✔
105
  EXPECT_EQ(it.index(), 3u);
1!
106
  EXPECT_EQ(*it, 0x08u);
1!
107
}
1✔
108

109
TEST(BitIteratorAdapter_BigToSmall, OperatorStarAndArrow) {
1✔
110
  // Use a single base word = 0xAABBCCDD
111
  uint32_t base_val = 0xAABBCCDDu;
1✔
112
  // Memory bytes: { DD, CC, BB, AA } little-endian
113
  using Iter8 = uint8_t*;
1✔
114
  using Base32 = uint32_t*;
1✔
115
  using Adapter8_32 = bit::bit_word_pointer_adapter<Iter8, Base32>;
1✔
116

117
  Adapter8_32 it(&base_val, /*pos=*/0);
1✔
118

119
  EXPECT_EQ(*it, 0xDDu);
1!
120
  // operator->() should return a pointer to the byte
121
  auto p = *it;
1✔
122
  EXPECT_EQ(p, 0xDDu);
1!
123

124
  // Move to pos=2
125
  it += 2;
1✔
126
  EXPECT_EQ(*it, 0xBBu);
1!
127
  EXPECT_EQ(it.index(), 2u);
1!
128

129
  // operator->() at pos=2
130
  p = *it;
1✔
131
  EXPECT_EQ(p, 0xBBu);
1!
132
}
1✔
133

134
TEST(BitIteratorAdapter_BigToSmall, OperatorPlusMinusAndDistance) {
1✔
135
  // Fill two 32-bit words
136
  uint32_t base_arr[2] = {0x11223344u, 0x55667788u};
1✔
137
  // Bytes: {44,33,22,11,  88,77,66,55}
138

139
  using Iter8 = uint8_t*;
1✔
140
  using Base32 = uint32_t*;
1✔
141
  using Adapter8_32 = bit::bit_word_pointer_adapter<Iter8, Base32>;
1✔
142

143
  Adapter8_32 it(base_arr, /*pos=*/0);  // points at first byte (0x44)
1✔
144

145
  // it + 3 => should point to 4th byte of base_arr[0] = 0x11
146
  auto it3 = it + 3;
1✔
147
  EXPECT_EQ(it3.base(), base_arr);
1!
148
  EXPECT_EQ(it3.index(), 3u);
1!
149
  EXPECT_EQ(*it3, 0x11u);
1!
150

151
  // it + 4 => moves into base_arr[1], pos=0 => should be 0x88
152
  auto it4 = it + 4;
1✔
153
  EXPECT_EQ(it4.base(), base_arr + 1);
1!
154
  EXPECT_EQ(it4.index(), 0u);
1!
155
  EXPECT_EQ(*it4, 0x88u);
1!
156

157
  // Now distance between it and it+7 = 7
158
  auto it7 = it + 7;
1✔
159
  EXPECT_EQ(it7.base(), base_arr + 1);
1!
160
  EXPECT_EQ(it7.index(), 3u);
1!
161
  EXPECT_EQ(*it7, 0x55u);
1!
162

163
  EXPECT_EQ(it7 - it, 7);
1!
164
  EXPECT_EQ(it - it, 0);
1!
165

166
  // Test operator- (iterator difference) with reversed operands
167
  EXPECT_EQ((it - it7), -7);
1!
168

169
  // Advance it4 by -2 => (it4 - 2) = it + 2 => base_arr[0], pos=2 => 0x22
170
  auto it2 = it4 - 2;
1✔
171
  EXPECT_EQ(it2.base(), base_arr);
1!
172
  EXPECT_EQ(it2.index(), 2u);
1!
173
  EXPECT_EQ(*it2, 0x22u);
1!
174
}
1✔
175

176
TEST(BitIteratorAdapter_BigToSmall, OperatorSubscript) {
1✔
177
  // 1 uint32_t: 0xDEADBEEFu => bytes { EF, BE, AD, DE }
178
  uint32_t base_val = 0xDEADBEEFu;
1✔
179
  using Iter8 = uint8_t*;
1✔
180
  using Base32 = uint32_t*;
1✔
181
  using Adapter8_32 = bit::bit_word_pointer_adapter<Iter8, Base32>;
1✔
182

183
  Adapter8_32 it(&base_val, /*pos=*/0);
1✔
184
  // it[0] == 0xEF, it[1] == 0xBE, it[2] == 0xAD, it[3] == 0xDE
185
  EXPECT_EQ(it[0], static_cast<uint8_t>(0xEFu));
1!
186
  EXPECT_EQ(it[1], static_cast<uint8_t>(0xBEu));
1!
187
  EXPECT_EQ(it[2], static_cast<uint8_t>(0xADu));
1!
188
  EXPECT_EQ(it[3], static_cast<uint8_t>(0xDEu));
1!
189

190
  // Negative index: it[ -1 ] => moves to previous base word;
191
  // but since there's no previous word, behavior is UB. We skip testing negative here.
192

193
  // If we do it + 4, then subscript( it + 4 )[0] should be same as it[4]
194
  auto it_shift = it + 4;  // rolls into next base (out-of-bounds, but for test allocate two words)
1✔
195
  // For safety, create two‐element array:
196
  uint32_t arr2[2] = {0x01020304u, 0x05060708u};
1✔
197
  Adapter8_32 it2(arr2, 0);
1✔
198
  EXPECT_EQ(it2[0], 0x04u);
1!
199
  EXPECT_EQ(it2[1], 0x03u);
1!
200
  EXPECT_EQ(it2[2], 0x02u);
1!
201
  EXPECT_EQ(it2[3], 0x01u);
1!
202
  EXPECT_EQ(it2[4], 0x08u);
1!
203
  EXPECT_EQ(it2[5], 0x07u);
1!
204
  EXPECT_EQ(it2[6], 0x06u);
1!
205
  EXPECT_EQ(it2[7], 0x05u);
1!
206
}
1✔
207

208
// -----------------------------------------------------------------------------
209
// TEST SUITE: Small-to-Large Mode (BaseIterator.value_type < Iterator.value_type)
210
// -----------------------------------------------------------------------------
211
TEST(BitIteratorAdapter_SmallToLarge, DereferenceAndIncrement) {
1✔
212
  // Base: array of uint8_t; Iterator’s value_type = uint16_t => ratio = 2
213
  uint8_t base_arr[] = {
1✔
214
      0x11, 0x22,  // first 16-bit chunk => 0x2211
1✔
215
      0x33, 0x44,  // second 16-bit chunk => 0x4433
1✔
216
      0x55, 0x66   // third 16-bit chunk => 0x6655
1✔
217
  };
1✔
218
  using Iter16 = uint16_t*;
1✔
219
  using Base8 = uint8_t*;
1✔
220
  using Adapter16_8 = bit::bit_word_pointer_adapter<Iter16, Base8>;
1✔
221

222
  Adapter16_8 it(base_arr);
1✔
223

224
  // *it: combine base[0] + (base[1] << 8) => 0x2211
225
  uint16_t first = *it;
1✔
226
  EXPECT_EQ(first, static_cast<uint16_t>(0x2211u));
1!
227

228
  // ++it => skip 2 bytes: now base points to base_arr+2
229
  ++it;
1✔
230
  uint16_t second = *it;
1✔
231
  EXPECT_EQ(second, static_cast<uint16_t>(0x4433u));
1!
232

233
  // ++it again
234
  ++it;
1✔
235
  uint16_t third = *it;
1✔
236
  EXPECT_EQ(third, static_cast<uint16_t>(0x6655u));
1!
237
}
1✔
238

239
TEST(BitIteratorAdapter_SmallToLarge, OperatorPlusMinusDistance) {
1✔
240
  // Base: eight uint8_t => four uint16_t logical elements
241
  uint8_t base_arr[8] = {
1✔
242
      0x10, 0x01,  // 0x0110
1✔
243
      0x20, 0x02,  // 0x0220
1✔
244
      0x30, 0x03,  // 0x0330
1✔
245
      0x40, 0x04   // 0x0440
1✔
246
  };
1✔
247
  using Iter16 = uint16_t*;
1✔
248
  using Base8 = uint8_t*;
1✔
249
  using Adapter16_8 = bit::bit_word_pointer_adapter<Iter16, Base8>;
1✔
250

251
  Adapter16_8 it(base_arr);
1✔
252

253
  // it + 0 => *it == 0x0110
254
  EXPECT_EQ(*it, static_cast<uint16_t>(0x0110u));
1!
255

256
  // it + 1 => combine bytes at indices [2,3] => 0x0220
257
  auto it1 = it + 1;
1✔
258
  EXPECT_EQ(*it1, static_cast<uint16_t>(0x0220u));
1!
259

260
  // it + 2 => 0x0330
261
  auto it2 = it + 2;
1✔
262
  EXPECT_EQ(*it2, static_cast<uint16_t>(0x0330u));
1!
263

264
  // it + 3 => 0x0440
265
  auto it3 = it + 3;
1✔
266
  EXPECT_EQ(*it3, static_cast<uint16_t>(0x0440u));
1!
267

268
  // Distance: it3 - it == 3
269
  EXPECT_EQ(it3 - it, 3);
1!
270
  EXPECT_EQ(it - it, 0);
1!
271

272
  // it2 - it1 == 1
273
  EXPECT_EQ(it2 - it1, 1);
1!
274

275
  // Subtraction reversed:
276
  EXPECT_EQ(it - it3, -3);
1!
277
}
1✔
278

279
TEST(BitIteratorAdapter_SmallToLarge, OperatorStarAndArrow) {
1✔
280
  uint8_t base_arr[4] = {0xAA, 0xBB, 0xCC, 0xDD};
1✔
281
  using Iter16 = uint16_t*;
1✔
282
  using Base8 = uint8_t*;
1✔
283
  using Adapter16_8 = bit::bit_word_pointer_adapter<Iter16, Base8>;
1✔
284

285
  Adapter16_8 it(base_arr);
1✔
286
  // *it => (0xBB << 8) | 0xAA = 0xBBAA
287
  EXPECT_EQ(*it, static_cast<uint16_t>(0xBBAAu));
1!
288
}
1✔
289

290
TEST(BitIteratorAdapter_SmallToLarge, OperatorPlusEqualsAndMinusEquals) {
1✔
291
  // Base: six uint8_t => three 16-bit words
292
  uint8_t base_arr[6] = {
1✔
293
      0x01, 0xA0,  // 0xA001
1✔
294
      0x02, 0xB0,  // 0xB002
1✔
295
      0x03, 0xC0   // 0xC003
1✔
296
  };
1✔
297
  using Iter16 = uint16_t*;
1✔
298
  using Base8 = uint8_t*;
1✔
299
  using Adapter16_8 = bit::bit_word_pointer_adapter<Iter16, Base8>;
1✔
300

301
  Adapter16_8 it(base_arr);
1✔
302

303
  // it += 1 => now at second 16-bit chunk: 0xB002
304
  it += 1;
1✔
305
  EXPECT_EQ(*it, static_cast<uint16_t>(0xB002u));
1!
306

307
  // it += 1 => now at third: 0xC003
308
  it += 1;
1✔
309
  EXPECT_EQ(*it, static_cast<uint16_t>(0xC003u));
1!
310

311
  // it -= 2 => go back to first chunk: 0xA001
312
  it -= 2;
1✔
313
  EXPECT_EQ(*it, static_cast<uint16_t>(0xA001u));
1!
314
}
1✔
315

316
TEST(BitIteratorAdapter_SmallToLarge, OperatorMinusBetweenDifferentIterators) {
1✔
317
  // Base: eight uint8_t => four 16-bit words
318
  uint8_t base_arr[8] = {
1✔
319
      0x01, 0x10,  // 0x1001
1✔
320
      0x02, 0x20,  // 0x2002
1✔
321
      0x03, 0x30,  // 0x3003
1✔
322
      0x04, 0x40   // 0x4004
1✔
323
  };
1✔
324
  using Iter16 = uint16_t*;
1✔
325
  using Base8 = uint8_t*;
1✔
326
  using Adapter16_8 = bit::bit_word_pointer_adapter<Iter16, Base8>;
1✔
327

328
  Adapter16_8 it0(base_arr);
1✔
329
  Adapter16_8 it2(base_arr + 4);  // same as (it0 + 2)
1✔
330

331
  EXPECT_EQ(it2 - it0, 2);
1!
332
  EXPECT_EQ(it0 - it2, -2);
1!
333
}
1✔
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