rlm@1
|
1 // LzhDecoder.cpp
|
rlm@1
|
2
|
rlm@1
|
3 #include "StdAfx.h"
|
rlm@1
|
4
|
rlm@1
|
5 #include "LzhDecoder.h"
|
rlm@1
|
6
|
rlm@1
|
7 #include "Windows/Defs.h"
|
rlm@1
|
8
|
rlm@1
|
9 namespace NCompress{
|
rlm@1
|
10 namespace NLzh {
|
rlm@1
|
11 namespace NDecoder {
|
rlm@1
|
12
|
rlm@1
|
13 static const UInt32 kHistorySize = (1 << 16);
|
rlm@1
|
14
|
rlm@1
|
15 static const int kBlockSizeBits = 16;
|
rlm@1
|
16 static const int kNumCBits = 9;
|
rlm@1
|
17 static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/
|
rlm@1
|
18
|
rlm@1
|
19 UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
|
rlm@1
|
20
|
rlm@1
|
21 HRESULT CCoder::ReadLevelTable()
|
rlm@1
|
22 {
|
rlm@1
|
23 int n = ReadBits(kNumLevelBits);
|
rlm@1
|
24 if (n == 0)
|
rlm@1
|
25 {
|
rlm@1
|
26 m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);
|
rlm@1
|
27 if (m_LevelHuffman.Symbol >= kNumLevelSymbols)
|
rlm@1
|
28 return S_FALSE;
|
rlm@1
|
29 }
|
rlm@1
|
30 else
|
rlm@1
|
31 {
|
rlm@1
|
32 if (n > kNumLevelSymbols)
|
rlm@1
|
33 return S_FALSE;
|
rlm@1
|
34 m_LevelHuffman.Symbol = -1;
|
rlm@1
|
35 Byte lens[kNumLevelSymbols];
|
rlm@1
|
36 int i = 0;
|
rlm@1
|
37 while (i < n)
|
rlm@1
|
38 {
|
rlm@1
|
39 int c = m_InBitStream.ReadBits(3);
|
rlm@1
|
40 if (c == 7)
|
rlm@1
|
41 while (ReadBits(1))
|
rlm@1
|
42 if (c++ > kMaxHuffmanLen)
|
rlm@1
|
43 return S_FALSE;
|
rlm@1
|
44 lens[i++] = (Byte)c;
|
rlm@1
|
45 if (i == kNumSpecLevelSymbols)
|
rlm@1
|
46 {
|
rlm@1
|
47 c = ReadBits(2);
|
rlm@1
|
48 while (--c >= 0)
|
rlm@1
|
49 lens[i++] = 0;
|
rlm@1
|
50 }
|
rlm@1
|
51 }
|
rlm@1
|
52 while (i < kNumLevelSymbols)
|
rlm@1
|
53 lens[i++] = 0;
|
rlm@1
|
54 m_LevelHuffman.SetCodeLengths(lens);
|
rlm@1
|
55 }
|
rlm@1
|
56 return S_OK;
|
rlm@1
|
57 }
|
rlm@1
|
58
|
rlm@1
|
59 HRESULT CCoder::ReadPTable(int numBits)
|
rlm@1
|
60 {
|
rlm@1
|
61 int n = ReadBits(numBits);
|
rlm@1
|
62 if (n == 0)
|
rlm@1
|
63 {
|
rlm@1
|
64 m_PHuffmanDecoder.Symbol = ReadBits(numBits);
|
rlm@1
|
65 if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)
|
rlm@1
|
66 return S_FALSE;
|
rlm@1
|
67 }
|
rlm@1
|
68 else
|
rlm@1
|
69 {
|
rlm@1
|
70 if (n > kNumDistanceSymbols)
|
rlm@1
|
71 return S_FALSE;
|
rlm@1
|
72 m_PHuffmanDecoder.Symbol = -1;
|
rlm@1
|
73 Byte lens[kNumDistanceSymbols];
|
rlm@1
|
74 int i = 0;
|
rlm@1
|
75 while (i < n)
|
rlm@1
|
76 {
|
rlm@1
|
77 int c = m_InBitStream.ReadBits(3);
|
rlm@1
|
78 if (c == 7)
|
rlm@1
|
79 while (ReadBits(1))
|
rlm@1
|
80 {
|
rlm@1
|
81 if (c > kMaxHuffmanLen)
|
rlm@1
|
82 return S_FALSE;
|
rlm@1
|
83 c++;
|
rlm@1
|
84 }
|
rlm@1
|
85 lens[i++] = (Byte)c;
|
rlm@1
|
86 }
|
rlm@1
|
87 while (i < kNumDistanceSymbols)
|
rlm@1
|
88 lens[i++] = 0;
|
rlm@1
|
89 m_PHuffmanDecoder.SetCodeLengths(lens);
|
rlm@1
|
90 }
|
rlm@1
|
91 return S_OK;
|
rlm@1
|
92 }
|
rlm@1
|
93
|
rlm@1
|
94 HRESULT CCoder::ReadCTable()
|
rlm@1
|
95 {
|
rlm@1
|
96 int n = ReadBits(kNumCBits);
|
rlm@1
|
97 if (n == 0)
|
rlm@1
|
98 {
|
rlm@1
|
99 m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);
|
rlm@1
|
100 if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)
|
rlm@1
|
101 return S_FALSE;
|
rlm@1
|
102 }
|
rlm@1
|
103 else
|
rlm@1
|
104 {
|
rlm@1
|
105 if (n > kNumCSymbols)
|
rlm@1
|
106 return S_FALSE;
|
rlm@1
|
107 m_CHuffmanDecoder.Symbol = -1;
|
rlm@1
|
108 Byte lens[kNumCSymbols];
|
rlm@1
|
109 int i = 0;
|
rlm@1
|
110 while (i < n)
|
rlm@1
|
111 {
|
rlm@1
|
112 int c = m_LevelHuffman.Decode(&m_InBitStream);
|
rlm@1
|
113 if (c < kNumSpecLevelSymbols)
|
rlm@1
|
114 {
|
rlm@1
|
115 if (c == 0)
|
rlm@1
|
116 c = 1;
|
rlm@1
|
117 else if (c == 1)
|
rlm@1
|
118 c = ReadBits(4) + 3;
|
rlm@1
|
119 else
|
rlm@1
|
120 c = ReadBits(kNumCBits) + 20;
|
rlm@1
|
121 while (--c >= 0)
|
rlm@1
|
122 {
|
rlm@1
|
123 if (i > kNumCSymbols)
|
rlm@1
|
124 return S_FALSE;
|
rlm@1
|
125 lens[i++] = 0;
|
rlm@1
|
126 }
|
rlm@1
|
127 }
|
rlm@1
|
128 else
|
rlm@1
|
129 lens[i++] = (Byte)(c - 2);
|
rlm@1
|
130 }
|
rlm@1
|
131 while (i < kNumCSymbols)
|
rlm@1
|
132 lens[i++] = 0;
|
rlm@1
|
133 m_CHuffmanDecoder.SetCodeLengths(lens);
|
rlm@1
|
134 }
|
rlm@1
|
135 return S_OK;
|
rlm@1
|
136 }
|
rlm@1
|
137
|
rlm@1
|
138 STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
|
rlm@1
|
139 ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
rlm@1
|
140 ICompressProgressInfo *progress)
|
rlm@1
|
141 {
|
rlm@1
|
142 if (outSize == NULL)
|
rlm@1
|
143 return E_INVALIDARG;
|
rlm@1
|
144
|
rlm@1
|
145 if (!m_OutWindowStream.Create(kHistorySize))
|
rlm@1
|
146 return E_OUTOFMEMORY;
|
rlm@1
|
147 if (!m_InBitStream.Create(1 << 20))
|
rlm@1
|
148 return E_OUTOFMEMORY;
|
rlm@1
|
149
|
rlm@1
|
150 UInt64 pos = 0;
|
rlm@1
|
151 m_OutWindowStream.SetStream(outStream);
|
rlm@1
|
152 m_OutWindowStream.Init(false);
|
rlm@1
|
153 m_InBitStream.SetStream(inStream);
|
rlm@1
|
154 m_InBitStream.Init();
|
rlm@1
|
155
|
rlm@1
|
156 CCoderReleaser coderReleaser(this);
|
rlm@1
|
157
|
rlm@1
|
158 int pbit;
|
rlm@1
|
159 if (m_NumDictBits <= 13)
|
rlm@1
|
160 pbit = 4;
|
rlm@1
|
161 else
|
rlm@1
|
162 pbit = 5;
|
rlm@1
|
163
|
rlm@1
|
164 UInt32 blockSize = 0;
|
rlm@1
|
165
|
rlm@1
|
166 while(pos < *outSize)
|
rlm@1
|
167 {
|
rlm@1
|
168 // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;
|
rlm@1
|
169
|
rlm@1
|
170 if (blockSize == 0)
|
rlm@1
|
171 {
|
rlm@1
|
172 if (progress != NULL)
|
rlm@1
|
173 {
|
rlm@1
|
174 UInt64 packSize = m_InBitStream.GetProcessedSize();
|
rlm@1
|
175 RINOK(progress->SetRatioInfo(&packSize, &pos));
|
rlm@1
|
176 }
|
rlm@1
|
177 blockSize = ReadBits(kBlockSizeBits);
|
rlm@1
|
178 ReadLevelTable();
|
rlm@1
|
179 ReadCTable();
|
rlm@1
|
180 RINOK(ReadPTable(pbit));
|
rlm@1
|
181 }
|
rlm@1
|
182 blockSize--;
|
rlm@1
|
183 UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);
|
rlm@1
|
184 if (c < 256)
|
rlm@1
|
185 {
|
rlm@1
|
186 m_OutWindowStream.PutByte((Byte)c);
|
rlm@1
|
187 pos++;
|
rlm@1
|
188 }
|
rlm@1
|
189 else if (c >= kNumCSymbols)
|
rlm@1
|
190 return S_FALSE;
|
rlm@1
|
191 else
|
rlm@1
|
192 {
|
rlm@1
|
193 // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;
|
rlm@1
|
194 UInt32 len = c - 256 + kMinMatch;
|
rlm@1
|
195 UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);
|
rlm@1
|
196 if (distance != 0)
|
rlm@1
|
197 distance = (1 << (distance - 1)) + ReadBits(distance - 1);
|
rlm@1
|
198 if (distance >= pos)
|
rlm@1
|
199 return S_FALSE;
|
rlm@1
|
200 if (pos + len > *outSize)
|
rlm@1
|
201 len = (UInt32)(*outSize - pos);
|
rlm@1
|
202 pos += len;
|
rlm@1
|
203 m_OutWindowStream.CopyBlock(distance, len);
|
rlm@1
|
204 }
|
rlm@1
|
205 }
|
rlm@1
|
206 coderReleaser.NeedFlush = false;
|
rlm@1
|
207 return m_OutWindowStream.Flush();
|
rlm@1
|
208 }
|
rlm@1
|
209
|
rlm@1
|
210 STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,
|
rlm@1
|
211 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
rlm@1
|
212 ICompressProgressInfo *progress)
|
rlm@1
|
213 {
|
rlm@1
|
214 try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
|
rlm@1
|
215 catch(const CInBufferException &e) { return e.ErrorCode; }
|
rlm@1
|
216 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
rlm@1
|
217 catch(...) { return S_FALSE; }
|
rlm@1
|
218 }
|
rlm@1
|
219
|
rlm@1
|
220 }}}
|