~ubuntu-branches/ubuntu/trusty/advancecomp/trusty

« back to all changes in this revision

Viewing changes to 7z/DeflateDecoder.cc

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ozarowski
  • Date: 2006-05-13 21:15:49 UTC
  • Revision ID: james.westby@ubuntu.com-20060513211549-2vu7peis643ojcm5
Tags: upstream-1.15
ImportĀ upstreamĀ versionĀ 1.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Portable.h"
 
2
#include "DeflateDecoder.h"
 
3
 
 
4
namespace NDeflate {
 
5
namespace NDecoder {
 
6
 
 
7
static const UINT32 kWindowReservSize = (1 << 17) + 256;
 
8
 
 
9
CCoder::CCoder() :
 
10
  m_MainDecoder(kStaticMainTableSize),
 
11
  m_DistDecoder(kStaticDistTableSize),
 
12
  m_LevelDecoder(kLevelTableSize)
 
13
{}
 
14
 
 
15
void CCoder::DeCodeLevelTable(BYTE *aNewLevels, int aNumLevels)
 
16
{
 
17
  int i = 0;
 
18
  while (i < aNumLevels)
 
19
  {
 
20
    UINT32 aNumber = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
 
21
    if (aNumber < kTableDirectLevels)
 
22
      aNewLevels[i++] = BYTE(aNumber);
 
23
    else
 
24
    {
 
25
      if (aNumber == kTableLevelRepNumber)
 
26
      {
 
27
        int t = m_InBitStream.ReadBits(2) + 3;
 
28
        for (int aReps = t; aReps > 0 && i < aNumLevels ; aReps--, i++)
 
29
          aNewLevels[i] = aNewLevels[i - 1];
 
30
      }
 
31
      else
 
32
      {
 
33
        int aNum;
 
34
        if (aNumber == kTableLevel0Number)
 
35
          aNum = m_InBitStream.ReadBits(3) + 3;
 
36
        else
 
37
          aNum = m_InBitStream.ReadBits(7) + 11;
 
38
        for (;aNum > 0 && i < aNumLevels; aNum--)
 
39
          aNewLevels[i++] = 0;
 
40
      }
 
41
    }
 
42
  }
 
43
}
 
44
 
 
45
void CCoder::ReadTables(void)
 
46
{
 
47
  if(m_FinalBlock) // test it
 
48
    throw E_INVALIDDATA;
 
49
 
 
50
  m_FinalBlock = (m_InBitStream.ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
 
51
 
 
52
  int aBlockType = m_InBitStream.ReadBits(kBlockTypeFieldSize);
 
53
 
 
54
  switch(aBlockType)
 
55
  {
 
56
    case NBlockType::kStored:
 
57
      {
 
58
        m_StoredMode = true;
 
59
        UINT32 aCurrentBitPosition = m_InBitStream.GetBitPosition();
 
60
        UINT32 aNumBitsForAlign = aCurrentBitPosition > 0 ? (8 - aCurrentBitPosition): 0;
 
61
        if (aNumBitsForAlign > 0)
 
62
          m_InBitStream.ReadBits(aNumBitsForAlign);
 
63
        m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize);
 
64
        WORD anOnesComplementReverse = ~WORD(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize));
 
65
        if (m_StoredBlockSize != anOnesComplementReverse)
 
66
          throw E_INVALIDDATA;
 
67
        break;
 
68
      }
 
69
    case NBlockType::kFixedHuffman:
 
70
    case NBlockType::kDynamicHuffman:
 
71
      {
 
72
        m_StoredMode = false;
 
73
        BYTE aLitLenLevels[kStaticMainTableSize];
 
74
        BYTE aDistLevels[kStaticDistTableSize];
 
75
        if (aBlockType == NBlockType::kFixedHuffman)
 
76
        {
 
77
          int i;
 
78
 
 
79
          // Leteral / length levels
 
80
          for (i = 0; i < 144; i++)
 
81
            aLitLenLevels[i] = 8;
 
82
          for (; i < 256; i++)
 
83
            aLitLenLevels[i] = 9;
 
84
          for (; i < 280; i++)
 
85
            aLitLenLevels[i] = 7;
 
86
          for (; i < 288; i++)          /* make a complete, but wrong code set */
 
87
            aLitLenLevels[i] = 8;
 
88
        
 
89
          // Distance levels
 
90
          for (i = 0; i < kStaticDistTableSize; i++)  // test it: infozip only use kDistTableSize       
 
91
            aDistLevels[i] = 5;
 
92
        }
 
93
        else // in case when (aBlockType == kDeflateBlockTypeFixedHuffman)
 
94
        {
 
95
          int aNumLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) + 
 
96
            kDeflateNumberOfLitLenCodesMin;
 
97
          int aNumDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) + 
 
98
            kDeflateNumberOfDistanceCodesMin;
 
99
          int aNumLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) + 
 
100
            kDeflateNumberOfLevelCodesMin;
 
101
          
 
102
          int aNumLevels;
 
103
          aNumLevels = kHeapTablesSizesSum;
 
104
          
 
105
          BYTE aLevelLevels[kLevelTableSize];
 
106
          int i;
 
107
          for (i = 0; i < kLevelTableSize; i++)
 
108
          {
 
109
            int aPosition = kCodeLengthAlphabetOrder[i]; 
 
110
            if(i < aNumLevelCodes)
 
111
              aLevelLevels[aPosition] = BYTE(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize));
 
112
            else
 
113
              aLevelLevels[aPosition] = 0;
 
114
          }
 
115
          
 
116
          try
 
117
          {
 
118
            m_LevelDecoder.SetCodeLengths(aLevelLevels);
 
119
          }
 
120
          catch(...)
 
121
          {
 
122
            throw E_INVALIDDATA;
 
123
          }
 
124
          
 
125
          BYTE aTmpLevels[kStaticMaxTableSize];
 
126
          DeCodeLevelTable(aTmpLevels, aNumLitLenLevels + aNumDistLevels);
 
127
          
 
128
          memmove(aLitLenLevels, aTmpLevels, aNumLitLenLevels);
 
129
          memset(aLitLenLevels + aNumLitLenLevels, 0, 
 
130
            kStaticMainTableSize - aNumLitLenLevels);
 
131
          
 
132
          memmove(aDistLevels, aTmpLevels + aNumLitLenLevels, aNumDistLevels);
 
133
          memset(aDistLevels + aNumDistLevels, 0, kStaticDistTableSize - aNumDistLevels);
 
134
        }
 
135
        try
 
136
        {
 
137
          m_MainDecoder.SetCodeLengths(aLitLenLevels);
 
138
          m_DistDecoder.SetCodeLengths(aDistLevels);
 
139
        }
 
140
        catch(...)
 
141
        {
 
142
          throw E_INVALIDDATA;
 
143
        }
 
144
        break;
 
145
      }
 
146
    default:
 
147
      throw E_INVALIDDATA;
 
148
  }
 
149
}
 
150
 
 
151
HRESULT CCoder::CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize)
 
152
{
 
153
  if (m_OutWindowStream.GetBuffer() == 0)
 
154
  {
 
155
    try
 
156
    {
 
157
      m_OutWindowStream.Create(kHistorySize, kMatchMaxLen, kWindowReservSize);
 
158
    }
 
159
    catch(...)
 
160
    {
 
161
      return E_OUTOFMEMORY;
 
162
    }
 
163
  }
 
164
  UINT64 aPos = 0;
 
165
  m_OutWindowStream.Init(anOutStream, false);
 
166
  m_InBitStream.Init(anInStream);
 
167
 
 
168
  m_FinalBlock = false;
 
169
 
 
170
  while(!m_FinalBlock)
 
171
  {
 
172
    ReadTables();
 
173
    if(m_StoredMode)
 
174
    {
 
175
      for (UINT32 i = 0; i < m_StoredBlockSize; i++)
 
176
        m_OutWindowStream.PutOneByte(BYTE(m_InBitStream.ReadBits(8)));
 
177
      aPos += m_StoredBlockSize;
 
178
      continue;
 
179
    }
 
180
    while(true)
 
181
    {
 
182
      UINT32 aNumber = m_MainDecoder.DecodeSymbol(&m_InBitStream);
 
183
      if (aNumber < 256)
 
184
      {
 
185
        if (anOutSize != NULL)
 
186
          if (aPos >= *anOutSize)
 
187
            throw E_INVALIDDATA;
 
188
        m_OutWindowStream.PutOneByte(BYTE(aNumber));
 
189
        aPos++;
 
190
        continue;
 
191
      }
 
192
      else if (aNumber >= kMatchNumber)
 
193
      {
 
194
        if (anOutSize != NULL)
 
195
          if (aPos >= *anOutSize)
 
196
            throw E_INVALIDDATA;
 
197
        aNumber -= kMatchNumber;
 
198
        UINT32 aLength = UINT32(kLenStart[aNumber]) + kMatchMinLen;
 
199
        UINT32 aNumBits; 
 
200
        if ((aNumBits = kLenDirectBits[aNumber]) > 0)
 
201
          aLength += m_InBitStream.ReadBits(aNumBits);
 
202
        
 
203
        aNumber = m_DistDecoder.DecodeSymbol(&m_InBitStream);
 
204
        UINT32 aDistance = kDistStart[aNumber] + m_InBitStream.ReadBits(kDistDirectBits[aNumber]);
 
205
        if (aDistance >= aPos)
 
206
          throw E_INVALIDDATA;
 
207
         m_OutWindowStream.CopyBackBlock(aDistance, aLength);
 
208
        aPos += aLength;
 
209
      }
 
210
      else if (aNumber == kReadTableNumber)
 
211
        break;
 
212
      else
 
213
        throw E_INVALIDDATA;
 
214
    }
 
215
  }
 
216
  return m_OutWindowStream.Flush();
 
217
}
 
218
 
 
219
HRESULT CCoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize)
 
220
{
 
221
        try {
 
222
                return CodeReal(anInStream, anOutStream, anInSize, anOutSize);
 
223
        } catch (HRESULT& e) {
 
224
                return e;
 
225
        } catch (...) {
 
226
                return E_FAIL;
 
227
        }
 
228
}
 
229
 
 
230
}}