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