RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
BinaryPrefixTree.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2018-2023 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#pragma once
22
23#include "adt/Invariant.h"
25#include <array>
26#include <cassert>
27#include <cstdint>
28#include <functional>
29#include <initializer_list> // IWYU pragma: keep
30#include <memory>
31
32namespace rawspeed {
33
34template <typename CodeTag>
35class BinaryPrefixTree final /* : public BinarySearchTree */ {
36public:
39 using CodeTy = typename Traits::CodeTy;
40
41 struct Branch;
42 struct Leaf;
43
44 struct Node {
45 enum class Type : uint8_t { Branch, Leaf };
46
47 explicit virtual operator Type() const = 0;
48
50 assert(Node::Type::Branch == static_cast<Node::Type>(*this));
51 return static_cast<Branch&>(*this);
52 }
53
55 assert(Node::Type::Leaf == static_cast<Node::Type>(*this));
56 return static_cast<Leaf&>(*this);
57 }
58
59 virtual ~Node() = default;
60 };
61
62 struct Branch final : public Node {
63 explicit operator typename Node::Type() const final {
64 return Node::Type::Branch;
65 }
66
67 std::array<std::unique_ptr<Node>, 2> buds;
68 };
69
70 struct Leaf final : public Node {
71 explicit operator typename Node::Type() const final {
72 return Node::Type::Leaf;
73 }
74
76
77 Leaf() = default;
78
79 explicit Leaf(CodeTy value_) : value(value_) {}
80 };
81
82 void add(CodeSymbol symbol, CodeTy value);
83
84 std::unique_ptr<Node> root;
85};
86
87template <typename CodeTag>
89 invariant(symbol.code_len > 0);
90 invariant(symbol.code_len <= Traits::MaxCodeLenghtBits);
91
92 CodeSymbol partial;
93 partial.code = 0;
94 partial.code_len = 0;
95
96 std::reference_wrapper<std::unique_ptr<Node>> newBud = root;
97 for (unsigned bit : symbol.getBitsMSB()) {
98 ++partial.code_len;
99 partial.code =
100 implicit_cast<typename Traits::CodeTy>((partial.code << 1) | bit);
101 std::unique_ptr<Node>& bud = newBud;
102 if (!bud)
103 bud = std::make_unique<Branch>();
104 // NOTE: if this bud is already a Leaf, this is not a prefix code.
105 newBud = bud->getAsBranch().buds[bit];
106 }
107 invariant(partial == symbol && "Failed to interpret symbol as bit sequence.");
108
109 std::unique_ptr<Node>& bud = newBud;
110 assert(!bud && "This Node should be vacant!");
111
112 // And add this node/leaf to tree in the given position
113 bud = std::make_unique<Leaf>(value);
114}
115
116} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
assert(dim.area() >=area)
typename AbstractPrefixCode< CodeTag >::Traits Traits
std::unique_ptr< Node > root
typename Traits::CodeTy CodeTy
void add(CodeSymbol symbol, CodeTy value)
typename AbstractPrefixCode< CodeTag >::CodeSymbol CodeSymbol
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
std::array< std::unique_ptr< Node >, 2 > buds