1 // Compress/BZip2Decoder.h 2 3 #ifndef __COMPRESS_BZIP2_DECODER_H 4 #define __COMPRESS_BZIP2_DECODER_H 5 6 #include "../../Common/MyCom.h" 7 8 // #define NO_READ_FROM_CODER 9 // #define _7ZIP_ST 10 11 #ifndef _7ZIP_ST 12 #include "../../Windows/Synchronization.h" 13 #include "../../Windows/Thread.h" 14 #endif 15 16 #include "../ICoder.h" 17 18 #include "BZip2Const.h" 19 #include "BZip2Crc.h" 20 #include "HuffmanDecoder.h" 21 #include "Mtf8.h" 22 23 namespace NCompress { 24 namespace NBZip2 { 25 26 bool IsEndSig(const Byte *p) throw(); 27 bool IsBlockSig(const Byte *p) throw(); 28 29 const unsigned kNumTableBits = 9; 30 const unsigned kNumBitsMax = kMaxHuffmanLen; 31 32 typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder; 33 34 35 struct CBlockProps 36 { 37 UInt32 blockSize; 38 UInt32 origPtr; 39 unsigned randMode; 40 CBlockPropsCBlockProps41 CBlockProps(): blockSize(0), origPtr(0), randMode(0) {} 42 }; 43 44 45 struct CBitDecoder 46 { 47 unsigned _numBits; 48 UInt32 _value; 49 const Byte *_buf; 50 const Byte *_lim; 51 InitBitDecoderCBitDecoder52 void InitBitDecoder() 53 { 54 _numBits = 0; 55 _value = 0; 56 } 57 AlignToByteCBitDecoder58 void AlignToByte() 59 { 60 unsigned bits = _numBits & 7; 61 _numBits -= bits; 62 _value <<= bits; 63 } 64 65 /* 66 bool AreRemainByteBitsEmpty() const 67 { 68 unsigned bits = _numBits & 7; 69 if (bits != 0) 70 return (_value >> (32 - bits)) == 0; 71 return true; 72 } 73 */ 74 75 SRes ReadByte(int &b); 76 CBitDecoderCBitDecoder77 CBitDecoder(): 78 _buf(NULL), 79 _lim(NULL) 80 { 81 InitBitDecoder(); 82 } 83 }; 84 85 86 // 19.03: we allow additional 8 selectors to support files created by lbzip2. 87 const UInt32 kNumSelectorsMax_Decoder = kNumSelectorsMax + 8; 88 89 struct CBase: public CBitDecoder 90 { 91 unsigned numInUse; 92 UInt32 groupIndex; 93 UInt32 groupSize; 94 unsigned runPower; 95 UInt32 runCounter; 96 UInt32 blockSize; 97 98 UInt32 *Counters; 99 UInt32 blockSizeMax; 100 101 unsigned state; 102 unsigned state2; 103 unsigned state3; 104 unsigned state4; 105 unsigned state5; 106 unsigned numTables; 107 UInt32 numSelectors; 108 109 CBlockProps Props; 110 111 private: 112 CMtf8Decoder mtf; 113 Byte selectors[kNumSelectorsMax_Decoder]; 114 CHuffmanDecoder huffs[kNumTablesMax]; 115 116 Byte lens[kMaxAlphaSize]; 117 118 Byte temp[10]; 119 120 public: 121 UInt32 crc; 122 CBZip2CombinedCrc CombinedCrc; 123 124 bool IsBz; 125 bool StreamCrcError; 126 bool MinorError; 127 bool NeedMoreInput; 128 129 bool DecodeAllStreams; 130 131 UInt64 NumStreams; 132 UInt64 NumBlocks; 133 UInt64 FinishedPackSize; 134 135 ISequentialInStream *InStream; 136 137 #ifndef NO_READ_FROM_CODER 138 CMyComPtr<ISequentialInStream> InStreamRef; 139 #endif 140 CBaseCBase141 CBase(): 142 StreamCrcError(false), 143 MinorError(false), 144 NeedMoreInput(false), 145 146 DecodeAllStreams(false), 147 148 NumStreams(0), 149 NumBlocks(0), 150 FinishedPackSize(0) 151 {} 152 InitNumStreams2CBase153 void InitNumStreams2() 154 { 155 StreamCrcError = false; 156 MinorError = false; 157 NeedMoreInput = 0; 158 NumStreams = 0; 159 NumBlocks = 0; 160 FinishedPackSize = 0; 161 } 162 163 SRes ReadStreamSignature2(); 164 SRes ReadBlockSignature2(); 165 166 /* ReadBlock2() : Props->randMode: 167 in: need read randMode bit 168 out: randMode status */ 169 SRes ReadBlock2(); 170 }; 171 172 173 class CSpecState 174 { 175 UInt32 _tPos; 176 unsigned _prevByte; 177 int _reps; 178 179 public: 180 CBZip2Crc _crc; 181 UInt32 _blockSize; 182 UInt32 *_tt; 183 184 int _randToGo; 185 unsigned _randIndex; 186 187 void Init(UInt32 origPtr, unsigned randMode) throw(); 188 Finished()189 bool Finished() const { return _reps <= 0 && _blockSize == 0; } 190 191 Byte *Decode(Byte *data, size_t size) throw(); 192 }; 193 194 195 196 197 class CDecoder : 198 public ICompressCoder, 199 public ICompressSetFinishMode, 200 public ICompressGetInStreamProcessedSize, 201 public ICompressReadUnusedFromInBuf, 202 203 #ifndef NO_READ_FROM_CODER 204 public ICompressSetInStream, 205 public ICompressSetOutStreamSize, 206 public ISequentialInStream, 207 #endif 208 209 #ifndef _7ZIP_ST 210 public ICompressSetCoderMt, 211 #endif 212 213 public CMyUnknownImp 214 { 215 Byte *_outBuf; 216 size_t _outPos; 217 UInt64 _outWritten; 218 ISequentialOutStream *_outStream; 219 HRESULT _writeRes; 220 221 protected: 222 HRESULT ErrorResult; // for ISequentialInStream::Read mode only 223 224 public: 225 226 UInt32 _calcedBlockCrc; 227 bool _blockFinished; 228 bool BlockCrcError; 229 230 bool FinishMode; 231 bool _outSizeDefined; 232 UInt64 _outSize; 233 UInt64 _outPosTotal; 234 235 CSpecState _spec; 236 UInt32 *_counters; 237 238 #ifndef _7ZIP_ST 239 240 struct CBlock 241 { 242 bool StopScout; 243 244 bool WasFinished; 245 bool Crc_Defined; 246 // bool NextCrc_Defined; 247 248 UInt32 Crc; 249 UInt32 NextCrc; 250 HRESULT Res; 251 UInt64 PackPos; 252 253 CBlockProps Props; 254 }; 255 256 CBlock _block; 257 258 bool NeedWaitScout; 259 bool MtMode; 260 261 NWindows::CThread Thread; 262 NWindows::NSynchronization::CAutoResetEvent DecoderEvent; 263 NWindows::NSynchronization::CAutoResetEvent ScoutEvent; 264 // HRESULT ScoutRes; 265 266 Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. 267 268 269 void RunScout(); 270 WaitScout()271 void WaitScout() 272 { 273 if (NeedWaitScout) 274 { 275 DecoderEvent.Lock(); 276 NeedWaitScout = false; 277 } 278 } 279 280 class CWaitScout_Releaser 281 { 282 CDecoder *_decoder; 283 public: CWaitScout_Releaser(CDecoder * decoder)284 CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {} ~CWaitScout_Releaser()285 ~CWaitScout_Releaser() { _decoder->WaitScout(); } 286 }; 287 288 HRESULT CreateThread(); 289 290 #endif 291 292 Byte *_inBuf; 293 UInt64 _inProcessed; 294 bool _inputFinished; 295 HRESULT _inputRes; 296 297 CBase Base; 298 GetCrcError()299 bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; } 300 301 void InitOutSize(const UInt64 *outSize); 302 303 bool CreateInputBufer(); 304 InitInputBuffer()305 void InitInputBuffer() 306 { 307 // We use InitInputBuffer() before stream init. 308 // So don't read from stream here 309 _inProcessed = 0; 310 Base._buf = _inBuf; 311 Base._lim = _inBuf; 312 Base.InitBitDecoder(); 313 } 314 GetInputProcessedSize()315 UInt64 GetInputProcessedSize() const 316 { 317 // for NSIS case : we need also look the number of bits in bitDecoder 318 return _inProcessed + (size_t)(Base._buf - _inBuf); 319 } 320 GetInStreamSize()321 UInt64 GetInStreamSize() const 322 { 323 return _inProcessed + (size_t)(Base._buf - _inBuf) - (Base._numBits >> 3); 324 } 325 GetOutProcessedSize()326 UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; } 327 328 HRESULT ReadInput(); 329 330 void StartNewStream(); 331 332 HRESULT ReadStreamSignature(); 333 HRESULT StartRead(); 334 335 HRESULT ReadBlockSignature(); 336 HRESULT ReadBlock(); 337 338 HRESULT Flush(); 339 HRESULT DecodeBlock(const CBlockProps &props); 340 HRESULT DecodeStreams(ICompressProgressInfo *progress); 341 342 MY_QUERYINTERFACE_BEGIN2(ICompressCoder) 343 MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) 344 MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) 345 MY_QUERYINTERFACE_ENTRY(ICompressReadUnusedFromInBuf) 346 347 #ifndef NO_READ_FROM_CODER 348 MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) 349 MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) 350 MY_QUERYINTERFACE_ENTRY(ISequentialInStream) 351 #endif 352 353 #ifndef _7ZIP_ST 354 MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) 355 #endif 356 357 MY_QUERYINTERFACE_END 358 MY_ADDREF_RELEASE 359 360 361 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, 362 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 363 364 STDMETHOD(SetFinishMode)(UInt32 finishMode); 365 STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); 366 STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize); 367 GetNumStreams()368 UInt64 GetNumStreams() const { return Base.NumStreams; } GetNumBlocks()369 UInt64 GetNumBlocks() const { return Base.NumBlocks; } 370 371 #ifndef NO_READ_FROM_CODER 372 373 STDMETHOD(SetInStream)(ISequentialInStream *inStream); 374 STDMETHOD(ReleaseInStream)(); 375 STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); 376 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 377 378 #endif 379 380 #ifndef _7ZIP_ST 381 STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); 382 #endif 383 384 CDecoder(); 385 ~CDecoder(); 386 }; 387 388 389 390 #ifndef NO_READ_FROM_CODER 391 392 class CNsisDecoder : public CDecoder 393 { 394 public: 395 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 396 }; 397 398 #endif 399 400 }} 401 402 #endif 403