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 __COMPRESS_RAR3_DECODER_H 8 #define __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 UInt32 kWindowSize = 1 << 22; 26 const UInt32 kWindowMask = (kWindowSize - 1); 27 28 const UInt32 kNumReps = 4; 29 const UInt32 kNumLen2Symbols = 8; 30 const UInt32 kLenTableSize = 28; 31 const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize; 32 const UInt32 kDistTableSize = 60; 33 34 const unsigned kNumAlignBits = 4; 35 const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1; 36 37 const UInt32 kLevelTableSize = 20; 38 39 const UInt32 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 GetValue(unsigned numBits)71 UInt32 GetValue(unsigned numBits) 72 { 73 if (_bitPos < numBits) 74 { 75 _bitPos += 8; 76 _value = (_value << 8) | Stream.ReadByte(); 77 if (_bitPos < numBits) 78 { 79 _bitPos += 8; 80 _value = (_value << 8) | Stream.ReadByte(); 81 } 82 } 83 return _value >> (_bitPos - numBits); 84 } 85 MovePos(unsigned numBits)86 void MovePos(unsigned numBits) 87 { 88 _bitPos -= numBits; 89 _value = _value & ((1 << _bitPos) - 1); 90 } 91 ReadBits(unsigned numBits)92 UInt32 ReadBits(unsigned numBits) 93 { 94 UInt32 res = GetValue(numBits); 95 MovePos(numBits); 96 return res; 97 } 98 }; 99 100 const UInt32 kTopValue = (1 << 24); 101 const UInt32 kBot = (1 << 15); 102 103 struct CRangeDecoder 104 { 105 IPpmd7_RangeDec vt; 106 UInt32 Range; 107 UInt32 Code; 108 UInt32 Low; 109 CBitDecoder BitDecoder; 110 SRes Res; 111 112 public: InitRangeCoderCRangeDecoder113 void InitRangeCoder() 114 { 115 Code = 0; 116 Low = 0; 117 Range = 0xFFFFFFFF; 118 for (int i = 0; i < 4; i++) 119 Code = (Code << 8) | BitDecoder.ReadBits(8); 120 } 121 NormalizeCRangeDecoder122 void Normalize() 123 { 124 while ((Low ^ (Low + Range)) < kTopValue || 125 Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) 126 { 127 Code = (Code << 8) | BitDecoder.Stream.ReadByte(); 128 Range <<= 8; 129 Low <<= 8; 130 } 131 } 132 133 CRangeDecoder() throw(); 134 }; 135 136 struct CFilter: public NVm::CProgram 137 { 138 CRecordVector<Byte> GlobalData; 139 UInt32 BlockStart; 140 UInt32 BlockSize; 141 UInt32 ExecCount; 142 CFilterCFilter143 CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} 144 }; 145 146 struct CTempFilter: public NVm::CProgramInitState 147 { 148 UInt32 BlockStart; 149 UInt32 BlockSize; 150 bool NextWindow; 151 152 UInt32 FilterIndex; 153 CTempFilterCTempFilter154 CTempFilter() 155 { 156 // all filters must contain at least FixedGlobal block 157 AllocateEmptyFixedGlobal(); 158 } 159 }; 160 161 const unsigned kNumHuffmanBits = 15; 162 163 class CDecoder: 164 public ICompressCoder, 165 public ICompressSetDecoderProperties2, 166 public CMyUnknownImp 167 { 168 CRangeDecoder m_InBitStream; 169 Byte *_window; 170 UInt32 _winPos; 171 UInt32 _wrPtr; 172 UInt64 _lzSize; 173 UInt64 _unpackSize; 174 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written 175 ISequentialOutStream *_outStream; 176 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; 177 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; 178 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; 179 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; 180 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder; 181 182 UInt32 _reps[kNumReps]; 183 UInt32 _lastLength; 184 185 Byte m_LastLevels[kTablesSizesSum]; 186 187 Byte *_vmData; 188 Byte *_vmCode; 189 NVm::CVm _vm; 190 CRecordVector<CFilter *> _filters; 191 CRecordVector<CTempFilter *> _tempFilters; 192 UInt32 _lastFilter; 193 194 bool m_IsSolid; 195 bool _errorMode; 196 197 bool _lzMode; 198 bool _unsupportedFilter; 199 200 UInt32 PrevAlignBits; 201 UInt32 PrevAlignCount; 202 203 bool TablesRead; 204 bool TablesOK; 205 206 CPpmd7 _ppmd; 207 int PpmEscChar; 208 bool PpmError; 209 210 HRESULT WriteDataToStream(const Byte *data, UInt32 size); 211 HRESULT WriteData(const Byte *data, UInt32 size); 212 HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); 213 void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef); 214 HRESULT WriteBuf(); 215 216 void InitFilters(); 217 bool AddVmCode(UInt32 firstByte, UInt32 codeSize); 218 bool ReadVmCodeLZ(); 219 bool ReadVmCodePPM(); 220 221 UInt32 ReadBits(unsigned numBits); 222 223 HRESULT InitPPM(); 224 int DecodePpmSymbol(); 225 HRESULT DecodePPM(Int32 num, bool &keepDecompressing); 226 227 HRESULT ReadTables(bool &keepDecompressing); 228 HRESULT ReadEndOfBlock(bool &keepDecompressing); 229 HRESULT DecodeLZ(bool &keepDecompressing); 230 HRESULT CodeReal(ICompressProgressInfo *progress); 231 InputEofError()232 bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); } InputEofError_Fast()233 bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); } 234 235 public: 236 CDecoder(); 237 ~CDecoder(); 238 239 MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) 240 241 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, 242 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 243 244 STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); 245 CopyBlock(UInt32 distance,UInt32 len)246 void CopyBlock(UInt32 distance, UInt32 len) 247 { 248 _lzSize += len; 249 UInt32 pos = (_winPos - distance - 1) & kWindowMask; 250 Byte *window = _window; 251 UInt32 winPos = _winPos; 252 if (kWindowSize - winPos > len && kWindowSize - pos > len) 253 { 254 const Byte *src = window + pos; 255 Byte *dest = window + winPos; 256 _winPos += len; 257 do 258 *dest++ = *src++; 259 while (--len != 0); 260 return; 261 } 262 do 263 { 264 window[winPos] = window[pos]; 265 winPos = (winPos + 1) & kWindowMask; 266 pos = (pos + 1) & kWindowMask; 267 } 268 while (--len != 0); 269 _winPos = winPos; 270 } 271 PutByte(Byte b)272 void PutByte(Byte b) 273 { 274 _window[_winPos] = b; 275 _winPos = (_winPos + 1) & kWindowMask; 276 _lzSize++; 277 } 278 279 280 }; 281 282 }} 283 284 #endif 285