Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BZip2Decoder.h « Compress « 7zip « CPP - github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2c28c5a1f8b710761b2282e8e4e7e722cfe416a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// Compress/BZip2Decoder.h

#ifndef __COMPRESS_BZIP2_DECODER_H
#define __COMPRESS_BZIP2_DECODER_H

#include "../../Common/MyCom.h"

#ifndef _7ZIP_ST
#include "../../Windows/Synchronization.h"
#include "../../Windows/Thread.h"
#endif

#include "../ICoder.h"

#include "../Common/InBuffer.h"
#include "../Common/OutBuffer.h"

#include "BitmDecoder.h"
#include "BZip2Const.h"
#include "BZip2Crc.h"
#include "HuffmanDecoder.h"

namespace NCompress {
namespace NBZip2 {

bool IsEndSig(const Byte *p) throw();
bool IsBlockSig(const Byte *p) throw();

typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder;

class CDecoder;

struct CState
{
  UInt32 *Counters;

  #ifndef _7ZIP_ST

  CDecoder *Decoder;
  NWindows::CThread Thread;
  bool m_OptimizeNumTables;

  NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;
  NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;

  // it's not member of this thread. We just need one event per thread
  NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;

  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.

  HRESULT Create();
  void FinishStream();
  void ThreadFunc();

  #endif

  CState(): Counters(0) {}
  ~CState() { Free(); }
  bool Alloc();
  void Free();
};

struct CBlockProps
{
  UInt32 blockSize;
  UInt32 origPtr;
  bool randMode;
  
  CBlockProps(): blockSize(0), origPtr(0), randMode(false) {}
};

struct CBase
{
  CMyComPtr<ISequentialInStream> InStreamRef;
  NBitm::CDecoder<CInBuffer> BitDecoder;

private:
  Byte m_Selectors[kNumSelectorsMax];
  CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];

public:
  UInt64 NumBlocks;

  CBase(): NumBlocks(0) {}
  UInt32 ReadBits(unsigned numBits);
  unsigned ReadBit();
  void InitNumBlocks() { NumBlocks = 0; }

  /*
    ReadBlock() props->randMode:
      in: need read randMode bit,
      out: randMode status
  */
  HRESULT ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props);
};

class CDecoder :
  public ICompressCoder,
  #ifndef _7ZIP_ST
  public ICompressSetCoderMt,
  #endif
  public CMyUnknownImp
{
public:
  COutBuffer m_OutStream;
  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.

  CBase Base;

  UInt64 _inStart;

private:

  bool _needInStreamInit;

  Byte ReadByte();

  HRESULT DecodeFile(ICompressProgressInfo *progress);
  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
  
  class CDecoderFlusher
  {
    CDecoder *_decoder;
  public:
    bool NeedFlush;
    CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
    ~CDecoderFlusher()
    {
      if (NeedFlush)
        _decoder->Flush();
    }
  };

public:
  CBZip2CombinedCrc CombinedCrc;
  ICompressProgressInfo *Progress;

  #ifndef _7ZIP_ST
  CState *m_States;
  UInt32 m_NumThreadsPrev;

  NWindows::NSynchronization::CManualResetEvent CanProcessEvent;
  NWindows::NSynchronization::CCriticalSection CS;
  UInt32 NumThreads;
  bool MtMode;
  UInt32 NextBlockIndex;
  bool CloseThreads;
  bool StreamWasFinished1;
  bool StreamWasFinished2;
  NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;

  HRESULT Result1;
  HRESULT Result2;

  UInt32 BlockSizeMax;

  bool IsBz;
  bool BzWasFinished; // bzip stream was finished with end signature
  bool CrcError; // it can CRC error of block or CRC error of whole stream.

  ~CDecoder();
  HRESULT Create();
  void Free();

  #else
  CState m_States[1];
  #endif

  CDecoder();

  HRESULT SetRatioProgress(UInt64 packSize);
  HRESULT ReadSignature(UInt32 &crc);

  HRESULT Flush() { return m_OutStream.Flush(); }

  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
  #ifndef _7ZIP_ST
  MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
  #endif

  MY_QUERYINTERFACE_END
  MY_ADDREF_RELEASE

  
  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
  STDMETHOD(ReleaseInStream)();

  HRESULT CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress);

  UInt64 GetStreamSize() const { return Base.BitDecoder.GetStreamSize(); }
  UInt64 GetInputProcessedSize() const { return Base.BitDecoder.GetProcessedSize(); }

  void InitNumBlocks() { Base.InitNumBlocks(); }
  UInt64 GetNumBlocks() const { return Base.NumBlocks; }
  
  #ifndef _7ZIP_ST
  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
  #endif
};


class CNsisDecoder :
  public ISequentialInStream,
  public ICompressSetInStream,
  public ICompressSetOutStreamSize,
  public CMyUnknownImp
{
  CBase Base;

  CState m_State;
  
  int _nsisState;
  UInt32 _tPos;
  unsigned _prevByte;
  unsigned _repRem;
  unsigned _numReps;
  UInt32 _blockSize;

public:

  MY_QUERYINTERFACE_BEGIN2(ISequentialInStream)
  MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
  MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
  MY_QUERYINTERFACE_END
  MY_ADDREF_RELEASE

  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
  STDMETHOD(ReleaseInStream)();
  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
};

}}

#endif