RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
BitVacuumerMSBTest.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2024 Roman Lebedev
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
22#include "adt/Array1DRef.h"
23#include "adt/Bit.h"
24#include "adt/Casts.h"
28#include "common/Common.h"
29#include <climits>
30#include <cstdint>
31#include <iterator>
32#include <utility>
33#include <vector>
34#include <gmock/gmock.h>
35#include <gtest/gtest.h>
36
37#pragma GCC diagnostic push
38#pragma GCC diagnostic ignored "-Wpragmas"
39#pragma GCC diagnostic ignored "-Wunknown-warning-option"
40#pragma GCC diagnostic ignored "-Wunknown-pragmas"
41#pragma GCC diagnostic ignored "-Wframe-larger-than="
42#pragma GCC diagnostic ignored "-Wstack-usage="
43
44namespace rawspeed {
45
46namespace {
47
48using RecepieEntryType = std::pair<uint32_t, uint8_t>;
49using RecepieType = std::vector<RecepieEntryType>;
50using ResultType = std::vector<uint8_t>;
51
52using valueType = std::pair<RecepieType, ResultType>;
53class BitVacuumerMSBTest : public ::testing::TestWithParam<valueType> {
54protected:
55 BitVacuumerMSBTest() = default;
56 virtual void SetUp() {
57 recepie = std::get<0>(GetParam());
58 expectedOutput = std::get<1>(GetParam());
59 }
60
63};
64const std::vector<valueType> values = {{
65 // clang-format off
66 {RecepieType({{std::make_pair(0x00, 0)}}), ResultType()},
67 {RecepieType({{std::make_pair(0x00, 1)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
68 {RecepieType({{std::make_pair(0x00, 2)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
69 {RecepieType({{std::make_pair(0x00, 3)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
70 {RecepieType({{std::make_pair(0x00, 4)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
71 {RecepieType({{std::make_pair(0x00, 5)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
72 {RecepieType({{std::make_pair(0x00, 6)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
73 {RecepieType({{std::make_pair(0x00, 7)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
74 {RecepieType({{std::make_pair(0x00, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
75 {RecepieType({{std::make_pair(0x00, 9)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
76 {RecepieType({{std::make_pair(0x00, 10)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
77 {RecepieType({{std::make_pair(0x00, 11)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
78 {RecepieType({{std::make_pair(0x00, 12)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
79 {RecepieType({{std::make_pair(0x00, 13)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
80 {RecepieType({{std::make_pair(0x00, 14)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
81 {RecepieType({{std::make_pair(0x00, 15)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
82 {RecepieType({{std::make_pair(0x00, 16)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
83 {RecepieType({{std::make_pair(0x00, 17)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
84 {RecepieType({{std::make_pair(0x00, 18)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
85 {RecepieType({{std::make_pair(0x00, 19)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
86 {RecepieType({{std::make_pair(0x00, 20)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
87 {RecepieType({{std::make_pair(0x00, 21)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
88 {RecepieType({{std::make_pair(0x00, 22)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
89 {RecepieType({{std::make_pair(0x00, 23)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
90 {RecepieType({{std::make_pair(0x00, 24)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
91 {RecepieType({{std::make_pair(0x00, 25)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
92 {RecepieType({{std::make_pair(0x00, 26)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
93 {RecepieType({{std::make_pair(0x00, 27)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
94 {RecepieType({{std::make_pair(0x00, 28)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
95 {RecepieType({{std::make_pair(0x00, 29)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
96 {RecepieType({{std::make_pair(0x00, 30)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
97 {RecepieType({{std::make_pair(0x00, 31)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
98 {RecepieType({{std::make_pair(0x00, 32)}}), ResultType({{0x00, 0x00, 0x00, 0x00}})},
99
100 {RecepieType({{std::make_pair(0xFF, 8)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
101
102 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 0)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
103 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 1)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
104 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 2)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
105 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 3)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
106 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 4)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
107 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 5)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
108 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 6)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
109 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 7)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
110 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 8)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
111 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 9)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
112 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 10)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
113 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 11)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
114 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 12)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
115 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 13)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
116 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 14)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
117 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 15)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
118 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 16)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
119 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 17)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
120 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 18)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
121 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 19)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
122 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 20)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
123 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 21)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
124 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 22)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
125 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 23)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
126 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 24)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
127 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 25)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
128 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 26)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
129 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 27)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
130 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 28)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
131 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 29)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
132 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 30)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
133 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 31)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
134 {RecepieType({{std::make_pair(0xFF, 8), std::make_pair(0x00, 32)}}), ResultType({{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}})},
135
136 {RecepieType({{std::make_pair(0x00, 0), std::make_pair(0xFF, 8)}}), ResultType({{0xFF, 0x00, 0x00, 0x00}})},
137 {RecepieType({{std::make_pair(0x00, 1), std::make_pair(0xFF, 8)}}), ResultType({{0x7F, 0x80, 0x00, 0x00}})},
138 {RecepieType({{std::make_pair(0x00, 2), std::make_pair(0xFF, 8)}}), ResultType({{0x3F, 0xC0, 0x00, 0x00}})},
139 {RecepieType({{std::make_pair(0x00, 3), std::make_pair(0xFF, 8)}}), ResultType({{0x1F, 0xE0, 0x00, 0x00}})},
140 {RecepieType({{std::make_pair(0x00, 4), std::make_pair(0xFF, 8)}}), ResultType({{0x0F, 0xF0, 0x00, 0x00}})},
141 {RecepieType({{std::make_pair(0x00, 5), std::make_pair(0xFF, 8)}}), ResultType({{0x07, 0xF8, 0x00, 0x00}})},
142 {RecepieType({{std::make_pair(0x00, 6), std::make_pair(0xFF, 8)}}), ResultType({{0x03, 0xFC, 0x00, 0x00}})},
143 {RecepieType({{std::make_pair(0x00, 7), std::make_pair(0xFF, 8)}}), ResultType({{0x01, 0xFE, 0x00, 0x00}})},
144 {RecepieType({{std::make_pair(0x00, 8), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0xFF, 0x00, 0x00}})},
145 {RecepieType({{std::make_pair(0x00, 9), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x7F, 0x80, 0x00}})},
146 {RecepieType({{std::make_pair(0x00, 10), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x3F, 0xC0, 0x00}})},
147 {RecepieType({{std::make_pair(0x00, 11), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x1F, 0xE0, 0x00}})},
148 {RecepieType({{std::make_pair(0x00, 12), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x0F, 0xF0, 0x00}})},
149 {RecepieType({{std::make_pair(0x00, 13), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x07, 0xF8, 0x00}})},
150 {RecepieType({{std::make_pair(0x00, 14), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x03, 0xFC, 0x00}})},
151 {RecepieType({{std::make_pair(0x00, 15), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x01, 0xFE, 0x00}})},
152 {RecepieType({{std::make_pair(0x00, 16), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0xFF, 0x00}})},
153 {RecepieType({{std::make_pair(0x00, 17), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x7F, 0x80}})},
154 {RecepieType({{std::make_pair(0x00, 18), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x3F, 0xC0}})},
155 {RecepieType({{std::make_pair(0x00, 19), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x1F, 0xE0}})},
156 {RecepieType({{std::make_pair(0x00, 20), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x0F, 0xF0}})},
157 {RecepieType({{std::make_pair(0x00, 21), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x07, 0xF8}})},
158 {RecepieType({{std::make_pair(0x00, 22), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x03, 0xFC}})},
159 {RecepieType({{std::make_pair(0x00, 23), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x01, 0xFE}})},
160 {RecepieType({{std::make_pair(0x00, 24), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0xFF}})},
161 {RecepieType({{std::make_pair(0x00, 25), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00}})},
162 {RecepieType({{std::make_pair(0x00, 26), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00}})},
163 {RecepieType({{std::make_pair(0x00, 27), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00}})},
164 {RecepieType({{std::make_pair(0x00, 28), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00}})},
165 {RecepieType({{std::make_pair(0x00, 29), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00}})},
166 {RecepieType({{std::make_pair(0x00, 30), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00}})},
167 {RecepieType({{std::make_pair(0x00, 31), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00}})},
168 {RecepieType({{std::make_pair(0x00, 32), std::make_pair(0xFF, 8)}}), ResultType({{0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}})},
169 // clang-format on
170}};
171
173 ::testing::ValuesIn(values));
174
176 ResultType bitstream;
177
178 {
179 auto bsInserter = PartitioningOutputIterator(std::back_inserter(bitstream));
180 using BitVacuumer = BitVacuumerMSB<decltype(bsInserter)>;
181 auto bv = BitVacuumer(bsInserter);
182
183 for (const auto& e : recepie)
184 bv.put(e.first, e.second);
185 }
186
187 return bitstream;
188}
189
191 const ResultType bitstream = synthesizeBitstream(recepie);
192 ASSERT_THAT(bitstream, testing::ContainerEq(expectedOutput));
193}
194
196 if (expectedOutput.empty())
197 return;
198
199 auto bs = BitStreamerMSB(Array1DRef(
200 expectedOutput.data(), implicit_cast<int>(expectedOutput.size())));
201 for (int i = 0; i != implicit_cast<int>(recepie.size()); ++i) {
202 const auto [expectedVal, len] = recepie[i];
203 bs.fill(32);
204 const auto actualVal = len != 0 ? bs.getBitsNoFill(len) : 0;
205 ASSERT_THAT(actualVal, expectedVal);
206 }
207}
208
210 std::vector<uint8_t> bitstream;
211
212 constexpr int numByteElts = 64;
213
214 {
215 auto bsInserter = PartitioningOutputIterator(std::back_inserter(bitstream));
216 using BitVacuumer = BitVacuumerMSB<decltype(bsInserter)>;
217 auto bv = BitVacuumer(bsInserter);
218
219 for (int e = 0; e != numByteElts; ++e)
220 bv.put(e, 8);
221 }
222
223 auto fullInput =
224 Array1DRef(bitstream.data(), implicit_cast<int>(bitstream.size()));
225
229
230 for (int fillLevel : {8, 32}) {
231 for (int baseLoadPosStep = 1;
232 baseLoadPosStep <= 2 * BitStreamTraits::MinLoadStepByteMultiple;
233 ++baseLoadPosStep) {
234 for (int baseLoadPos = 0;
235 baseLoadPos <= numByteElts - BitStreamerTraits::MaxProcessBytes;
236 baseLoadPos += baseLoadPosStep) {
237 auto input =
238 fullInput.getCrop(baseLoadPos, fullInput.size() - baseLoadPos)
239 .getAsArray1DRef();
240 auto bs = BitStreamer(input);
241 for (int i = 0; i != input.size(); ++i) {
242 const auto expectedVal = baseLoadPos + i;
243 bs.fill(fillLevel);
244 const auto actualVal = bs.getBitsNoFill(8);
245 if (baseLoadPosStep % BitStreamTraits::MinLoadStepByteMultiple == 0 ||
246 baseLoadPos % BitStreamTraits::MinLoadStepByteMultiple == 0) {
247 ASSERT_THAT(actualVal, expectedVal);
248 } else {
249 ASSERT_NE(actualVal, expectedVal);
250 }
251 }
252 }
253 }
254 }
255}
256
257TEST(BitVacuumerMSBTest, DependencyBreaking) {
258 std::vector<uint8_t> bitstream;
259
262
263 constexpr int numByteElts = 256;
264
265 {
266 auto bsInserter = PartitioningOutputIterator(std::back_inserter(bitstream));
267 using BitVacuumer = BitVacuumerMSB<decltype(bsInserter)>;
268 auto bv = BitVacuumer(bsInserter);
269
270 for (int e = 0; e != numByteElts + BitStreamerTraits::MaxProcessBytes; ++e)
271 bv.put(e, 8);
272 }
273 constexpr int numBitsTotal = CHAR_BIT * numByteElts;
274
275 auto fullInput =
276 Array1DRef(bitstream.data(), implicit_cast<int>(bitstream.size()));
277
278 for (int numBitsToSkip = 0; numBitsToSkip <= numBitsTotal; ++numBitsToSkip) {
279 auto bsRef = BitStreamer(fullInput);
280 bsRef.fill();
281
282 for (int i = 0; i != numBitsToSkip / 8; ++i) {
283 const auto expectedVal = i;
284 ASSERT_THAT(bsRef.getBits(8), expectedVal);
285 }
286 if ((numBitsToSkip % 8) != 0) {
287 const auto expectedVal = extractHighBits<unsigned>(
288 numBitsToSkip / CHAR_BIT, numBitsToSkip % 8, CHAR_BIT);
289 ASSERT_THAT(bsRef.getBits(numBitsToSkip % 8), expectedVal);
290 }
291
292 const int numBitsRemaining = numBitsTotal - numBitsToSkip;
293
295 state.pos = bsRef.getInputPosition();
296 state.fillLevel = bsRef.getFillLevel();
297 const auto bsPos = getAsByteStreamPosition(state);
298
299 auto rebasedInput =
300 fullInput.getCrop(bsPos.bytePos, fullInput.size() - bsPos.bytePos)
301 .getAsArray1DRef();
302 auto bsRebased = BitStreamer(rebasedInput);
303 if (bsPos.numBitsToSkip != 0)
304 bsRebased.skipBits(bsPos.numBitsToSkip);
305
306 int numSubByteBitsRemaining = numBitsRemaining % CHAR_BIT;
307 int numBytesRemaining = numBitsRemaining / CHAR_BIT;
308 if (numSubByteBitsRemaining != 0) {
309 const auto expectedVal = extractLowBits<unsigned>(
310 numBitsToSkip / CHAR_BIT, numSubByteBitsRemaining);
311 ASSERT_THAT(bsRef.getBits(numSubByteBitsRemaining), expectedVal);
312 ASSERT_THAT(bsRebased.getBits(numSubByteBitsRemaining), expectedVal);
313 }
314
315 for (int i = 0; i != numBytesRemaining; ++i) {
316 const auto expectedVal = roundUpDivision(numBitsToSkip, CHAR_BIT) + i;
317 ASSERT_THAT(bsRef.getBits(8), expectedVal);
318 ASSERT_THAT(bsRebased.getBits(8), expectedVal);
319 }
320 }
321}
322
324 std::vector<uint8_t> bitstream;
325
328
329 constexpr int numByteElts = 256;
330
331 {
332 auto bsInserter = PartitioningOutputIterator(std::back_inserter(bitstream));
333 using BitVacuumer = BitVacuumerMSB<decltype(bsInserter)>;
334 auto bv = BitVacuumer(bsInserter);
335
336 for (int e = 0; e != numByteElts + BitStreamerTraits::MaxProcessBytes; ++e)
337 bv.put(e, 8);
338 }
339 constexpr int numBitsTotal = CHAR_BIT * numByteElts;
340
341 auto fullInput =
342 Array1DRef(bitstream.data(), implicit_cast<int>(bitstream.size()));
343
344 for (int numBitsToSkip = 0; numBitsToSkip <= numBitsTotal; ++numBitsToSkip) {
345 auto bsRef = BitStreamer(fullInput);
346 bsRef.fill();
347
348 for (int i = 0; i != numBitsToSkip / 8; ++i) {
349 const auto expectedVal = i;
350 ASSERT_THAT(bsRef.getBits(8), expectedVal);
351 }
352 if ((numBitsToSkip % 8) != 0) {
353 const auto expectedVal = extractHighBits<unsigned>(
354 numBitsToSkip / CHAR_BIT, numBitsToSkip % 8, CHAR_BIT);
355 ASSERT_THAT(bsRef.getBits(numBitsToSkip % 8), expectedVal);
356 }
357
358 bsRef.reload();
359
360 const int numBitsRemaining = numBitsTotal - numBitsToSkip;
361
362 int numSubByteBitsRemaining = numBitsRemaining % CHAR_BIT;
363 int numBytesRemaining = numBitsRemaining / CHAR_BIT;
364 if (numSubByteBitsRemaining != 0) {
365 const auto expectedVal = extractLowBits<unsigned>(
366 numBitsToSkip / CHAR_BIT, numSubByteBitsRemaining);
367 ASSERT_THAT(bsRef.getBits(numSubByteBitsRemaining), expectedVal);
368 }
369
370 for (int i = 0; i != numBytesRemaining; ++i) {
371 const auto expectedVal = roundUpDivision(numBitsToSkip, CHAR_BIT) + i;
372 ASSERT_THAT(bsRef.getBits(8), expectedVal);
373 }
374 }
375}
376
377} // namespace
378
379} // namespace rawspeed
380
381// NOTE: no `#pragma GCC diagnostic pop` wanted!
INSTANTIATE_TEST_SUITE_P(MD5Test, MD5Test, ::testing::ValuesIn(testCases))
TEST_P(MD5Test, CheckTestCaseSet)
Definition MD5Test.cpp:388
BitStreamerTraits< Derived > Traits
BitStreamTraits< Traits::Tag > StreamTraits
void put(uint32_t bits, int count)
ResultType synthesizeBitstream(const RecepieType &recepie)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
constexpr uint64_t RAWSPEED_READNONE roundUpDivision(uint64_t value, uint64_t div)
Definition Common.h:139
ByteStreamPosition< bo > getAsByteStreamPosition(BitStreamPosition< bo > state)
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >
PartitioningOutputIterator(T) -> PartitioningOutputIterator< T >
constexpr RAWSPEED_READNONE T extractHighBits(T value, unsigned nBits, unsigned effectiveBitwidth=bitwidth< T >())
Definition Bit.h:120
constexpr RAWSPEED_READNONE T extractLowBits(T value, unsigned nBits)
Definition Bit.h:96