RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
BitVacuumer.h
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#pragma once
22
23#include "adt/Invariant.h"
25#include "io/Endianness.h"
26#include <concepts>
27#include <cstdint>
28#include <iterator>
29#include <type_traits>
30
31namespace rawspeed {
32
33template <typename BIT_STREAM> struct BitVacuumerTraits;
34
35template <typename Derived_, typename OutputIterator_>
36 requires std::output_iterator<OutputIterator_, uint8_t>
38public:
41
42 using Cache = typename StreamTraits::StreamFlow;
43
44 using Derived = Derived_;
46 using OutputIterator = OutputIterator_;
47
49
51
52 bool flushed = false;
53
55 static constexpr int chunk_bitwidth = 32;
56
57 void drainImpl() {
58 invariant(cache.fillLevel >= chunk_bitwidth);
59 static_assert(chunk_bitwidth == 32);
60
61 constexpr int StreamChunkBitwidth =
63 static_assert(chunk_bitwidth >= StreamChunkBitwidth);
64 static_assert(chunk_bitwidth % StreamChunkBitwidth == 0);
65 constexpr int NumChunksNeeded = chunk_bitwidth / StreamChunkBitwidth;
66 static_assert(NumChunksNeeded >= 1);
67
68 for (int i = 0; i != NumChunksNeeded; ++i) {
70 cache.peek(StreamChunkBitwidth));
72 &chunk, StreamTraits::ChunkEndianness != Endianness::little);
73 cache.skip(StreamChunkBitwidth);
74
75 *output = chunk;
76 ++output;
77 }
78 }
79
80 void drain() {
82
83 if (cache.fillLevel < chunk_bitwidth)
84 return; // NOTE: does not mean the cache is empty!
85
86 static_cast<Derived*>(this)->drainImpl();
87 invariant(cache.fillLevel < chunk_bitwidth);
88 }
89
90 void flush() {
91 drain();
92
93 if (cache.fillLevel == 0) {
94 flushed = true;
95 return;
96 }
97
98 // Pad with zero bits, so we can drain the partial chunk.
99 put(/*bits=*/0, chunk_bitwidth - cache.fillLevel);
100 invariant(cache.fillLevel == chunk_bitwidth);
101
102 drain();
103
104 invariant(cache.fillLevel == 0);
105 flushed = true;
106 }
107
108 BitVacuumer() = delete;
109
110 BitVacuumer(const BitVacuumer&) = delete;
114
115 template <typename U>
116 requires std::same_as<OutputIterator, std::remove_reference_t<U>>
117 explicit BitVacuumer(U&& output_) : output(std::forward<U>(output_)) {}
118
120
121 void put(uint32_t bits, int count) {
122 invariant(count >= 0);
123 // NOTE: count may be zero!
124 drain();
125 cache.push(bits, count);
126 }
127};
128
129} // namespace rawspeed
Declaration of the bitstream data structure.
#define invariant(expr)
Definition Invariant.h:27
OutputIterator_ OutputIterator
Definition BitVacuumer.h:46
BitVacuumer(const BitVacuumer &)=delete
BitStreamTraits< Traits::Tag > StreamTraits
Definition BitVacuumer.h:40
typename StreamTraits::StreamFlow Cache
Definition BitVacuumer.h:42
BitVacuumer(U &&output_)
BitVacuumer(BitVacuumer &&)=delete
void put(uint32_t bits, int count)
BitVacuumerTraits< Derived_ > Traits
Definition BitVacuumer.h:39
BitVacuumer & operator=(BitVacuumer &&)=delete
BitVacuumer & operator=(const BitVacuumer &)=delete
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
int8_t getByteSwapped(int8_t v)
Definition Endianness.h:75
constexpr unsigned RAWSPEED_READNONE bitwidth(T unused={})
Definition Bit.h:43