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