~ubuntu-branches/ubuntu/precise/p7zip/precise-updates

« back to all changes in this revision

Viewing changes to CPP/7zip/Compress/Deflate/DeflateDecoder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mohammed Adnène Trojette
  • Date: 2009-02-14 20:12:27 UTC
  • mfrom: (1.1.11 upstream) (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090214201227-go63qxm9ozfdma60
Tags: 4.65~dfsg.1-1
* New upstream release.
* Remove wx2.8 Build-Depends added by mistakes (7zG is not yet
  intended to be built).
* Use dh_clean without -k.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// DeflateDecoder.cpp
2
 
 
3
 
#include "StdAfx.h"
4
 
 
5
 
#include "DeflateDecoder.h"
6
 
 
7
 
namespace NCompress {
8
 
namespace NDeflate {
9
 
namespace NDecoder {
10
 
 
11
 
static const int kLenIdFinished = -1;
12
 
static const int kLenIdNeedInit = -2;
13
 
 
14
 
CCoder::CCoder(bool deflate64Mode, bool deflateNSIS):  
15
 
    _deflate64Mode(deflate64Mode), 
16
 
    _deflateNSIS(deflateNSIS), 
17
 
    _keepHistory(false) {}
18
 
 
19
 
UInt32 CCoder::ReadBits(int numBits)
20
 
{
21
 
  return m_InBitStream.ReadBits(numBits);
22
 
}
23
 
 
24
 
bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)
25
 
{
26
 
  int i = 0;
27
 
  do
28
 
  {
29
 
    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
30
 
    if (number < kTableDirectLevels)
31
 
      values[i++] = (Byte)number;
32
 
    else if (number < kLevelTableSize)
33
 
    {
34
 
      if (number == kTableLevelRepNumber)
35
 
      {
36
 
        if (i == 0)
37
 
          return false;
38
 
        int num = ReadBits(2) + 3;
39
 
        for (; num > 0 && i < numSymbols; num--, i++)
40
 
          values[i] = values[i - 1];
41
 
      }
42
 
      else
43
 
      {
44
 
        int num;
45
 
        if (number == kTableLevel0Number)
46
 
          num = ReadBits(3) + 3;
47
 
        else
48
 
          num = ReadBits(7) + 11;
49
 
        for (;num > 0 && i < numSymbols; num--)
50
 
          values[i++] = 0;
51
 
      }
52
 
    }
53
 
    else
54
 
      return false;
55
 
  }
56
 
  while(i < numSymbols);
57
 
  return true;
58
 
}
59
 
 
60
 
#define RIF(x) { if (!(x)) return false; }
61
 
 
62
 
bool CCoder::ReadTables(void)
63
 
{
64
 
  m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
65
 
  UInt32 blockType = ReadBits(kBlockTypeFieldSize);
66
 
  if (blockType > NBlockType::kDynamicHuffman)
67
 
    return false;
68
 
 
69
 
  if (blockType == NBlockType::kStored)
70
 
  {
71
 
    m_StoredMode = true;
72
 
    UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
73
 
    int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
74
 
    ReadBits(numBitsForAlign);
75
 
    m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);
76
 
    if (_deflateNSIS)
77
 
      return true;
78
 
    return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));
79
 
  }
80
 
 
81
 
  m_StoredMode = false;
82
 
 
83
 
  CLevels levels;
84
 
  if (blockType == NBlockType::kFixedHuffman)
85
 
  {
86
 
    levels.SetFixedLevels();
87
 
    _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
88
 
  }
89
 
  else
90
 
  {
91
 
    int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
92
 
    _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
93
 
    int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
94
 
 
95
 
    if (!_deflate64Mode)
96
 
      if (_numDistLevels > kDistTableSize32)
97
 
        return false;
98
 
    
99
 
    Byte levelLevels[kLevelTableSize];
100
 
    for (int i = 0; i < kLevelTableSize; i++)
101
 
    {
102
 
      int position = kCodeLengthAlphabetOrder[i]; 
103
 
      if(i < numLevelCodes)
104
 
        levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
105
 
      else
106
 
        levelLevels[position] = 0;
107
 
    }
108
 
    
109
 
    RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
110
 
    
111
 
    Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
112
 
    if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))
113
 
      return false;
114
 
 
115
 
    levels.SubClear();
116
 
    memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
117
 
    memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
118
 
  }
119
 
  RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));
120
 
  return m_DistDecoder.SetCodeLengths(levels.distLevels);
121
 
}
122
 
 
123
 
HRESULT CCoder::CodeSpec(UInt32 curSize)
124
 
{
125
 
  if (_remainLen == kLenIdFinished)
126
 
    return S_OK;
127
 
  if (_remainLen == kLenIdNeedInit)
128
 
  {
129
 
    if (!_keepHistory)
130
 
      if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
131
 
        return E_OUTOFMEMORY;
132
 
    if (!m_InBitStream.Create(1 << 17))
133
 
      return E_OUTOFMEMORY;
134
 
    m_OutWindowStream.Init(_keepHistory);
135
 
    m_InBitStream.Init();
136
 
    m_FinalBlock = false;
137
 
    _remainLen = 0;
138
 
    _needReadTable = true;
139
 
  }
140
 
 
141
 
  if (curSize == 0)
142
 
    return S_OK;
143
 
 
144
 
  while(_remainLen > 0 && curSize > 0)
145
 
  {
146
 
    _remainLen--;
147
 
    Byte b = m_OutWindowStream.GetByte(_rep0);
148
 
    m_OutWindowStream.PutByte(b);
149
 
    curSize--;
150
 
  }
151
 
 
152
 
  while(curSize > 0)
153
 
  {
154
 
    if (_needReadTable)
155
 
    {
156
 
      if (m_FinalBlock)
157
 
      {
158
 
        _remainLen = kLenIdFinished;
159
 
        break;
160
 
      }
161
 
      if (!ReadTables())
162
 
        return S_FALSE;
163
 
      _needReadTable = false;
164
 
    }
165
 
 
166
 
    if(m_StoredMode)
167
 
    {
168
 
      for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
169
 
        m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
170
 
      _needReadTable = (m_StoredBlockSize == 0);
171
 
      continue;
172
 
    }
173
 
    while(curSize > 0)
174
 
    {
175
 
      if (m_InBitStream.NumExtraBytes > 4)
176
 
        return S_FALSE;
177
 
 
178
 
      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
179
 
      if (number < 0x100)
180
 
      {
181
 
        m_OutWindowStream.PutByte((Byte)number);
182
 
        curSize--;
183
 
        continue;
184
 
      }
185
 
      else if (number == kSymbolEndOfBlock)
186
 
      {
187
 
        _needReadTable = true;
188
 
        break;
189
 
      }
190
 
      else if (number < kMainTableSize)
191
 
      {
192
 
        number -= kSymbolMatch;
193
 
        UInt32 len;
194
 
        {
195
 
          int numBits;
196
 
          if (_deflate64Mode)
197
 
          {
198
 
            len = kLenStart64[number];
199
 
            numBits = kLenDirectBits64[number];
200
 
          }
201
 
          else
202
 
          {
203
 
            len = kLenStart32[number];
204
 
            numBits = kLenDirectBits32[number];
205
 
          }
206
 
          len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
207
 
        }
208
 
        UInt32 locLen = len;
209
 
        if (locLen > curSize)
210
 
          locLen = (UInt32)curSize;
211
 
        number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
212
 
        if (number >= _numDistLevels)
213
 
          return S_FALSE;
214
 
        UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
215
 
        if (!m_OutWindowStream.CopyBlock(distance, locLen))
216
 
          return S_FALSE;
217
 
        curSize -= locLen;
218
 
        len -= locLen;
219
 
        if (len != 0)
220
 
        {
221
 
          _remainLen = (Int32)len;
222
 
          _rep0 = distance;
223
 
          break;
224
 
        }
225
 
      }
226
 
      else
227
 
        return S_FALSE;
228
 
    }
229
 
  }
230
 
  return S_OK;
231
 
}
232
 
 
233
 
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
234
 
    ISequentialOutStream *outStream, 
235
 
    const UInt64 *, const UInt64 *outSize,
236
 
    ICompressProgressInfo *progress)
237
 
{
238
 
  SetInStream(inStream);
239
 
  m_OutWindowStream.SetStream(outStream);
240
 
  SetOutStreamSize(outSize);
241
 
  CCoderReleaser flusher(this);
242
 
 
243
 
  const UInt64 start = m_OutWindowStream.GetProcessedSize();
244
 
  for (;;)
245
 
  {
246
 
    UInt32 curSize = 1 << 18;
247
 
    if (outSize != 0)
248
 
    {
249
 
      const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);
250
 
      if (curSize > rem)
251
 
        curSize = (UInt32)rem;
252
 
    }
253
 
    if (curSize == 0)
254
 
      break;
255
 
    RINOK(CodeSpec(curSize));
256
 
    if (_remainLen == kLenIdFinished)
257
 
      break;
258
 
    if (progress != NULL)
259
 
    {
260
 
      const UInt64 inSize = m_InBitStream.GetProcessedSize();
261
 
      const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
262
 
      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
263
 
    }
264
 
  } 
265
 
  flusher.NeedFlush = false;
266
 
  return Flush();
267
 
}
268
 
 
269
 
 
270
 
#ifdef _NO_EXCEPTIONS
271
 
 
272
 
#define DEFLATE_TRY_BEGIN
273
 
#define DEFLATE_TRY_END
274
 
 
275
 
#else
276
 
 
277
 
#define DEFLATE_TRY_BEGIN try { 
278
 
#define DEFLATE_TRY_END } \
279
 
  catch(const CInBufferException &e)  { return e.ErrorCode; } \
280
 
  catch(const CLZOutWindowException &e)  { return e.ErrorCode; } \
281
 
  catch(...) { return S_FALSE; }
282
 
 
283
 
#endif
284
 
 
285
 
HRESULT CCoder::Code(ISequentialInStream *inStream,
286
 
    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
287
 
    ICompressProgressInfo *progress)
288
 
{
289
 
  DEFLATE_TRY_BEGIN
290
 
  return CodeReal(inStream, outStream, inSize, outSize, progress);
291
 
  DEFLATE_TRY_END
292
 
}
293
 
 
294
 
STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
295
 
{
296
 
  if (value == NULL)
297
 
    return E_INVALIDARG;
298
 
  *value = m_InBitStream.GetProcessedSize();
299
 
  return S_OK;
300
 
}
301
 
 
302
 
STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
303
 
{
304
 
  m_InBitStream.SetStream(inStream);
305
 
  return S_OK;
306
 
}
307
 
 
308
 
STDMETHODIMP CCoder::ReleaseInStream()
309
 
{
310
 
  m_InBitStream.ReleaseStream();
311
 
  return S_OK;
312
 
}
313
 
 
314
 
STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)
315
 
{
316
 
  _remainLen = kLenIdNeedInit;
317
 
  m_OutWindowStream.Init(_keepHistory);
318
 
  return S_OK;
319
 
}
320
 
 
321
 
#ifndef NO_READ_FROM_CODER
322
 
 
323
 
STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
324
 
{
325
 
  DEFLATE_TRY_BEGIN
326
 
  if (processedSize)
327
 
    *processedSize = 0;
328
 
  const UInt64 startPos = m_OutWindowStream.GetProcessedSize();
329
 
  m_OutWindowStream.SetMemStream((Byte *)data);
330
 
  RINOK(CodeSpec(size));
331
 
  if (processedSize)
332
 
    *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);
333
 
  return Flush();
334
 
  DEFLATE_TRY_END
335
 
}
336
 
 
337
 
#endif
338
 
 
339
 
}}}