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

« back to all changes in this revision

Viewing changes to CPP/7zip/Compress/ImplodeDecoder.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
// Implode/Decoder.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
#include "ImplodeDecoder.h"
 
6
#include "Common/Defs.h"
 
7
 
 
8
namespace NCompress {
 
9
namespace NImplode {
 
10
namespace NDecoder {
 
11
 
 
12
class CException
 
13
{
 
14
public:
 
15
  enum ECauseType
 
16
  {
 
17
    kData
 
18
  } m_Cause;
 
19
  CException(ECauseType cause): m_Cause(cause) {}
 
20
};
 
21
 
 
22
static const int kNumDistanceLowDirectBitsForBigDict = 7;
 
23
static const int kNumDistanceLowDirectBitsForSmallDict = 6;
 
24
 
 
25
static const int kNumBitsInByte = 8;
 
26
 
 
27
// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte;
 
28
static const int kLevelStructuresNumberAdditionalValue = 1;
 
29
 
 
30
static const int kNumLevelStructureLevelBits = 4;
 
31
static const int kLevelStructureLevelAdditionalValue = 1;
 
32
 
 
33
static const int kNumLevelStructureRepNumberBits = 4;
 
34
static const int kLevelStructureRepNumberAdditionalValue = 1;
 
35
 
 
36
 
 
37
static const int kLiteralTableSize = (1 << kNumBitsInByte);
 
38
static const int kDistanceTableSize = 64;
 
39
static const int kLengthTableSize = 64;
 
40
 
 
41
static const UInt32 kHistorySize =
 
42
    (1 << MyMax(kNumDistanceLowDirectBitsForBigDict,
 
43
                kNumDistanceLowDirectBitsForSmallDict)) *
 
44
    kDistanceTableSize; // = 8 KB;
 
45
 
 
46
static const int kNumAdditionalLengthBits = 8;
 
47
 
 
48
static const UInt32 kMatchMinLenWhenLiteralsOn = 3;
 
49
static const UInt32 kMatchMinLenWhenLiteralsOff = 2;
 
50
 
 
51
static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn,
 
52
    kMatchMinLenWhenLiteralsOff);  // 3
 
53
 
 
54
// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1;  // or 2
 
55
 
 
56
enum
 
57
{
 
58
  kMatchId = 0,
 
59
  kLiteralId = 1
 
60
};
 
61
 
 
62
 
 
63
CCoder::CCoder():
 
64
  m_LiteralDecoder(kLiteralTableSize),
 
65
  m_LengthDecoder(kLengthTableSize),
 
66
  m_DistanceDecoder(kDistanceTableSize)
 
67
{
 
68
}
 
69
 
 
70
void CCoder::ReleaseStreams()
 
71
{
 
72
  m_OutWindowStream.ReleaseStream();
 
73
  m_InBitStream.ReleaseStream();
 
74
}
 
75
 
 
76
bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder,
 
77
    Byte *levels, int numLevelItems)
 
78
{
 
79
  int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) +
 
80
      kLevelStructuresNumberAdditionalValue;
 
81
  int currentIndex = 0;
 
82
  for(int i = 0; i < numCodedStructures; i++)
 
83
  {
 
84
    int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) +
 
85
      kLevelStructureLevelAdditionalValue;
 
86
    int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) +
 
87
      kLevelStructureRepNumberAdditionalValue;
 
88
    if (currentIndex + rep > numLevelItems)
 
89
      throw CException(CException::kData);
 
90
    for(int j = 0; j < rep; j++)
 
91
      levels[currentIndex++] = (Byte)level;
 
92
  }
 
93
  if (currentIndex != numLevelItems)
 
94
    return false;
 
95
  return decoder.SetCodeLengths(levels);
 
96
}
 
97
 
 
98
 
 
99
bool CCoder::ReadTables(void)
 
100
{
 
101
  if (m_LiteralsOn)
 
102
  {
 
103
    Byte literalLevels[kLiteralTableSize];
 
104
    if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize))
 
105
      return false;
 
106
  }
 
107
 
 
108
  Byte lengthLevels[kLengthTableSize];
 
109
  if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize))
 
110
    return false;
 
111
 
 
112
  Byte distanceLevels[kDistanceTableSize];
 
113
  return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize);
 
114
}
 
115
 
 
116
class CCoderReleaser
 
117
{
 
118
  CCoder *m_Coder;
 
119
public:
 
120
  CCoderReleaser(CCoder *coder): m_Coder(coder) {}
 
121
  ~CCoderReleaser() { m_Coder->ReleaseStreams(); }
 
122
};
 
123
 
 
124
HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
 
125
    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
 
126
{
 
127
  if (!m_InBitStream.Create(1 << 20))
 
128
    return E_OUTOFMEMORY;
 
129
  if (!m_OutWindowStream.Create(kHistorySize))
 
130
    return E_OUTOFMEMORY;
 
131
  if (outSize == NULL)
 
132
    return E_INVALIDARG;
 
133
  UInt64 pos = 0, unPackSize = *outSize;
 
134
 
 
135
  m_OutWindowStream.SetStream(outStream);
 
136
  m_OutWindowStream.Init(false);
 
137
  m_InBitStream.SetStream(inStream);
 
138
  m_InBitStream.Init();
 
139
  CCoderReleaser coderReleaser(this);
 
140
 
 
141
  if (!ReadTables())
 
142
    return S_FALSE;
 
143
  
 
144
  while(pos < unPackSize)
 
145
  {
 
146
    if (progress != NULL && pos % (1 << 16) == 0)
 
147
    {
 
148
      UInt64 packSize = m_InBitStream.GetProcessedSize();
 
149
      RINOK(progress->SetRatioInfo(&packSize, &pos));
 
150
    }
 
151
    if(m_InBitStream.ReadBits(1) == kMatchId) // match
 
152
    {
 
153
      UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);
 
154
      UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);
 
155
      if (distance >= kDistanceTableSize)
 
156
        return S_FALSE;
 
157
      distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;
 
158
      UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);
 
159
      if (lengthSymbol >= kLengthTableSize)
 
160
        return S_FALSE;
 
161
      UInt32 length = lengthSymbol + m_MinMatchLength;
 
162
      if (lengthSymbol == kLengthTableSize - 1) // special symbol  = 63
 
163
        length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);
 
164
      while(distance >= pos && length > 0)
 
165
      {
 
166
        m_OutWindowStream.PutByte(0);
 
167
        pos++;
 
168
        length--;
 
169
      }
 
170
      if (length > 0)
 
171
        m_OutWindowStream.CopyBlock(distance, length);
 
172
      pos += length;
 
173
    }
 
174
    else
 
175
    {
 
176
      Byte b;
 
177
      if (m_LiteralsOn)
 
178
      {
 
179
        UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);
 
180
        if (temp >= kLiteralTableSize)
 
181
          return S_FALSE;
 
182
        b = (Byte)temp;
 
183
      }
 
184
      else
 
185
        b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);
 
186
      m_OutWindowStream.PutByte(b);
 
187
      pos++;
 
188
    }
 
189
  }
 
190
  if (pos > unPackSize)
 
191
    return S_FALSE;
 
192
  return m_OutWindowStream.Flush();
 
193
}
 
194
 
 
195
STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
 
196
    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
 
197
{
 
198
  try { return CodeReal(inStream, outStream, inSize, outSize, progress);  }
 
199
  catch(const CLzOutWindowException &e) { return e.ErrorCode; }
 
200
  catch(...) { return S_FALSE; }
 
201
}
 
202
 
 
203
STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
 
204
{
 
205
  if (size < 1)
 
206
    return E_INVALIDARG;
 
207
  Byte flag = data[0];
 
208
  m_BigDictionaryOn = ((flag & 2) != 0);
 
209
  m_NumDistanceLowDirectBits = m_BigDictionaryOn ?
 
210
      kNumDistanceLowDirectBitsForBigDict:
 
211
      kNumDistanceLowDirectBitsForSmallDict;
 
212
  m_LiteralsOn = ((flag & 4) != 0);
 
213
  m_MinMatchLength = m_LiteralsOn ?
 
214
      kMatchMinLenWhenLiteralsOn :
 
215
      kMatchMinLenWhenLiteralsOff;
 
216
  return S_OK;
 
217
}
 
218
 
 
219
}}}