5 #include "ArjDecoder1.h"
\r
9 namespace NDecoder1 {
\r
11 static const UInt32 kHistorySize = 26624;
\r
12 static const UInt32 kMatchMinLen = 3;
\r
13 static const UInt32 kMatchMaxLen = 256;
\r
15 // static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;
\r
17 void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits,
\r
18 UInt32 *table, int tablesize)
\r
20 UInt32 count[17], weight[17], start[18], *p;
\r
21 UInt32 i, k, len, ch, jutbits, avail, nextcode, mask;
\r
23 for (i = 1; i <= 16; i++)
\r
25 for (i = 0; (int)i < nchar; i++)
\r
29 for (i = 1; i <= 16; i++)
\r
30 start[i + 1] = start[i] + (count[i] << (16 - i));
\r
31 if (start[17] != (UInt32) (1 << 16))
\r
34 jutbits = 16 - tablebits;
\r
35 for (i = 1; (int)i <= tablebits; i++)
\r
37 start[i] >>= jutbits;
\r
38 weight[i] = 1 << (tablebits - i);
\r
42 weight[i] = 1 << (16 - i);
\r
46 i = start[tablebits + 1] >> jutbits;
\r
47 if (i != (UInt32) (1 << 16))
\r
55 mask = 1 << (15 - tablebits);
\r
56 for (ch = 0; (int)ch < nchar; ch++)
\r
58 if ((len = bitlen[ch]) == 0)
\r
61 nextcode = k + weight[len];
\r
62 if ((int)len <= tablebits)
\r
64 if (nextcode > (UInt32)tablesize)
\r
66 for (i = start[len]; i < nextcode; i++)
\r
71 p = &table[k >> jutbits];
\r
72 i = len - tablebits;
\r
77 right[avail] = left[avail] = 0;
\r
89 start[len] = nextcode;
\r
93 void CCoder::read_pt_len(int nn, int nbit, int i_special)
\r
95 UInt32 n = m_InBitStream.ReadBits(nbit);
\r
98 UInt32 c = m_InBitStream.ReadBits(nbit);
\r
100 for (i = 0; i < nn; i++)
\r
102 for (i = 0; i < 256; i++)
\r
110 UInt32 bitBuf = m_InBitStream.GetValue(16);
\r
111 int c = bitBuf >> 13;
\r
114 UInt32 mask = 1 << (12);
\r
115 while (mask & bitBuf)
\r
121 m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3));
\r
122 pt_len[i++] = (Byte)c;
\r
123 if (i == (UInt32)i_special)
\r
125 c = m_InBitStream.ReadBits(2);
\r
130 while (i < (UInt32)nn)
\r
132 MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE);
\r
136 void CCoder::read_c_len()
\r
141 n = m_InBitStream.ReadBits(CBIT);
\r
144 c = m_InBitStream.ReadBits(CBIT);
\r
145 for (i = 0; i < NC; i++)
\r
147 for (i = 0; i < CTABLESIZE; i++)
\r
155 UInt32 bitBuf = m_InBitStream.GetValue(16);
\r
156 c = pt_table[bitBuf >> (8)];
\r
169 m_InBitStream.MovePos((int)(pt_len[c]));
\r
175 c = m_InBitStream.ReadBits(4) + 3;
\r
177 c = m_InBitStream.ReadBits(CBIT) + 20;
\r
182 c_len[i++] = (Byte)(c - 2);
\r
186 MakeTable(NC, c_len, 12, c_table, CTABLESIZE);
\r
190 UInt32 CCoder::decode_c()
\r
193 UInt32 bitbuf = m_InBitStream.GetValue(16);
\r
194 j = c_table[bitbuf >> 4];
\r
207 m_InBitStream.MovePos((int)(c_len[j]));
\r
211 UInt32 CCoder::decode_p()
\r
214 UInt32 bitbuf = m_InBitStream.GetValue(16);
\r
215 j = pt_table[bitbuf >> (8)];
\r
228 m_InBitStream.MovePos((int)(pt_len[j]));
\r
232 j = (1 << j) + m_InBitStream.ReadBits((int)j);
\r
238 HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
239 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
\r
241 if (outSize == NULL)
\r
242 return E_INVALIDARG;
\r
244 if (!m_OutWindowStream.Create(kHistorySize))
\r
245 return E_OUTOFMEMORY;
\r
246 if (!m_InBitStream.Create(1 << 20))
\r
247 return E_OUTOFMEMORY;
\r
250 for (int i = 0; i < CTABLESIZE; i++)
\r
254 m_OutWindowStream.SetStream(outStream);
\r
255 m_OutWindowStream.Init(false);
\r
256 m_InBitStream.SetStream(inStream);
\r
257 m_InBitStream.Init();
\r
259 CCoderReleaser coderReleaser(this);
\r
261 UInt32 blockSize = 0;
\r
263 while(pos < *outSize)
\r
265 if (blockSize == 0)
\r
267 if (progress != NULL)
\r
269 UInt64 packSize = m_InBitStream.GetProcessedSize();
\r
270 RINOK(progress->SetRatioInfo(&packSize, &pos));
\r
272 blockSize = m_InBitStream.ReadBits(16);
\r
273 read_pt_len(NT, TBIT, 3);
\r
275 read_pt_len(NP, PBIT, -1);
\r
279 UInt32 number = decode_c();
\r
282 m_OutWindowStream.PutByte((Byte)number);
\r
288 UInt32 len = number - 256 + kMatchMinLen;
\r
289 UInt32 distance = decode_p();
\r
290 if (distance >= pos)
\r
292 m_OutWindowStream.CopyBlock(distance, len);
\r
296 coderReleaser.NeedFlush = false;
\r
297 return m_OutWindowStream.Flush();
\r
300 STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
301 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
\r
303 try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
\r
304 catch(const CInBufferException &e) { return e.ErrorCode; }
\r
305 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
\r
306 catch(...) { return S_FALSE; }
\r