// 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 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 CDecoder: public CBaseDecoder { UInt32 m_NormalValue; public: void Init() { CBaseDecoder::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