diff options
Diffstat (limited to 'CPP/7zip/Compress/Rar/Rar3Decoder.h')
-rwxr-xr-x | CPP/7zip/Compress/Rar/Rar3Decoder.h | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/Rar/Rar3Decoder.h b/CPP/7zip/Compress/Rar/Rar3Decoder.h new file mode 100755 index 00000000..ec07a4d3 --- /dev/null +++ b/CPP/7zip/Compress/Rar/Rar3Decoder.h @@ -0,0 +1,294 @@ +// Rar3Decoder.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR3DECODER_H +#define __RAR3DECODER_H + +#include "../../../Common/MyCom.h" + +#include "../../ICoder.h" +#include "../../Common/MSBFDecoder.h" +#include "../../Common/InBuffer.h" + +// #include "../LZ/LZOutWindow.h" +#include "../Huffman/HuffmanDecoder.h" +#include "../PPMD/PPMDDecode.h" +#include "Rar3Vm.h" + +namespace NCompress { +namespace NRar3 { + +const UInt32 kWindowSize = 1 << 22; +const UInt32 kWindowMask = (kWindowSize - 1); + +const UInt32 kNumReps = 4; +const UInt32 kNumLen2Symbols = 8; +const UInt32 kLenTableSize = 28; +const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize; +const UInt32 kDistTableSize = 60; + +const int kNumAlignBits = 4; +const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1; + +const UInt32 kLevelTableSize = 20; + +const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize; + +template<class TInByte> +class CBitDecoder2 +{ + UInt32 m_Value; +public: + UInt32 m_BitPos; + TInByte m_Stream; + 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 = 0; + m_Value = 0; + // m_BitPos = kNumBigValueBits; + // Normalize(); + } + + UInt64 GetProcessedSize() const + { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; } + UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); } + + /* + void Normalize() + { + for (;m_BitPos >= 8; m_BitPos -= 8) + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + } + */ + + UInt32 GetValue(UInt32 numBits) + { + // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits); + // return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits); + if (m_BitPos < numBits) + { + m_BitPos += 8; + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + if (m_BitPos < numBits) + { + m_BitPos += 8; + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + } + } + return m_Value >> (m_BitPos - numBits); + } + + void MovePos(UInt32 numBits) + { + m_BitPos -= numBits; + m_Value = m_Value & ((1 << m_BitPos) - 1); + } + + UInt32 ReadBits(UInt32 numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } +}; + +typedef CBitDecoder2<CInBuffer> CBitDecoder; + +const int kNumTopBits = 24; +const UInt32 kTopValue = (1 << kNumTopBits); +const UInt32 kBot = (1 << 15); + +class CRangeDecoder:public NPPMD::CRangeDecoderVirt, public CBitDecoder +{ +public: + UInt32 Range; + UInt32 Low; + UInt32 Code; + + void Normalize() + { + while ((Low ^ (Low + Range)) < kTopValue || + Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) + { + Code = (Code << 8) | m_Stream.ReadByte(); + Range <<= 8; + Low <<= 8; + } + } + + void InitRangeCoder() + { + Code = 0; + Low = 0; + Range = 0xFFFFFFFF; + for(int i = 0; i < 4; i++) + Code = (Code << 8) | ReadBits(8); + } + + virtual UInt32 GetThreshold(UInt32 total) + { + return (Code - Low) / ( Range /= total); + } + + virtual void Decode(UInt32 start, UInt32 size) + { + Low += start * Range; + Range *= size; + Normalize(); + } + + virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + { + if (((Code - Low) / (Range >>= numTotalBits)) < size0) + { + Decode(0, size0); + return 0; + } + else + { + Decode(size0, (1 << numTotalBits) - size0); + return 1; + } + } + + // UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); } +}; + + +struct CFilter: public NVm::CProgram +{ + CRecordVector<Byte> GlobalData; + UInt32 BlockStart; + UInt32 BlockSize; + UInt32 ExecCount; + CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} +}; + +struct CTempFilter: public NVm::CProgramInitState +{ + UInt32 BlockStart; + UInt32 BlockSize; + UInt32 ExecCount; + bool NextWindow; + + UInt32 FilterIndex; +}; + +const int kNumHuffmanBits = 15; + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + CRangeDecoder m_InBitStream; + Byte *_window; + UInt32 _winPos; + UInt32 _wrPtr; + UInt64 _lzSize; + UInt64 _unpackSize; + UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written + CMyComPtr<ISequentialOutStream> _outStream; + NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder; + + UInt32 _reps[kNumReps]; + UInt32 _lastLength; + + Byte m_LastLevels[kTablesSizesSum]; + + Byte *_vmData; + Byte *_vmCode; + NVm::CVm _vm; + CRecordVector<CFilter *> _filters; + CRecordVector<CTempFilter *> _tempFilters; + UInt32 _lastFilter; + + bool m_IsSolid; + + bool _lzMode; + + UInt32 PrevAlignBits; + UInt32 PrevAlignCount; + + bool TablesRead; + + NPPMD::CDecodeInfo _ppm; + int PpmEscChar; + + HRESULT WriteDataToStream(const Byte *data, UInt32 size); + HRESULT WriteData(const Byte *data, UInt32 size); + HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); + void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef); + HRESULT WriteBuf(); + + void InitFilters(); + bool AddVmCode(UInt32 firstByte, UInt32 codeSize); + bool ReadVmCodeLZ(); + bool ReadVmCodePPM(); + + UInt32 ReadBits(int numBits); + + HRESULT InitPPM(); + int DecodePpmSymbol(); + HRESULT DecodePPM(Int32 num, bool &keepDecompressing); + + HRESULT ReadTables(bool &keepDecompressing); + HRESULT ReadEndOfBlock(bool &keepDecompressing); + HRESULT DecodeLZ(bool &keepDecompressing); + HRESULT CodeReal(ICompressProgressInfo *progress); +public: + CDecoder(); + ~CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams() + { + _outStream.Release(); + m_InBitStream.ReleaseStream(); + } + + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + void CopyBlock(UInt32 distance, UInt32 len) + { + _lzSize += len; + UInt32 pos = (_winPos - distance - 1) & kWindowMask; + do + { + _window[_winPos] = _window[pos]; + _winPos = (_winPos + 1) & kWindowMask; + pos = (pos + 1) & kWindowMask; + } + while(--len != 0); + } + + void PutByte(Byte b) + { + _window[_winPos] = b; + _winPos = (_winPos + 1) & kWindowMask; + _lzSize++; + } + + +}; + +}} + +#endif |