michael@0: // LSBFDecoder.h michael@0: michael@0: #ifndef __STREAM_LSBFDECODER_H michael@0: #define __STREAM_LSBFDECODER_H michael@0: michael@0: #include "../IStream.h" michael@0: michael@0: namespace NStream { michael@0: namespace NLSBF { michael@0: michael@0: const int kNumBigValueBits = 8 * 4; michael@0: michael@0: const int kNumValueBytes = 3; michael@0: const int kNumValueBits = 8 * kNumValueBytes; michael@0: michael@0: const UInt32 kMask = (1 << kNumValueBits) - 1; michael@0: michael@0: extern Byte kInvertTable[256]; michael@0: // the Least Significant Bit of byte is First michael@0: michael@0: template michael@0: class CBaseDecoder michael@0: { michael@0: protected: michael@0: int m_BitPos; michael@0: UInt32 m_Value; michael@0: TInByte m_Stream; michael@0: public: michael@0: UInt32 NumExtraBytes; michael@0: bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } michael@0: void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); } michael@0: void ReleaseStream() { m_Stream.ReleaseStream(); } michael@0: void Init() michael@0: { michael@0: m_Stream.Init(); michael@0: m_BitPos = kNumBigValueBits; michael@0: m_Value = 0; michael@0: NumExtraBytes = 0; michael@0: } michael@0: UInt64 GetProcessedSize() const michael@0: { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } michael@0: UInt64 GetProcessedBitsSize() const michael@0: { return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); } michael@0: int GetBitPosition() const { return (m_BitPos & 7); } michael@0: michael@0: void Normalize() michael@0: { michael@0: for (;m_BitPos >= 8; m_BitPos -= 8) michael@0: { michael@0: Byte b; michael@0: if (!m_Stream.ReadByte(b)) michael@0: { michael@0: b = 0xFF; // check it michael@0: NumExtraBytes++; michael@0: } michael@0: m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value; michael@0: } michael@0: } michael@0: michael@0: UInt32 ReadBits(int numBits) michael@0: { michael@0: Normalize(); michael@0: UInt32 res = m_Value & ((1 << numBits) - 1); michael@0: m_BitPos += numBits; michael@0: m_Value >>= numBits; michael@0: return res; michael@0: } michael@0: michael@0: bool ExtraBitsWereRead() const michael@0: { michael@0: if (NumExtraBytes == 0) michael@0: return false; michael@0: return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3)); michael@0: } michael@0: }; michael@0: michael@0: template michael@0: class CDecoder: public CBaseDecoder michael@0: { michael@0: UInt32 m_NormalValue; michael@0: michael@0: public: michael@0: void Init() michael@0: { michael@0: CBaseDecoder::Init(); michael@0: m_NormalValue = 0; michael@0: } michael@0: michael@0: void Normalize() michael@0: { michael@0: for (;this->m_BitPos >= 8; this->m_BitPos -= 8) michael@0: { michael@0: Byte b; michael@0: if (!this->m_Stream.ReadByte(b)) michael@0: { michael@0: b = 0xFF; // check it michael@0: this->NumExtraBytes++; michael@0: } michael@0: m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue; michael@0: this->m_Value = (this->m_Value << 8) | kInvertTable[b]; michael@0: } michael@0: } michael@0: michael@0: UInt32 GetValue(int numBits) michael@0: { michael@0: Normalize(); michael@0: return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits); michael@0: } michael@0: michael@0: void MovePos(int numBits) michael@0: { michael@0: this->m_BitPos += numBits; michael@0: m_NormalValue >>= numBits; michael@0: } michael@0: michael@0: UInt32 ReadBits(int numBits) michael@0: { michael@0: Normalize(); michael@0: UInt32 res = m_NormalValue & ( (1 << numBits) - 1); michael@0: MovePos(numBits); michael@0: return res; michael@0: } michael@0: }; michael@0: michael@0: }} michael@0: michael@0: #endif