Skip to content

Commit 4a81fb4

Browse files
committed
PrefixCodeTreeDecoder: support finishReadingPartialSymbol() iface
1 parent 1a56e24 commit 4a81fb4

3 files changed

Lines changed: 53 additions & 20 deletions

File tree

fuzz/all-fuzzers.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@ PanasonicV6DecompressorFuzzer
2222
PanasonicV7DecompressorFuzzer
2323
PentaxDecompressorFuzzer
2424
PhaseOneDecompressorFuzzer
25+
PrefixCodeDecoderFuzzer-LUTWithLookupVsLUTWithTree
2526
PrefixCodeDecoderFuzzer-LUTWithLookupVsLUTWithVector
2627
PrefixCodeDecoderFuzzer-LUTWithLookupVsLookup
2728
PrefixCodeDecoderFuzzer-LUTWithLookupVsTree
2829
PrefixCodeDecoderFuzzer-LUTWithLookupVsVector
30+
PrefixCodeDecoderFuzzer-LUTWithTreeVsLUTWithVector
31+
PrefixCodeDecoderFuzzer-LUTWithTreeVsLookup
32+
PrefixCodeDecoderFuzzer-LUTWithTreeVsTree
33+
PrefixCodeDecoderFuzzer-LUTWithTreeVsVector
2934
PrefixCodeDecoderFuzzer-LUTWithVectorVsLookup
3035
PrefixCodeDecoderFuzzer-LUTWithVectorVsTree
3136
PrefixCodeDecoderFuzzer-LUTWithVectorVsVector
3237
PrefixCodeDecoderFuzzer-LookupVsTree
3338
PrefixCodeDecoderFuzzer-LookupVsVector
3439
PrefixCodeDecoderFuzzer-TreeVsVector
3540
PrefixCodeLUTWithLookupDecoderFuzzer
41+
PrefixCodeLUTWithTreeDecoderFuzzer
3642
PrefixCodeLUTWithVectorDecoderFuzzer
3743
PrefixCodeLookupDecoderFuzzer
3844
PrefixCodeTreeDecoderFuzzer

fuzz/librawspeed/codes/PrefixCodeDecoder/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ function(add_ht_dual_fuzzer impl0 impl1)
6767
add_dependencies(PrefixCodeDecoderFuzzers ${fuzzer})
6868
endfunction()
6969

70-
set(IMPL "Tree")
7170
set(FRONTEND "LUT")
72-
set(BACKEND "Lookup" "Vector")
71+
set(BACKEND "Tree" "Vector" "Lookup")
7372

7473
foreach(backend ${BACKEND})
7574
list(APPEND IMPL "${backend}")

src/librawspeed/codes/PrefixCodeTreeDecoder.h

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@
3030
#include <initializer_list> // for initializer_list
3131
#include <iterator> // for advance, next
3232
#include <memory> // for unique_ptr, make_unique
33+
#include <optional> // for optional
3334
#include <tuple> // for tie
3435
#include <utility> // for pair
3536
#include <vector> // for vector, vector<>::co...
3637

3738
namespace rawspeed {
3839

3940
template <typename CodeTag>
40-
class PrefixCodeTreeDecoder final : public AbstractPrefixCodeDecoder<CodeTag> {
41+
class PrefixCodeTreeDecoder : public AbstractPrefixCodeDecoder<CodeTag> {
4142
public:
4243
using Tag = CodeTag;
4344
using Base = AbstractPrefixCodeDecoder<CodeTag>;
@@ -48,29 +49,23 @@ class PrefixCodeTreeDecoder final : public AbstractPrefixCodeDecoder<CodeTag> {
4849
private:
4950
BinaryPrefixTree<CodeTag> tree;
5051

52+
protected:
5153
template <typename BIT_STREAM>
52-
inline std::pair<typename Base::CodeSymbol,
53-
typename Traits::CodeValueTy /*codeValue*/>
54-
readSymbol(BIT_STREAM& bs) const {
55-
static_assert(
56-
BitStreamTraits<typename BIT_STREAM::tag>::canUseWithPrefixCodeDecoder,
57-
"This BitStream specialization is not marked as usable here");
54+
inline std::pair<typename Base::CodeSymbol, int /*codeValue*/>
55+
finishReadingPartialSymbol(BIT_STREAM& bs,
56+
typename Base::CodeSymbol initialPartial) const {
5857
typename Base::CodeSymbol partial;
58+
partial.code = 0;
59+
partial.code_len = 0;
5960

6061
const auto* top = &(tree.root->getAsBranch());
6162

62-
// Read bits until either find the code or detect the incorrect code
63-
for (partial.code = 0, partial.code_len = 1;; ++partial.code_len) {
64-
invariant(partial.code_len <= Traits::MaxCodeLenghtBits);
65-
66-
// Read one more bit
67-
const bool bit = bs.getBitsNoFill(1);
68-
69-
// codechecker_false_positive [core.uninitialized.Assign]
63+
auto walkBinaryTree = [&partial, &top](bool bit)
64+
-> std::optional<
65+
std::pair<typename Base::CodeSymbol, int /*codeValue*/>> {
7066
partial.code <<= 1;
7167
partial.code |= bit;
72-
73-
// What is the last bit, which we have just read?
68+
partial.code_len++;
7469

7570
// NOTE: The order *IS* important! Left to right, zero to one!
7671
const auto& newNode = top->buds[bit];
@@ -84,17 +79,50 @@ class PrefixCodeTreeDecoder final : public AbstractPrefixCodeDecoder<CodeTag> {
8479
if (static_cast<typename decltype(tree)::Node::Type>(*newNode) ==
8580
decltype(tree)::Node::Type::Leaf) {
8681
// Ok, great, hit a Leaf. This is it.
87-
return {partial, newNode->getAsLeaf().value};
82+
return {{partial, newNode->getAsLeaf().value}};
8883
}
8984

9085
// Else, this is a branch, continue looking.
9186
top = &(newNode->getAsBranch());
87+
return std::nullopt;
88+
};
89+
90+
// First, translate pre-existing code bits.
91+
for (unsigned bit : initialPartial.getBitsMSB()) {
92+
if (auto sym = walkBinaryTree(bit))
93+
return *sym;
94+
}
95+
96+
// Read bits until either find the code or detect the incorrect code
97+
while (true) {
98+
invariant(partial.code_len <= Traits::MaxCodeLenghtBits);
99+
100+
// Read one more bit
101+
const bool bit = bs.getBitsNoFill(1);
102+
103+
if (auto sym = walkBinaryTree(bit))
104+
return *sym;
92105
}
93106

94107
// We have either returned the found symbol, or thrown on incorrect symbol.
95108
__builtin_unreachable();
96109
}
97110

111+
template <typename BIT_STREAM>
112+
inline std::pair<typename Base::CodeSymbol, int /*codeValue*/>
113+
readSymbol(BIT_STREAM& bs) const {
114+
static_assert(
115+
BitStreamTraits<typename BIT_STREAM::tag>::canUseWithPrefixCodeDecoder,
116+
"This BitStream specialization is not marked as usable here");
117+
118+
// Start from completely unknown symbol.
119+
typename Base::CodeSymbol partial;
120+
partial.code_len = 0;
121+
partial.code = 0;
122+
123+
return finishReadingPartialSymbol(bs, partial);
124+
}
125+
98126
public:
99127
void setup(bool fullDecode_, bool fixDNGBug16_) {
100128
AbstractPrefixCodeDecoder<CodeTag>::setup(fullDecode_, fixDNGBug16_);

0 commit comments

Comments
 (0)