diff options
Diffstat (limited to 'CPP/7zip/Common/LSBFDecoder.h')
-rwxr-xr-x | CPP/7zip/Common/LSBFDecoder.h | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/CPP/7zip/Common/LSBFDecoder.h b/CPP/7zip/Common/LSBFDecoder.h new file mode 100755 index 00000000..75458452 --- /dev/null +++ b/CPP/7zip/Common/LSBFDecoder.h @@ -0,0 +1,127 @@ +// LSBFDecoder.h + +#ifndef __STREAM_LSBFDECODER_H +#define __STREAM_LSBFDECODER_H + +#include "../IStream.h" + +namespace NStream { +namespace NLSBF { + +const int kNumBigValueBits = 8 * 4; + +const int kNumValueBytes = 3; +const int kNumValueBits = 8 * kNumValueBytes; + +const UInt32 kMask = (1 << kNumValueBits) - 1; + +extern Byte kInvertTable[256]; +// the Least Significant Bit of byte is First + +template<class TInByte> +class CBaseDecoder +{ +protected: + int 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() - (kNumBigValueBits - m_BitPos) / 8; } + UInt64 GetProcessedBitsSize() const + { return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); } + int GetBitPosition() const { return (m_BitPos & 7); } + + 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(int 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(int numBits) + { + Normalize(); + return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits); + } + + void MovePos(int numBits) + { + this->m_BitPos += numBits; + m_NormalValue >>= numBits; + } + + UInt32 ReadBits(int numBits) + { + Normalize(); + UInt32 res = m_NormalValue & ( (1 << numBits) - 1); + MovePos(numBits); + return res; + } +}; + +}} + +#endif |