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

« back to all changes in this revision

Viewing changes to CPP/7zip/Compress/ZDecoder.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
// ZDecoder.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
extern "C"
 
6
{
 
7
#include "../../../C/Alloc.h"
 
8
}
 
9
 
 
10
#include "../Common/InBuffer.h"
 
11
#include "../Common/OutBuffer.h"
 
12
 
 
13
#include "ZDecoder.h"
 
14
 
 
15
namespace NCompress {
 
16
namespace NZ {
 
17
 
 
18
static const UInt32 kBufferSize = (1 << 20);
 
19
static const Byte kNumBitsMask = 0x1F;
 
20
static const Byte kBlockModeMask = 0x80;
 
21
static const int kNumMinBits = 9;
 
22
static const int kNumMaxBits = 16;
 
23
 
 
24
void CDecoder::Free()
 
25
{
 
26
  MyFree(_parents); _parents = 0;
 
27
  MyFree(_suffixes); _suffixes = 0;
 
28
  MyFree(_stack); _stack = 0;
 
29
}
 
30
 
 
31
CDecoder::~CDecoder() { Free(); }
 
32
 
 
33
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
 
34
    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
 
35
{
 
36
  CInBuffer inBuffer;
 
37
  COutBuffer outBuffer;
 
38
 
 
39
  if (!inBuffer.Create(kBufferSize))
 
40
    return E_OUTOFMEMORY;
 
41
  inBuffer.SetStream(inStream);
 
42
  inBuffer.Init();
 
43
 
 
44
  if (!outBuffer.Create(kBufferSize))
 
45
    return E_OUTOFMEMORY;
 
46
  outBuffer.SetStream(outStream);
 
47
  outBuffer.Init();
 
48
 
 
49
  int maxbits = _properties & kNumBitsMask;
 
50
  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
 
51
    return S_FALSE;
 
52
  UInt32 numItems = 1 << maxbits;
 
53
  bool blockMode = ((_properties & kBlockModeMask) != 0);
 
54
 
 
55
  if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)
 
56
  {
 
57
    Free();
 
58
    _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (_parents == 0) return E_OUTOFMEMORY;
 
59
    _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_suffixes == 0) return E_OUTOFMEMORY;
 
60
    _stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_stack == 0) return E_OUTOFMEMORY;
 
61
    _numMaxBits = maxbits;
 
62
  }
 
63
 
 
64
  UInt64 prevPos = 0;
 
65
  int numBits = kNumMinBits;
 
66
  UInt32 head = blockMode ? 257 : 256;
 
67
 
 
68
  bool needPrev = false;
 
69
 
 
70
  unsigned bitPos = 0;
 
71
  unsigned numBufBits = 0;
 
72
 
 
73
  Byte buf[kNumMaxBits + 4];
 
74
 
 
75
  _parents[256] = 0; // virus protection
 
76
  _suffixes[256] = 0;
 
77
 
 
78
  for (;;)
 
79
  {
 
80
    if (numBufBits == bitPos)
 
81
    {
 
82
      numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8;
 
83
      bitPos = 0;
 
84
      UInt64 nowPos = outBuffer.GetProcessedSize();
 
85
      if (progress != NULL && nowPos - prevPos >= (1 << 18))
 
86
      {
 
87
        prevPos = nowPos;
 
88
        UInt64 packSize = inBuffer.GetProcessedSize();
 
89
        RINOK(progress->SetRatioInfo(&packSize, &nowPos));
 
90
      }
 
91
    }
 
92
    unsigned bytePos = bitPos >> 3;
 
93
    UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);
 
94
    symbol >>= (bitPos & 7);
 
95
    symbol &= (1 << numBits) - 1;
 
96
    bitPos += numBits;
 
97
    if (bitPos > numBufBits)
 
98
      break;
 
99
    if (symbol >= head)
 
100
      return S_FALSE;
 
101
    if (blockMode && symbol == 256)
 
102
    {
 
103
      numBufBits = bitPos = 0;
 
104
      numBits = kNumMinBits;
 
105
      head = 257;
 
106
      needPrev = false;
 
107
      continue;
 
108
    }
 
109
    UInt32 cur = symbol;
 
110
    int i = 0;
 
111
    while (cur >= 256)
 
112
    {
 
113
      _stack[i++] = _suffixes[cur];
 
114
      cur = _parents[cur];
 
115
    }
 
116
    _stack[i++] = (Byte)cur;
 
117
    if (needPrev)
 
118
    {
 
119
      _suffixes[head - 1] = (Byte)cur;
 
120
      if (symbol == head - 1)
 
121
        _stack[0] = (Byte)cur;
 
122
    }
 
123
    do
 
124
      outBuffer.WriteByte((_stack[--i]));
 
125
    while (i > 0);
 
126
    if (head < numItems)
 
127
    {
 
128
      needPrev = true;
 
129
      _parents[head++] = (UInt16)symbol;
 
130
      if (head > ((UInt32)1 << numBits))
 
131
      {
 
132
        if (numBits < maxbits)
 
133
        {
 
134
          numBufBits = bitPos = 0;
 
135
          numBits++;
 
136
        }
 
137
      }
 
138
    }
 
139
    else
 
140
      needPrev = false;
 
141
  }
 
142
  return outBuffer.Flush();
 
143
}
 
144
 
 
145
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
 
146
    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
 
147
{
 
148
  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
 
149
  catch(const CInBufferException &e) { return e.ErrorCode; }
 
150
  catch(const COutBufferException &e) { return e.ErrorCode; }
 
151
  catch(...) { return S_FALSE; }
 
152
}
 
153
 
 
154
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
 
155
{
 
156
  if (size < 1)
 
157
    return E_INVALIDARG;
 
158
  _properties = data[0];
 
159
  return S_OK;
 
160
}
 
161
 
 
162
}}