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 ReadBits_upto8(unsigned numBits)99 UInt32 ReadBits_upto8(unsigned numBits) 100 { 101 if (_bitPos < numBits) 102 { 103 _bitPos += 8; 104 _value = (_value << 8) | Stream.ReadByte(); 105 } 106 _bitPos -= numBits; 107 UInt32 res = _value >> _bitPos; 108 _value = _value & ((1 << _bitPos) - 1); 109 return res; 110 } 111 ReadByteFromAligned()112 Byte ReadByteFromAligned() 113 { 114 if (_bitPos == 0) 115 return Stream.ReadByte(); 116 unsigned bitsPos = _bitPos - 8; 117 Byte b = (Byte)(_value >> bitsPos); 118 _value = _value & ((1 << bitsPos) - 1); 119 _bitPos = bitsPos; 120 return b; 121 } 122 }; 123 124 125 struct CByteIn 126 { 127 IByteIn IByteIn_obj; 128 CBitDecoder BitDecoder; 129 }; 130 131 132 struct CFilter: public NVm::CProgram 133 { 134 CRecordVector<Byte> GlobalData; 135 UInt32 BlockStart; 136 UInt32 BlockSize; 137 UInt32 ExecCount; 138 CFilterCFilter139 CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} 140 }; 141 142 struct CTempFilter: public NVm::CProgramInitState 143 { 144 UInt32 BlockStart; 145 UInt32 BlockSize; 146 bool NextWindow; 147 148 UInt32 FilterIndex; 149 CTempFilterCTempFilter150 CTempFilter() 151 { 152 // all filters must contain at least FixedGlobal block 153 AllocateEmptyFixedGlobal(); 154 } 155 }; 156 157 const unsigned kNumHuffmanBits = 15; 158 159 class CDecoder: 160 public ICompressCoder, 161 public ICompressSetDecoderProperties2, 162 public CMyUnknownImp 163 { 164 CByteIn m_InBitStream; 165 Byte *_window; 166 UInt32 _winPos; 167 UInt32 _wrPtr; 168 UInt64 _lzSize; 169 UInt64 _unpackSize; 170 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written 171 ISequentialOutStream *_outStream; 172 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; 173 UInt32 kDistStart[kDistTableSize]; 174 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; 175 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; 176 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; 177 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder; 178 179 UInt32 _reps[kNumReps]; 180 UInt32 _lastLength; 181 182 Byte m_LastLevels[kTablesSizesSum]; 183 184 Byte *_vmData; 185 Byte *_vmCode; 186 NVm::CVm _vm; 187 CRecordVector<CFilter *> _filters; 188 CRecordVector<CTempFilter *> _tempFilters; 189 unsigned _numEmptyTempFilters; 190 UInt32 _lastFilter; 191 192 bool _isSolid; 193 bool _solidAllowed; 194 // bool _errorMode; 195 196 bool _lzMode; 197 bool _unsupportedFilter; 198 199 UInt32 PrevAlignBits; 200 UInt32 PrevAlignCount; 201 202 bool TablesRead; 203 bool TablesOK; 204 205 CPpmd7 _ppmd; 206 int PpmEscChar; 207 bool PpmError; 208 209 HRESULT WriteDataToStream(const Byte *data, UInt32 size); 210 HRESULT WriteData(const Byte *data, UInt32 size); 211 HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); 212 void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef); 213 HRESULT WriteBuf(); 214 215 void InitFilters(); 216 bool AddVmCode(UInt32 firstByte, UInt32 codeSize); 217 bool ReadVmCodeLZ(); 218 bool ReadVmCodePPM(); 219 220 UInt32 ReadBits(unsigned numBits); 221 222 HRESULT InitPPM(); 223 // int DecodePpmSymbol(); 224 HRESULT DecodePPM(Int32 num, bool &keepDecompressing); 225 226 HRESULT ReadTables(bool &keepDecompressing); 227 HRESULT ReadEndOfBlock(bool &keepDecompressing); 228 HRESULT DecodeLZ(bool &keepDecompressing); 229 HRESULT CodeReal(ICompressProgressInfo *progress); 230 InputEofError()231 bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); } InputEofError_Fast()232 bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); } 233 234 public: 235 CDecoder(); 236 ~CDecoder(); 237 238 MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) 239 240 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, 241 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 242 243 STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); 244 CopyBlock(UInt32 dist,UInt32 len)245 void CopyBlock(UInt32 dist, UInt32 len) 246 { 247 _lzSize += len; 248 UInt32 pos = (_winPos - dist - 1) & kWindowMask; 249 Byte *window = _window; 250 UInt32 winPos = _winPos; 251 if (kWindowSize - winPos > len && kWindowSize - pos > len) 252 { 253 const Byte *src = window + pos; 254 Byte *dest = window + winPos; 255 _winPos += len; 256 do 257 *dest++ = *src++; 258 while (--len != 0); 259 return; 260 } 261 do 262 { 263 window[winPos] = window[pos]; 264 winPos = (winPos + 1) & kWindowMask; 265 pos = (pos + 1) & kWindowMask; 266 } 267 while (--len != 0); 268 _winPos = winPos; 269 } 270 PutByte(Byte b)271 void PutByte(Byte b) 272 { 273 UInt32 wp = _winPos; 274 _window[wp] = b; 275 _winPos = (wp + 1) & kWindowMask; 276 _lzSize++; 277 } 278 }; 279 280 }} 281 282 #endif 283