Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Compress/ShrinkDecoder.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 // ShrinkDecoder.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 extern "C" | |
6 { | |
7 #include "../../../C/Alloc.h" | |
8 } | |
9 | |
10 #include "../Common/InBuffer.h" | |
11 #include "../Common/OutBuffer.h" | |
12 | |
13 #include "BitlDecoder.h" | |
14 #include "ShrinkDecoder.h" | |
15 | |
16 namespace NCompress { | |
17 namespace NShrink { | |
18 | |
19 static const UInt32 kBufferSize = (1 << 20); | |
20 static const int kNumMinBits = 9; | |
21 | |
22 HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, | |
23 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) | |
24 { | |
25 NBitl::CBaseDecoder<CInBuffer> inBuffer; | |
26 COutBuffer outBuffer; | |
27 | |
28 if (!inBuffer.Create(kBufferSize)) | |
29 return E_OUTOFMEMORY; | |
30 inBuffer.SetStream(inStream); | |
31 inBuffer.Init(); | |
32 | |
33 if (!outBuffer.Create(kBufferSize)) | |
34 return E_OUTOFMEMORY; | |
35 outBuffer.SetStream(outStream); | |
36 outBuffer.Init(); | |
37 | |
38 UInt64 prevPos = 0; | |
39 int numBits = kNumMinBits; | |
40 UInt32 head = 257; | |
41 bool needPrev = false; | |
42 UInt32 lastSymbol = 0; | |
43 | |
44 int i; | |
45 for (i = 0; i < kNumItems; i++) | |
46 _parents[i] = 0; | |
47 for (i = 0; i < kNumItems; i++) | |
48 _suffixes[i] = 0; | |
49 for (i = 0; i < 257; i++) | |
50 _isFree[i] = false; | |
51 for (; i < kNumItems; i++) | |
52 _isFree[i] = true; | |
53 | |
54 for (;;) | |
55 { | |
56 UInt32 symbol = inBuffer.ReadBits(numBits); | |
57 if (inBuffer.ExtraBitsWereRead()) | |
58 break; | |
59 if (_isFree[symbol]) | |
60 return S_FALSE; | |
61 if (symbol == 256) | |
62 { | |
63 UInt32 symbol = inBuffer.ReadBits(numBits); | |
64 if (symbol == 1) | |
65 { | |
66 if (numBits < kNumMaxBits) | |
67 numBits++; | |
68 } | |
69 else if (symbol == 2) | |
70 { | |
71 if (needPrev) | |
72 _isFree[head - 1] = true; | |
73 for (i = 257; i < kNumItems; i++) | |
74 _isParent[i] = false; | |
75 for (i = 257; i < kNumItems; i++) | |
76 if (!_isFree[i]) | |
77 _isParent[_parents[i]] = true; | |
78 for (i = 257; i < kNumItems; i++) | |
79 if (!_isParent[i]) | |
80 _isFree[i] = true; | |
81 head = 257; | |
82 while (head < kNumItems && !_isFree[head]) | |
83 head++; | |
84 if (head < kNumItems) | |
85 { | |
86 needPrev = true; | |
87 _isFree[head] = false; | |
88 _parents[head] = (UInt16)lastSymbol; | |
89 head++; | |
90 } | |
91 } | |
92 else | |
93 return S_FALSE; | |
94 continue; | |
95 } | |
96 UInt32 cur = symbol; | |
97 i = 0; | |
98 int corectionIndex = -1; | |
99 while (cur >= 256) | |
100 { | |
101 if (cur == head - 1) | |
102 corectionIndex = i; | |
103 _stack[i++] = _suffixes[cur]; | |
104 cur = _parents[cur]; | |
105 } | |
106 _stack[i++] = (Byte)cur; | |
107 if (needPrev) | |
108 { | |
109 _suffixes[head - 1] = (Byte)cur; | |
110 if (corectionIndex >= 0) | |
111 _stack[corectionIndex] = (Byte)cur; | |
112 } | |
113 while (i > 0) | |
114 outBuffer.WriteByte((_stack[--i])); | |
115 while (head < kNumItems && !_isFree[head]) | |
116 head++; | |
117 if (head < kNumItems) | |
118 { | |
119 needPrev = true; | |
120 _isFree[head] = false; | |
121 _parents[head] = (UInt16)symbol; | |
122 head++; | |
123 } | |
124 else | |
125 needPrev = false; | |
126 lastSymbol = symbol; | |
127 | |
128 UInt64 nowPos = outBuffer.GetProcessedSize(); | |
129 if (progress != NULL && nowPos - prevPos > (1 << 18)) | |
130 { | |
131 prevPos = nowPos; | |
132 UInt64 packSize = inBuffer.GetProcessedSize(); | |
133 RINOK(progress->SetRatioInfo(&packSize, &nowPos)); | |
134 } | |
135 } | |
136 return outBuffer.Flush(); | |
137 } | |
138 | |
139 STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, | |
140 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) | |
141 { | |
142 try { return CodeReal(inStream, outStream, inSize, outSize, progress); } | |
143 catch(const CInBufferException &e) { return e.ErrorCode; } | |
144 catch(const COutBufferException &e) { return e.ErrorCode; } | |
145 catch(...) { return S_FALSE; } | |
146 } | |
147 | |
148 }} |