RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
PrefixCodeEncoder.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
21#include "adt/Array1DRef.h"
22#include "adt/Casts.h"
23#include "adt/Optional.h"
37#include "io/Buffer.h"
38#include "io/ByteStream.h"
39#include "io/Endianness.h"
40#include <cassert>
41#include <cstdint>
42#include <cstdio>
43#include <iterator>
44#include <vector>
45
46extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size);
47
48namespace rawspeed {
49
50namespace {
51
52struct BitstreamFlavorMSB;
53struct BitstreamFlavorMSB32;
54struct BitstreamFlavorJPEG;
55
56template <typename T> struct BitStreamRoundtripTypes final {};
57
58template <> struct BitStreamRoundtripTypes<BitstreamFlavorMSB> final {
60
61 template <typename OutputIterator>
63};
64
65template <> struct BitStreamRoundtripTypes<BitstreamFlavorMSB32> final {
67
68 template <typename OutputIterator>
70};
71
72template <> struct BitStreamRoundtripTypes<BitstreamFlavorJPEG> final {
74
75 template <typename OutputIterator>
77};
78
79template <typename flavor, bool IsFullDecode, typename HT>
80void workloop(Array1DRef<const uint8_t> inputSrc, const HT& ht) {
82 encoder.setup(IsFullDecode, ht.handleDNGBug16());
83
85
86 std::vector<uint8_t> inputRec;
87
88 int numCodesEncoded = 0;
89 {
90 auto bsSrc = BitStreamer(inputSrc);
91
92 auto bsInserter = PartitioningOutputIterator(std::back_inserter(inputRec));
93 using BitVacuumer = typename BitStreamRoundtripTypes<
94 flavor>::template vacuumer<decltype(bsInserter)>;
95 auto bv = BitVacuumer(bsInserter);
96
97 bsSrc.fill(32);
98 while (bsSrc.getInputPosition() <= inputSrc.size()) {
100
101 try {
102 v = ht.template decode<BitStreamer, IsFullDecode>(bsSrc);
103 } catch (...) {
104 break;
105 }
106
107 try {
108 encoder.template encode<BitVacuumer, IsFullDecode>(bv, *v);
109 } catch (...) {
110 __builtin_unreachable();
111 }
112 ++numCodesEncoded;
113 }
114 }
115
116 if (constexpr int MinSize = BitStreamer::Traits::MaxProcessBytes;
117 inputRec.size() < MinSize)
118 inputRec.resize(MinSize, uint8_t(0));
119
120 try {
121 auto bsSrc = BitStreamer(inputSrc);
122 auto bsRec = BitStreamer(
123 Array1DRef(inputRec.data(), implicit_cast<int>(inputRec.size())));
124 for (int i = 0; i != numCodesEncoded; ++i) {
125 const auto vSrc = ht.template decode<BitStreamer, IsFullDecode>(bsSrc);
126 const auto vRec = ht.template decode<BitStreamer, IsFullDecode>(bsRec);
127 assert(vSrc == vRec);
128 (void)vSrc;
129 (void)vRec;
130 }
131 } catch (...) {
132 __builtin_unreachable();
133 }
134}
135
136template <typename flavor, typename HT>
137void checkPump(Array1DRef<const uint8_t> input, const HT& ht) {
138 if (ht.isFullDecode())
139 workloop<flavor, /*IsFullDecode=*/true>(input, ht);
140 else
141 workloop<flavor, /*IsFullDecode=*/false>(input, ht);
142}
143
144template <typename HT> void checkDecoder(ByteStream bs) {
145 const auto ht = createPrefixCodeDecoder<HT>(bs);
146
147 // Which bit stream flavor should we use?
148 const auto flavor = bs.getByte();
149 const auto input = bs.peekRemainingBuffer().getAsArray1DRef();
150 switch (flavor) {
151 case 0:
153 break;
154 case 1:
156 break;
157 case 2:
159 break;
160 default:
161 ThrowRSE("Unknown bit pump");
162 }
163}
164
165template <typename CodeTag> void checkFlavour(ByteStream bs) {
166 // Which decoder implementation should we use?
167 const auto decoderImpl = bs.getByte();
168 switch (decoderImpl) {
169 case 0:
171 break;
172 case 1:
174 break;
175 case 2:
177 break;
178 case 3: {
179 // Which backing decoder implementation should we use?
180 const auto backingDecoderImpl = bs.getByte();
181 switch (backingDecoderImpl) {
182 case 0:
185 break;
186 case 1:
189 break;
190 case 2:
193 break;
194 default:
195 ThrowRSE("Unknown decoder");
196 }
197 break;
198 }
199 default:
200 ThrowRSE("Unknown decoder");
201 }
202}
203
204extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
205 assert(Data);
206
207 try {
208 const Buffer b(Data, implicit_cast<Buffer::size_type>(Size));
209 const DataBuffer db(b, Endianness::little);
210 ByteStream bs(db);
211
212 // Which flavor?
213 switch (bs.getByte()) {
214 case 0:
216 break;
217 case 1:
219 break;
220 default:
221 ThrowRSE("Unknown flavor");
222 }
223 } catch (const RawspeedException&) {
224 return 0;
225 }
226
227 return 0;
228}
229
230} // namespace
231
232} // namespace rawspeed
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Definition Dual.cpp:161
#define ThrowRSE(...)
assert(dim.area() >=area)
int RAWSPEED_READONLY size() const
Array1DRef< const uint8_t > getAsArray1DRef() const
Definition Buffer.h:70
Buffer peekRemainingBuffer() const
Definition ByteStream.h:108
void setup(bool fullDecode_, bool fixDNGBug16_)
static T createPrefixCodeDecoder(rawspeed::ByteStream &bs)
Definition Common.h:147
void workloop(Array1DRef< const uint8_t > inputSrc, const HT &ht)
void checkPump(Array1DRef< const uint8_t > input, const HT &ht)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >
PartitioningOutputIterator(T) -> PartitioningOutputIterator< T >