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