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