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 }; 77 78 79 struct CBase: public CBitDecoder 80 { 81 unsigned numInUse; 82 UInt32 groupIndex; 83 UInt32 groupSize; 84 unsigned runPower; 85 UInt32 runCounter; 86 UInt32 blockSize; 87 88 UInt32 *Counters; 89 UInt32 blockSizeMax; 90 91 unsigned state; 92 unsigned state2; 93 unsigned state3; 94 unsigned state4; 95 unsigned state5; 96 unsigned numTables; 97 UInt32 numSelectors; 98 99 CBlockProps Props; 100 101 private: 102 CMtf8Decoder mtf; 103 Byte selectors[kNumSelectorsMax]; 104 CHuffmanDecoder huffs[kNumTablesMax]; 105 106 Byte lens[kMaxAlphaSize]; 107 108 Byte temp[10]; 109 110 public: 111 UInt32 crc; 112 CBZip2CombinedCrc CombinedCrc; 113 114 bool IsBz; 115 bool StreamCrcError; 116 bool MinorError; 117 bool NeedMoreInput; 118 119 bool DecodeAllStreams; 120 121 UInt64 NumStreams; 122 UInt64 NumBlocks; 123 UInt64 FinishedPackSize; 124 125 ISequentialInStream *InStream; 126 127 #ifndef NO_READ_FROM_CODER 128 CMyComPtr<ISequentialInStream> InStreamRef; 129 #endif 130 CBaseCBase131 CBase(): 132 StreamCrcError(false), 133 MinorError(false), 134 NeedMoreInput(false), 135 136 DecodeAllStreams(false), 137 138 NumStreams(0), 139 NumBlocks(0), 140 FinishedPackSize(0) 141 {} 142 InitNumStreams2CBase143 void InitNumStreams2() 144 { 145 StreamCrcError = false; 146 MinorError = false; 147 NeedMoreInput = 0; 148 NumStreams = 0; 149 NumBlocks = 0; 150 FinishedPackSize = 0; 151 } 152 153 SRes ReadStreamSignature2(); 154 SRes ReadBlockSignature2(); 155 156 /* ReadBlock2() : Props->randMode: 157 in: need read randMode bit 158 out: randMode status */ 159 SRes ReadBlock2(); 160 }; 161 162 163 class CSpecState 164 { 165 UInt32 _tPos; 166 unsigned _prevByte; 167 int _reps; 168 169 public: 170 CBZip2Crc _crc; 171 UInt32 _blockSize; 172 UInt32 *_tt; 173 174 int _randToGo; 175 unsigned _randIndex; 176 177 void Init(UInt32 origPtr, unsigned randMode) throw(); 178 Finished()179 bool Finished() const { return _reps <= 0 && _blockSize == 0; } 180 181 Byte *Decode(Byte *data, size_t size) throw(); 182 }; 183 184 185 186 187 class CDecoder : 188 public ICompressCoder, 189 public ICompressSetFinishMode, 190 public ICompressGetInStreamProcessedSize, 191 192 #ifndef NO_READ_FROM_CODER 193 public ICompressSetInStream, 194 public ICompressSetOutStreamSize, 195 public ISequentialInStream, 196 #endif 197 198 #ifndef _7ZIP_ST 199 public ICompressSetCoderMt, 200 #endif 201 202 public CMyUnknownImp 203 { 204 Byte *_outBuf; 205 size_t _outPos; 206 UInt64 _outWritten; 207 ISequentialOutStream *_outStream; 208 HRESULT _writeRes; 209 210 protected: 211 HRESULT ErrorResult; // for ISequentialInStream::Read mode only 212 213 public: 214 215 UInt32 _calcedBlockCrc; 216 bool _blockFinished; 217 bool BlockCrcError; 218 219 bool FinishMode; 220 bool _outSizeDefined; 221 UInt64 _outSize; 222 UInt64 _outPosTotal; 223 224 CSpecState _spec; 225 UInt32 *_counters; 226 227 #ifndef _7ZIP_ST 228 229 struct CBlock 230 { 231 bool StopScout; 232 233 bool WasFinished; 234 bool Crc_Defined; 235 // bool NextCrc_Defined; 236 237 UInt32 Crc; 238 UInt32 NextCrc; 239 HRESULT Res; 240 UInt64 PackPos; 241 242 CBlockProps Props; 243 }; 244 245 CBlock _block; 246 247 bool NeedWaitScout; 248 bool MtMode; 249 250 NWindows::CThread Thread; 251 NWindows::NSynchronization::CAutoResetEvent DecoderEvent; 252 NWindows::NSynchronization::CAutoResetEvent ScoutEvent; 253 // HRESULT ScoutRes; 254 255 Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. 256 257 258 void RunScout(); 259 WaitScout()260 void WaitScout() 261 { 262 if (NeedWaitScout) 263 { 264 DecoderEvent.Lock(); 265 NeedWaitScout = false; 266 } 267 } 268 269 class CWaitScout_Releaser 270 { 271 CDecoder *_decoder; 272 public: CWaitScout_Releaser(CDecoder * decoder)273 CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {} ~CWaitScout_Releaser()274 ~CWaitScout_Releaser() { _decoder->WaitScout(); } 275 }; 276 277 HRESULT CreateThread(); 278 279 #endif 280 281 Byte *_inBuf; 282 UInt64 _inProcessed; 283 bool _inputFinished; 284 HRESULT _inputRes; 285 286 CBase Base; 287 GetCrcError()288 bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; } 289 290 void InitOutSize(const UInt64 *outSize); 291 292 bool CreateInputBufer(); 293 InitInputBuffer()294 void InitInputBuffer() 295 { 296 _inProcessed = 0; 297 Base._buf = _inBuf; 298 Base._lim = _inBuf; 299 Base.InitBitDecoder(); 300 } 301 GetInputProcessedSize()302 UInt64 GetInputProcessedSize() const 303 { 304 // for NSIS case : we need also look the number of bits in bitDecoder 305 return _inProcessed + (Base._buf - _inBuf); 306 } 307 GetOutProcessedSize()308 UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; } 309 310 HRESULT ReadInput(); 311 312 void StartNewStream(); 313 314 HRESULT ReadStreamSignature(); 315 HRESULT StartRead(); 316 317 HRESULT ReadBlockSignature(); 318 HRESULT ReadBlock(); 319 320 HRESULT Flush(); 321 HRESULT DecodeBlock(const CBlockProps &props); 322 HRESULT DecodeStreams(ICompressProgressInfo *progress); 323 324 MY_QUERYINTERFACE_BEGIN2(ICompressCoder) 325 MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) 326 MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) 327 328 #ifndef NO_READ_FROM_CODER 329 MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) 330 MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) 331 MY_QUERYINTERFACE_ENTRY(ISequentialInStream) 332 #endif 333 334 #ifndef _7ZIP_ST 335 MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) 336 #endif 337 338 MY_QUERYINTERFACE_END 339 MY_ADDREF_RELEASE 340 341 342 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, 343 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 344 345 STDMETHOD(SetFinishMode)(UInt32 finishMode); 346 STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); 347 GetNumStreams()348 UInt64 GetNumStreams() const { return Base.NumStreams; } GetNumBlocks()349 UInt64 GetNumBlocks() const { return Base.NumBlocks; } 350 351 #ifndef NO_READ_FROM_CODER 352 353 STDMETHOD(SetInStream)(ISequentialInStream *inStream); 354 STDMETHOD(ReleaseInStream)(); 355 STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); 356 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 357 358 #endif 359 360 #ifndef _7ZIP_ST 361 STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); 362 #endif 363 364 CDecoder(); 365 ~CDecoder(); 366 }; 367 368 369 370 #ifndef NO_READ_FROM_CODER 371 372 class CNsisDecoder : public CDecoder 373 { 374 public: 375 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 376 }; 377 378 #endif 379 380 }} 381 382 #endif 383