1*f6dc9357SAndroid Build Coastguard Worker // Rar3Decoder.h 2*f6dc9357SAndroid Build Coastguard Worker // According to unRAR license, this code may not be used to develop 3*f6dc9357SAndroid Build Coastguard Worker // a program that creates RAR archives 4*f6dc9357SAndroid Build Coastguard Worker 5*f6dc9357SAndroid Build Coastguard Worker /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_COMPRESS_RAR3_DECODER_H 8*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_COMPRESS_RAR3_DECODER_H 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Ppmd7.h" 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyCom.h" 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker #include "../ICoder.h" 15*f6dc9357SAndroid Build Coastguard Worker 16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InBuffer.h" 17*f6dc9357SAndroid Build Coastguard Worker 18*f6dc9357SAndroid Build Coastguard Worker #include "BitmDecoder.h" 19*f6dc9357SAndroid Build Coastguard Worker #include "HuffmanDecoder.h" 20*f6dc9357SAndroid Build Coastguard Worker #include "Rar3Vm.h" 21*f6dc9357SAndroid Build Coastguard Worker 22*f6dc9357SAndroid Build Coastguard Worker namespace NCompress { 23*f6dc9357SAndroid Build Coastguard Worker namespace NRar3 { 24*f6dc9357SAndroid Build Coastguard Worker 25*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumHuffmanBits = 15; 26*f6dc9357SAndroid Build Coastguard Worker 27*f6dc9357SAndroid Build Coastguard Worker const UInt32 kWindowSize = 1 << 22; 28*f6dc9357SAndroid Build Coastguard Worker const UInt32 kWindowMask = kWindowSize - 1; 29*f6dc9357SAndroid Build Coastguard Worker 30*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumReps = 4; 31*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumLen2Symbols = 8; 32*f6dc9357SAndroid Build Coastguard Worker const unsigned kLenTableSize = 28; 33*f6dc9357SAndroid Build Coastguard Worker const unsigned kMainTableSize = 256 + 3 + kNumReps + kNumLen2Symbols + kLenTableSize; 34*f6dc9357SAndroid Build Coastguard Worker const unsigned kDistTableSize = 60; 35*f6dc9357SAndroid Build Coastguard Worker 36*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumAlignBits = 4; 37*f6dc9357SAndroid Build Coastguard Worker const unsigned kAlignTableSize = (1 << kNumAlignBits) + 1; 38*f6dc9357SAndroid Build Coastguard Worker 39*f6dc9357SAndroid Build Coastguard Worker const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize; 40*f6dc9357SAndroid Build Coastguard Worker 41*f6dc9357SAndroid Build Coastguard Worker class CBitDecoder 42*f6dc9357SAndroid Build Coastguard Worker { 43*f6dc9357SAndroid Build Coastguard Worker UInt32 _value; 44*f6dc9357SAndroid Build Coastguard Worker unsigned _bitPos; 45*f6dc9357SAndroid Build Coastguard Worker public: 46*f6dc9357SAndroid Build Coastguard Worker CInBuffer Stream; 47*f6dc9357SAndroid Build Coastguard Worker Create(UInt32 bufSize)48*f6dc9357SAndroid Build Coastguard Worker bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } SetStream(ISequentialInStream * inStream)49*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialInStream *inStream) { Stream.SetStream(inStream);} 50*f6dc9357SAndroid Build Coastguard Worker Init()51*f6dc9357SAndroid Build Coastguard Worker void Init() 52*f6dc9357SAndroid Build Coastguard Worker { 53*f6dc9357SAndroid Build Coastguard Worker Stream.Init(); 54*f6dc9357SAndroid Build Coastguard Worker _bitPos = 0; 55*f6dc9357SAndroid Build Coastguard Worker _value = 0; 56*f6dc9357SAndroid Build Coastguard Worker } 57*f6dc9357SAndroid Build Coastguard Worker ExtraBitsWereRead()58*f6dc9357SAndroid Build Coastguard Worker bool ExtraBitsWereRead() const 59*f6dc9357SAndroid Build Coastguard Worker { 60*f6dc9357SAndroid Build Coastguard Worker return (Stream.NumExtraBytes > 4 || _bitPos < (Stream.NumExtraBytes << 3)); 61*f6dc9357SAndroid Build Coastguard Worker } 62*f6dc9357SAndroid Build Coastguard Worker GetProcessedSize()63*f6dc9357SAndroid Build Coastguard Worker UInt64 GetProcessedSize() const { return Stream.GetProcessedSize() - (_bitPos >> 3); } 64*f6dc9357SAndroid Build Coastguard Worker AlignToByte()65*f6dc9357SAndroid Build Coastguard Worker void AlignToByte() 66*f6dc9357SAndroid Build Coastguard Worker { 67*f6dc9357SAndroid Build Coastguard Worker _bitPos &= ~(unsigned)7; 68*f6dc9357SAndroid Build Coastguard Worker _value = _value & ((1 << _bitPos) - 1); 69*f6dc9357SAndroid Build Coastguard Worker } 70*f6dc9357SAndroid Build Coastguard Worker 71*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue(unsigned numBits)72*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue(unsigned numBits) 73*f6dc9357SAndroid Build Coastguard Worker { 74*f6dc9357SAndroid Build Coastguard Worker if (_bitPos < numBits) 75*f6dc9357SAndroid Build Coastguard Worker { 76*f6dc9357SAndroid Build Coastguard Worker _bitPos += 8; 77*f6dc9357SAndroid Build Coastguard Worker _value = (_value << 8) | Stream.ReadByte(); 78*f6dc9357SAndroid Build Coastguard Worker if (_bitPos < numBits) 79*f6dc9357SAndroid Build Coastguard Worker { 80*f6dc9357SAndroid Build Coastguard Worker _bitPos += 8; 81*f6dc9357SAndroid Build Coastguard Worker _value = (_value << 8) | Stream.ReadByte(); 82*f6dc9357SAndroid Build Coastguard Worker } 83*f6dc9357SAndroid Build Coastguard Worker } 84*f6dc9357SAndroid Build Coastguard Worker return _value >> (_bitPos - numBits); 85*f6dc9357SAndroid Build Coastguard Worker } 86*f6dc9357SAndroid Build Coastguard Worker 87*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue_InHigh32bits()88*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue_InHigh32bits() 89*f6dc9357SAndroid Build Coastguard Worker { 90*f6dc9357SAndroid Build Coastguard Worker return GetValue(kNumHuffmanBits) << (32 - kNumHuffmanBits); 91*f6dc9357SAndroid Build Coastguard Worker } 92*f6dc9357SAndroid Build Coastguard Worker 93*f6dc9357SAndroid Build Coastguard Worker 94*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE MovePos(unsigned numBits)95*f6dc9357SAndroid Build Coastguard Worker void MovePos(unsigned numBits) 96*f6dc9357SAndroid Build Coastguard Worker { 97*f6dc9357SAndroid Build Coastguard Worker _bitPos -= numBits; 98*f6dc9357SAndroid Build Coastguard Worker _value = _value & ((1 << _bitPos) - 1); 99*f6dc9357SAndroid Build Coastguard Worker } 100*f6dc9357SAndroid Build Coastguard Worker ReadBits(unsigned numBits)101*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(unsigned numBits) 102*f6dc9357SAndroid Build Coastguard Worker { 103*f6dc9357SAndroid Build Coastguard Worker const UInt32 res = GetValue(numBits); 104*f6dc9357SAndroid Build Coastguard Worker MovePos(numBits); 105*f6dc9357SAndroid Build Coastguard Worker return res; 106*f6dc9357SAndroid Build Coastguard Worker } 107*f6dc9357SAndroid Build Coastguard Worker ReadBits_upto8(unsigned numBits)108*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits_upto8(unsigned numBits) 109*f6dc9357SAndroid Build Coastguard Worker { 110*f6dc9357SAndroid Build Coastguard Worker if (_bitPos < numBits) 111*f6dc9357SAndroid Build Coastguard Worker { 112*f6dc9357SAndroid Build Coastguard Worker _bitPos += 8; 113*f6dc9357SAndroid Build Coastguard Worker _value = (_value << 8) | Stream.ReadByte(); 114*f6dc9357SAndroid Build Coastguard Worker } 115*f6dc9357SAndroid Build Coastguard Worker _bitPos -= numBits; 116*f6dc9357SAndroid Build Coastguard Worker const UInt32 res = _value >> _bitPos; 117*f6dc9357SAndroid Build Coastguard Worker _value = _value & ((1 << _bitPos) - 1); 118*f6dc9357SAndroid Build Coastguard Worker return res; 119*f6dc9357SAndroid Build Coastguard Worker } 120*f6dc9357SAndroid Build Coastguard Worker ReadByteFromAligned()121*f6dc9357SAndroid Build Coastguard Worker Byte ReadByteFromAligned() 122*f6dc9357SAndroid Build Coastguard Worker { 123*f6dc9357SAndroid Build Coastguard Worker if (_bitPos == 0) 124*f6dc9357SAndroid Build Coastguard Worker return Stream.ReadByte(); 125*f6dc9357SAndroid Build Coastguard Worker const unsigned bitsPos = _bitPos - 8; 126*f6dc9357SAndroid Build Coastguard Worker const Byte b = (Byte)(_value >> bitsPos); 127*f6dc9357SAndroid Build Coastguard Worker _value = _value & ((1 << bitsPos) - 1); 128*f6dc9357SAndroid Build Coastguard Worker _bitPos = bitsPos; 129*f6dc9357SAndroid Build Coastguard Worker return b; 130*f6dc9357SAndroid Build Coastguard Worker } 131*f6dc9357SAndroid Build Coastguard Worker }; 132*f6dc9357SAndroid Build Coastguard Worker 133*f6dc9357SAndroid Build Coastguard Worker 134*f6dc9357SAndroid Build Coastguard Worker struct CByteIn 135*f6dc9357SAndroid Build Coastguard Worker { 136*f6dc9357SAndroid Build Coastguard Worker IByteIn IByteIn_obj; 137*f6dc9357SAndroid Build Coastguard Worker CBitDecoder BitDecoder; 138*f6dc9357SAndroid Build Coastguard Worker }; 139*f6dc9357SAndroid Build Coastguard Worker 140*f6dc9357SAndroid Build Coastguard Worker 141*f6dc9357SAndroid Build Coastguard Worker struct CFilter: public NVm::CProgram 142*f6dc9357SAndroid Build Coastguard Worker { 143*f6dc9357SAndroid Build Coastguard Worker CRecordVector<Byte> GlobalData; 144*f6dc9357SAndroid Build Coastguard Worker UInt32 BlockStart; 145*f6dc9357SAndroid Build Coastguard Worker UInt32 BlockSize; 146*f6dc9357SAndroid Build Coastguard Worker UInt32 ExecCount; 147*f6dc9357SAndroid Build Coastguard Worker CFilterCFilter148*f6dc9357SAndroid Build Coastguard Worker CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} 149*f6dc9357SAndroid Build Coastguard Worker }; 150*f6dc9357SAndroid Build Coastguard Worker 151*f6dc9357SAndroid Build Coastguard Worker struct CTempFilter: public NVm::CProgramInitState 152*f6dc9357SAndroid Build Coastguard Worker { 153*f6dc9357SAndroid Build Coastguard Worker UInt32 BlockStart; 154*f6dc9357SAndroid Build Coastguard Worker UInt32 BlockSize; 155*f6dc9357SAndroid Build Coastguard Worker bool NextWindow; 156*f6dc9357SAndroid Build Coastguard Worker 157*f6dc9357SAndroid Build Coastguard Worker UInt32 FilterIndex; 158*f6dc9357SAndroid Build Coastguard Worker CTempFilterCTempFilter159*f6dc9357SAndroid Build Coastguard Worker CTempFilter() 160*f6dc9357SAndroid Build Coastguard Worker { 161*f6dc9357SAndroid Build Coastguard Worker // all filters must contain at least FixedGlobal block 162*f6dc9357SAndroid Build Coastguard Worker AllocateEmptyFixedGlobal(); 163*f6dc9357SAndroid Build Coastguard Worker } 164*f6dc9357SAndroid Build Coastguard Worker }; 165*f6dc9357SAndroid Build Coastguard Worker 166*f6dc9357SAndroid Build Coastguard Worker 167*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_2( 168*f6dc9357SAndroid Build Coastguard Worker CDecoder 169*f6dc9357SAndroid Build Coastguard Worker , ICompressCoder 170*f6dc9357SAndroid Build Coastguard Worker , ICompressSetDecoderProperties2 171*f6dc9357SAndroid Build Coastguard Worker ) 172*f6dc9357SAndroid Build Coastguard Worker bool _isSolid; 173*f6dc9357SAndroid Build Coastguard Worker bool _solidAllowed; 174*f6dc9357SAndroid Build Coastguard Worker // bool _errorMode; 175*f6dc9357SAndroid Build Coastguard Worker 176*f6dc9357SAndroid Build Coastguard Worker bool _lzMode; 177*f6dc9357SAndroid Build Coastguard Worker bool _unsupportedFilter; 178*f6dc9357SAndroid Build Coastguard Worker 179*f6dc9357SAndroid Build Coastguard Worker CByteIn m_InBitStream; 180*f6dc9357SAndroid Build Coastguard Worker Byte *_window; 181*f6dc9357SAndroid Build Coastguard Worker UInt32 _winPos; 182*f6dc9357SAndroid Build Coastguard Worker UInt32 _wrPtr; 183*f6dc9357SAndroid Build Coastguard Worker UInt64 _lzSize; 184*f6dc9357SAndroid Build Coastguard Worker UInt64 _unpackSize; 185*f6dc9357SAndroid Build Coastguard Worker UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written 186*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *_outStream; 187*f6dc9357SAndroid Build Coastguard Worker 188*f6dc9357SAndroid Build Coastguard Worker NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, 9> m_MainDecoder; 189*f6dc9357SAndroid Build Coastguard Worker UInt32 kDistStart[kDistTableSize]; 190*f6dc9357SAndroid Build Coastguard Worker NHuffman::CDecoder256<kNumHuffmanBits, kDistTableSize, 7> m_DistDecoder; 191*f6dc9357SAndroid Build Coastguard Worker NHuffman::CDecoder256<kNumHuffmanBits, kAlignTableSize, 6> m_AlignDecoder; 192*f6dc9357SAndroid Build Coastguard Worker NHuffman::CDecoder256<kNumHuffmanBits, kLenTableSize, 7> m_LenDecoder; 193*f6dc9357SAndroid Build Coastguard Worker 194*f6dc9357SAndroid Build Coastguard Worker UInt32 _reps[kNumReps]; 195*f6dc9357SAndroid Build Coastguard Worker UInt32 _lastLength; 196*f6dc9357SAndroid Build Coastguard Worker 197*f6dc9357SAndroid Build Coastguard Worker Byte m_LastLevels[kTablesSizesSum]; 198*f6dc9357SAndroid Build Coastguard Worker 199*f6dc9357SAndroid Build Coastguard Worker Byte *_vmData; 200*f6dc9357SAndroid Build Coastguard Worker Byte *_vmCode; 201*f6dc9357SAndroid Build Coastguard Worker NVm::CVm _vm; 202*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CFilter *> _filters; 203*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CTempFilter *> _tempFilters; 204*f6dc9357SAndroid Build Coastguard Worker unsigned _numEmptyTempFilters; 205*f6dc9357SAndroid Build Coastguard Worker UInt32 _lastFilter; 206*f6dc9357SAndroid Build Coastguard Worker 207*f6dc9357SAndroid Build Coastguard Worker UInt32 PrevAlignBits; 208*f6dc9357SAndroid Build Coastguard Worker UInt32 PrevAlignCount; 209*f6dc9357SAndroid Build Coastguard Worker 210*f6dc9357SAndroid Build Coastguard Worker bool TablesRead; 211*f6dc9357SAndroid Build Coastguard Worker bool TablesOK; 212*f6dc9357SAndroid Build Coastguard Worker bool PpmError; 213*f6dc9357SAndroid Build Coastguard Worker 214*f6dc9357SAndroid Build Coastguard Worker int PpmEscChar; 215*f6dc9357SAndroid Build Coastguard Worker CPpmd7 _ppmd; 216*f6dc9357SAndroid Build Coastguard Worker 217*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteDataToStream(const Byte *data, UInt32 size); 218*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteData(const Byte *data, UInt32 size); 219*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); 220*f6dc9357SAndroid Build Coastguard Worker void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef); 221*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteBuf(); 222*f6dc9357SAndroid Build Coastguard Worker 223*f6dc9357SAndroid Build Coastguard Worker void InitFilters(); 224*f6dc9357SAndroid Build Coastguard Worker bool AddVmCode(UInt32 firstByte, UInt32 codeSize); 225*f6dc9357SAndroid Build Coastguard Worker bool ReadVmCodeLZ(); 226*f6dc9357SAndroid Build Coastguard Worker bool ReadVmCodePPM(); 227*f6dc9357SAndroid Build Coastguard Worker 228*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(unsigned numBits); 229*f6dc9357SAndroid Build Coastguard Worker 230*f6dc9357SAndroid Build Coastguard Worker HRESULT InitPPM(); 231*f6dc9357SAndroid Build Coastguard Worker // int DecodePpmSymbol(); 232*f6dc9357SAndroid Build Coastguard Worker HRESULT DecodePPM(Int32 num, bool &keepDecompressing); 233*f6dc9357SAndroid Build Coastguard Worker 234*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadTables(bool &keepDecompressing); 235*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadEndOfBlock(bool &keepDecompressing); 236*f6dc9357SAndroid Build Coastguard Worker HRESULT DecodeLZ(bool &keepDecompressing); 237*f6dc9357SAndroid Build Coastguard Worker HRESULT CodeReal(ICompressProgressInfo *progress); 238*f6dc9357SAndroid Build Coastguard Worker InputEofError()239*f6dc9357SAndroid Build Coastguard Worker bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); } InputEofError_Fast()240*f6dc9357SAndroid Build Coastguard Worker bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); } 241*f6dc9357SAndroid Build Coastguard Worker CopyBlock(UInt32 dist,UInt32 len)242*f6dc9357SAndroid Build Coastguard Worker void CopyBlock(UInt32 dist, UInt32 len) 243*f6dc9357SAndroid Build Coastguard Worker { 244*f6dc9357SAndroid Build Coastguard Worker _lzSize += len; 245*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = (_winPos - dist - 1) & kWindowMask; 246*f6dc9357SAndroid Build Coastguard Worker Byte *window = _window; 247*f6dc9357SAndroid Build Coastguard Worker UInt32 winPos = _winPos; 248*f6dc9357SAndroid Build Coastguard Worker if (kWindowSize - winPos > len && kWindowSize - pos > len) 249*f6dc9357SAndroid Build Coastguard Worker { 250*f6dc9357SAndroid Build Coastguard Worker const Byte *src = window + pos; 251*f6dc9357SAndroid Build Coastguard Worker Byte *dest = window + winPos; 252*f6dc9357SAndroid Build Coastguard Worker _winPos += len; 253*f6dc9357SAndroid Build Coastguard Worker do 254*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++; 255*f6dc9357SAndroid Build Coastguard Worker while (--len != 0); 256*f6dc9357SAndroid Build Coastguard Worker return; 257*f6dc9357SAndroid Build Coastguard Worker } 258*f6dc9357SAndroid Build Coastguard Worker do 259*f6dc9357SAndroid Build Coastguard Worker { 260*f6dc9357SAndroid Build Coastguard Worker window[winPos] = window[pos]; 261*f6dc9357SAndroid Build Coastguard Worker winPos = (winPos + 1) & kWindowMask; 262*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 1) & kWindowMask; 263*f6dc9357SAndroid Build Coastguard Worker } 264*f6dc9357SAndroid Build Coastguard Worker while (--len != 0); 265*f6dc9357SAndroid Build Coastguard Worker _winPos = winPos; 266*f6dc9357SAndroid Build Coastguard Worker } 267*f6dc9357SAndroid Build Coastguard Worker PutByte(Byte b)268*f6dc9357SAndroid Build Coastguard Worker void PutByte(Byte b) 269*f6dc9357SAndroid Build Coastguard Worker { 270*f6dc9357SAndroid Build Coastguard Worker const UInt32 wp = _winPos; 271*f6dc9357SAndroid Build Coastguard Worker _window[wp] = b; 272*f6dc9357SAndroid Build Coastguard Worker _winPos = (wp + 1) & kWindowMask; 273*f6dc9357SAndroid Build Coastguard Worker _lzSize++; 274*f6dc9357SAndroid Build Coastguard Worker } 275*f6dc9357SAndroid Build Coastguard Worker 276*f6dc9357SAndroid Build Coastguard Worker public: 277*f6dc9357SAndroid Build Coastguard Worker CDecoder(); 278*f6dc9357SAndroid Build Coastguard Worker ~CDecoder(); 279*f6dc9357SAndroid Build Coastguard Worker }; 280*f6dc9357SAndroid Build Coastguard Worker 281*f6dc9357SAndroid Build Coastguard Worker }} 282*f6dc9357SAndroid Build Coastguard Worker 283*f6dc9357SAndroid Build Coastguard Worker #endif 284