25#include "rawspeedconfig.h"
59 ThrowIOE(
"Bit stream size is smaller than MaxProcessBytes");
63template <
typename Tag>
66 input.establishClassInvariants();
67 invariant(input.size() >= BitStreamerTraits<Tag>::MaxProcessBytes);
69 invariant(pos % StreamTraits::MinLoadStepByteMultiple == 0);
73template <
typename Tag>
74struct BitStreamerForwardSequentialReplenisher
76 using Base = BitStreamerReplenisherBase<Tag>;
77 using Traits = BitStreamerTraits<Tag>;
78 using StreamTraits = BitStreamTraits<Traits::Tag>;
80 using Base::BitStreamerReplenisherBase;
82 BitStreamerForwardSequentialReplenisher() =
delete;
84 [[nodiscard]]
typename Base::size_type getPos()
const {
85 Base::establishClassInvariants();
88 [[nodiscard]]
typename Base::size_type getRemainingSize()
const {
89 Base::establishClassInvariants();
90 return Base::input.size() - getPos();
92 void markNumBytesAsConsumed(
typename Base::size_type numBytes) {
93 Base::establishClassInvariants();
96 invariant(numBytes % StreamTraits::MinLoadStepByteMultiple == 0);
97 Base::pos += numBytes;
100 std::array<std::byte, BitStreamerTraits<Tag>::MaxProcessBytes>
getInput() {
101 Base::establishClassInvariants();
103 std::array<std::byte, BitStreamerTraits<Tag>::MaxProcessBytes> tmpStorage;
104 auto tmp = Array1DRef<std::byte>(tmpStorage.data(),
109 if (getPos() + BitStreamerTraits<Tag>::MaxProcessBytes <=
110 Base::input.
size()) [[likely]] {
112 Base::input.getCrop(getPos(), BitStreamerTraits<Tag>::MaxProcessBytes)
114 invariant(currInput.size() == tmp.size());
115 memcpy(tmp.begin(), currInput.begin(),
116 BitStreamerTraits<Tag>::MaxProcessBytes);
125 if (getPos() > Base::input.
size() +
126 2 * BitStreamerTraits<Tag>::MaxProcessBytes) [[unlikely]]
127 ThrowIOE(
"Buffer overflow read in BitStreamer");
135template <
typename Derived,
136 typename Replenisher =
137 BitStreamerForwardSequentialReplenisher<Derived>>
144 using Cache =
typename StreamTraits::StreamFlow;
162 invariant(input.size() == Traits::MaxProcessBytes);
164 constexpr int StreamChunkBitwidth =
166 static_assert(CHAR_BIT * Traits::MaxProcessBytes >= StreamChunkBitwidth);
167 static_assert(CHAR_BIT * Traits::MaxProcessBytes % StreamChunkBitwidth ==
169 constexpr int NumChunksNeeded =
170 (CHAR_BIT * Traits::MaxProcessBytes) / StreamChunkBitwidth;
171 static_assert(NumChunksNeeded >= 1);
173 for (
int i = 0; i != NumChunksNeeded; ++i) {
175 input.getBlock(
sizeof(
typename StreamTraits::ChunkType), i);
179 cache.push(chunk, StreamChunkBitwidth);
181 return Traits::MaxProcessBytes;
186 cache.establishClassInvariants();
205 if (bsPos.bytePos != 0)
206 replacement.replenisher.markNumBytesAsConsumed(bsPos.bytePos);
207 replacement.fill(Cache::MaxGetBits);
208 replacement.skipBitsNoFill(bsPos.numBitsToSkip);
210 replacement.getFillLevel() >
213 *
this = std::move(replacement);
216 void fill(
int nbits = Cache::MaxGetBits) {
222 if (
cache.fillLevel >= nbits)
226 const auto numBytes =
static_cast<Derived*
>(
this)->
fillCache(input);
250 return cache.fillLevel;
258 return cache.peek(nbits);
307 int remainingBitsToSkip = nbits;
308 for (; remainingBitsToSkip >= Cache::MaxGetBits;
309 remainingBitsToSkip -= Cache::MaxGetBits) {
310 fill(Cache::MaxGetBits);
313 if (remainingBitsToSkip > 0) {
314 fill(remainingBitsToSkip);
323 int nbits = 8 * nbytes;
Declaration of the bitstream data structure.
size_type fillCache(std::array< std::byte, BitStreamerTraits< Derived >::MaxProcessBytes > inputStorage)
void establishClassInvariants() const noexcept
size_type RAWSPEED_READONLY getInputPosition() const
BitStreamerTraits< Derived > Traits
size_type getRemainingSize() const
typename StreamTraits::StreamFlow Cache
BitStreamTraits< Traits::Tag > StreamTraits
size_type getStreamPosition() const
size_type RAWSPEED_READONLY getFillLevel() const
uint32_t peekBits(int nbits)
uint32_t getBitsNoFill(int nbits)
void skipBitsNoFill(int nbits)
BitStreamer(Array1DRef< const std::byte > input)
void skipManyBits(int nbits)
uint32_t getBits(int nbits)
uint32_t RAWSPEED_READONLY peekBitsNoFill(int nbits)
void fill(int nbits=Cache::MaxGetBits)
void skipBytes(int nbytes)
std::pair< WideType, std::vector< PartType > > getInput()
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
int8_t getByteSwapped(int8_t v)
ByteStreamPosition< bo > getAsByteStreamPosition(BitStreamPosition< bo > state)
Endianness getHostEndianness()
__attribute__((noinline)) __attribute__((visibility("default"))) JPEGStuffedByteStreamGenerator
constexpr unsigned RAWSPEED_READNONE bitwidth(T unused={})
void variableLengthLoadNaiveViaMemcpy(Array1DRef< std::byte > out, Array1DRef< const std::byte > in, int inPos)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
static constexpr int MaxGetBits
BitStreamTraits< Traits::Tag > StreamTraits
void establishClassInvariants() const noexcept
BitStreamerTraits< Tag > Traits
BitStreamerReplenisherBase()=delete
Array1DRef< const std::byte > input