mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
142 lines
2.9 KiB
C++
Executable File
142 lines
2.9 KiB
C++
Executable File
// BitlDecoder.h -- the Least Significant Bit of byte is First
|
|
|
|
#ifndef __BITL_DECODER_H
|
|
#define __BITL_DECODER_H
|
|
|
|
#include "../IStream.h"
|
|
|
|
namespace NBitl {
|
|
|
|
const unsigned kNumBigValueBits = 8 * 4;
|
|
const unsigned kNumValueBytes = 3;
|
|
const unsigned kNumValueBits = 8 * kNumValueBytes;
|
|
|
|
const UInt32 kMask = (1 << kNumValueBits) - 1;
|
|
|
|
extern Byte kInvertTable[256];
|
|
|
|
template<class TInByte>
|
|
class CBaseDecoder
|
|
{
|
|
protected:
|
|
unsigned m_BitPos;
|
|
UInt32 m_Value;
|
|
TInByte m_Stream;
|
|
public:
|
|
UInt32 NumExtraBytes;
|
|
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
|
void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); }
|
|
void ReleaseStream() { m_Stream.ReleaseStream(); }
|
|
void Init()
|
|
{
|
|
m_Stream.Init();
|
|
m_BitPos = kNumBigValueBits;
|
|
m_Value = 0;
|
|
NumExtraBytes = 0;
|
|
}
|
|
UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + NumExtraBytes - (kNumBigValueBits - m_BitPos) / 8; }
|
|
|
|
void Normalize()
|
|
{
|
|
for (; m_BitPos >= 8; m_BitPos -= 8)
|
|
{
|
|
Byte b = 0;
|
|
if (!m_Stream.ReadByte(b))
|
|
{
|
|
b = 0xFF; // check it
|
|
NumExtraBytes++;
|
|
}
|
|
m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value;
|
|
}
|
|
}
|
|
|
|
UInt32 ReadBits(unsigned numBits)
|
|
{
|
|
Normalize();
|
|
UInt32 res = m_Value & ((1 << numBits) - 1);
|
|
m_BitPos += numBits;
|
|
m_Value >>= numBits;
|
|
return res;
|
|
}
|
|
|
|
bool ExtraBitsWereRead() const
|
|
{
|
|
if (NumExtraBytes == 0)
|
|
return false;
|
|
return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3));
|
|
}
|
|
};
|
|
|
|
template<class TInByte>
|
|
class CDecoder: public CBaseDecoder<TInByte>
|
|
{
|
|
UInt32 m_NormalValue;
|
|
|
|
public:
|
|
void Init()
|
|
{
|
|
CBaseDecoder<TInByte>::Init();
|
|
m_NormalValue = 0;
|
|
}
|
|
|
|
void Normalize()
|
|
{
|
|
for (; this->m_BitPos >= 8; this->m_BitPos -= 8)
|
|
{
|
|
Byte b = 0;
|
|
if (!this->m_Stream.ReadByte(b))
|
|
{
|
|
b = 0xFF; // check it
|
|
this->NumExtraBytes++;
|
|
}
|
|
m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue;
|
|
this->m_Value = (this->m_Value << 8) | kInvertTable[b];
|
|
}
|
|
}
|
|
|
|
UInt32 GetValue(unsigned numBits)
|
|
{
|
|
Normalize();
|
|
return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits);
|
|
}
|
|
|
|
void MovePos(unsigned numBits)
|
|
{
|
|
this->m_BitPos += numBits;
|
|
m_NormalValue >>= numBits;
|
|
}
|
|
|
|
UInt32 ReadBits(unsigned numBits)
|
|
{
|
|
Normalize();
|
|
UInt32 res = m_NormalValue & ((1 << numBits) - 1);
|
|
MovePos(numBits);
|
|
return res;
|
|
}
|
|
|
|
void AlignToByte() { MovePos((32 - this->m_BitPos) & 7); }
|
|
|
|
Byte ReadByte()
|
|
{
|
|
if (this->m_BitPos == kNumBigValueBits)
|
|
{
|
|
Byte b = 0;
|
|
if (!this->m_Stream.ReadByte(b))
|
|
{
|
|
b = 0xFF;
|
|
this->NumExtraBytes++;
|
|
}
|
|
return b;
|
|
}
|
|
{
|
|
Byte b = (Byte)(m_NormalValue & 0xFF);
|
|
MovePos(8);
|
|
return b;
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|