1 | package LZMA;
|
---|
2 |
|
---|
3 | import java.io.InputStream;
|
---|
4 | import java.io.IOException;
|
---|
5 |
|
---|
6 | public class LzmaInputStream extends java.io.FilterInputStream {
|
---|
7 | boolean isClosed;
|
---|
8 | CRangeDecoder RangeDecoder;
|
---|
9 | byte [] dictionary;
|
---|
10 | int dictionarySize;
|
---|
11 | int dictionaryPos;
|
---|
12 | int GlobalPos;
|
---|
13 | int rep0, rep1, rep2, rep3;
|
---|
14 | int lc;
|
---|
15 | int lp;
|
---|
16 | int pb;
|
---|
17 | int State;
|
---|
18 | boolean PreviousIsMatch;
|
---|
19 | int RemainLen;
|
---|
20 | int [] probs;
|
---|
21 |
|
---|
22 | byte [] uncompressed_buffer;
|
---|
23 | int uncompressed_size;
|
---|
24 | int uncompressed_offset;
|
---|
25 | long GlobalNowPos;
|
---|
26 | long GlobalOutSize;
|
---|
27 |
|
---|
28 | static final int LZMA_BASE_SIZE = 1846;
|
---|
29 | static final int LZMA_LIT_SIZE = 768;
|
---|
30 |
|
---|
31 | final static int kBlockSize = 0x10000;
|
---|
32 |
|
---|
33 | static final int kNumStates = 12;
|
---|
34 |
|
---|
35 | static final int kStartPosModelIndex = 4;
|
---|
36 | static final int kEndPosModelIndex = 14;
|
---|
37 | static final int kNumFullDistances = (1 << (kEndPosModelIndex >> 1));
|
---|
38 |
|
---|
39 | static final int kNumPosSlotBits = 6;
|
---|
40 | static final int kNumLenToPosStates = 4;
|
---|
41 |
|
---|
42 | static final int kNumAlignBits = 4;
|
---|
43 | static final int kAlignTableSize = (1 << kNumAlignBits);
|
---|
44 |
|
---|
45 | static final int kMatchMinLen = 2;
|
---|
46 |
|
---|
47 | static final int IsMatch = 0;
|
---|
48 | static final int IsRep = (IsMatch + (kNumStates << CRangeDecoder.kNumPosBitsMax));
|
---|
49 | static final int IsRepG0 = (IsRep + kNumStates);
|
---|
50 | static final int IsRepG1 = (IsRepG0 + kNumStates);
|
---|
51 | static final int IsRepG2 = (IsRepG1 + kNumStates);
|
---|
52 | static final int IsRep0Long = (IsRepG2 + kNumStates);
|
---|
53 | static final int PosSlot = (IsRep0Long + (kNumStates << CRangeDecoder.kNumPosBitsMax));
|
---|
54 | static final int SpecPos = (PosSlot + (kNumLenToPosStates << kNumPosSlotBits));
|
---|
55 | static final int Align = (SpecPos + kNumFullDistances - kEndPosModelIndex);
|
---|
56 | static final int LenCoder = (Align + kAlignTableSize);
|
---|
57 | static final int RepLenCoder = (LenCoder + CRangeDecoder.kNumLenProbs);
|
---|
58 | static final int Literal = (RepLenCoder + CRangeDecoder.kNumLenProbs);
|
---|
59 |
|
---|
60 | public LzmaInputStream (InputStream in) throws IOException {
|
---|
61 | super(in);
|
---|
62 |
|
---|
63 | isClosed = false;
|
---|
64 |
|
---|
65 | readHeader();
|
---|
66 |
|
---|
67 | fill_buffer();
|
---|
68 | }
|
---|
69 |
|
---|
70 | private void LzmaDecode(int outSize) throws IOException {
|
---|
71 | byte previousbyte;
|
---|
72 | int posStateMask = (1 << (pb)) - 1;
|
---|
73 | int literalPosMask = (1 << (lp)) - 1;
|
---|
74 |
|
---|
75 | uncompressed_size = 0;
|
---|
76 |
|
---|
77 | if (RemainLen == -1) {
|
---|
78 | return ;
|
---|
79 | }
|
---|
80 |
|
---|
81 | while(RemainLen > 0 && uncompressed_size < outSize) {
|
---|
82 | int pos = dictionaryPos - rep0;
|
---|
83 | if (pos < 0)
|
---|
84 | pos += dictionarySize;
|
---|
85 | uncompressed_buffer[uncompressed_size++] = dictionary[dictionaryPos] = dictionary[pos];
|
---|
86 | if (++dictionaryPos == dictionarySize)
|
---|
87 | dictionaryPos = 0;
|
---|
88 | RemainLen--;
|
---|
89 | }
|
---|
90 | if (dictionaryPos == 0)
|
---|
91 | previousbyte = dictionary[dictionarySize - 1];
|
---|
92 | else
|
---|
93 | previousbyte = dictionary[dictionaryPos - 1];
|
---|
94 |
|
---|
95 | while(uncompressed_size < outSize) {
|
---|
96 | int posState = (int)( (uncompressed_size + GlobalPos ) & posStateMask);
|
---|
97 |
|
---|
98 | if (RangeDecoder.BitDecode(probs, IsMatch + (State << CRangeDecoder.kNumPosBitsMax) + posState) == 0) {
|
---|
99 | int ind_prob = Literal + (LZMA_LIT_SIZE * (((
|
---|
100 | (uncompressed_size + GlobalPos )
|
---|
101 | & literalPosMask) << lc) + ((previousbyte & 0xFF) >> (8 - lc))));
|
---|
102 |
|
---|
103 | if (State < 4)
|
---|
104 | State = 0;
|
---|
105 | else if (State < 10)
|
---|
106 | State -= 3;
|
---|
107 | else
|
---|
108 | State -= 6;
|
---|
109 | if (PreviousIsMatch) {
|
---|
110 | int pos = dictionaryPos - rep0;
|
---|
111 | if (pos < 0)
|
---|
112 | pos += dictionarySize;
|
---|
113 | byte matchbyte = dictionary[pos];
|
---|
114 |
|
---|
115 | previousbyte = RangeDecoder.LzmaLiteralDecodeMatch(probs,ind_prob, matchbyte);
|
---|
116 | PreviousIsMatch = false;
|
---|
117 | } else {
|
---|
118 | previousbyte = RangeDecoder.LzmaLiteralDecode(probs,ind_prob);
|
---|
119 | }
|
---|
120 |
|
---|
121 | uncompressed_buffer[uncompressed_size++] = previousbyte;
|
---|
122 |
|
---|
123 | dictionary[dictionaryPos] = previousbyte;
|
---|
124 | if (++dictionaryPos == dictionarySize)
|
---|
125 | dictionaryPos = 0;
|
---|
126 |
|
---|
127 | } else {
|
---|
128 | PreviousIsMatch = true;
|
---|
129 | if (RangeDecoder.BitDecode(probs, IsRep + State) == 1) {
|
---|
130 | if (RangeDecoder.BitDecode(probs, IsRepG0 + State) == 0) {
|
---|
131 | if (RangeDecoder.BitDecode(probs, IsRep0Long + (State << CRangeDecoder.kNumPosBitsMax) + posState) == 0) {
|
---|
132 |
|
---|
133 | if ((uncompressed_size + GlobalPos) == 0) {
|
---|
134 | throw new LzmaException ("LZMA : Data Error");
|
---|
135 | }
|
---|
136 | State = State < 7 ? 9 : 11;
|
---|
137 |
|
---|
138 | int pos = dictionaryPos - rep0;
|
---|
139 | if (pos < 0)
|
---|
140 | pos += dictionarySize;
|
---|
141 | previousbyte = dictionary[pos];
|
---|
142 | dictionary[dictionaryPos] = previousbyte;
|
---|
143 | if (++dictionaryPos == dictionarySize)
|
---|
144 | dictionaryPos = 0;
|
---|
145 |
|
---|
146 | uncompressed_buffer[uncompressed_size++] = previousbyte;
|
---|
147 | continue;
|
---|
148 | }
|
---|
149 | } else {
|
---|
150 | int distance;
|
---|
151 | if(RangeDecoder.BitDecode(probs, IsRepG1 + State) == 0)
|
---|
152 | distance = rep1;
|
---|
153 | else {
|
---|
154 | if(RangeDecoder.BitDecode(probs, IsRepG2 + State) == 0)
|
---|
155 | distance = rep2;
|
---|
156 | else {
|
---|
157 | distance = rep3;
|
---|
158 | rep3 = rep2;
|
---|
159 | }
|
---|
160 | rep2 = rep1;
|
---|
161 | }
|
---|
162 | rep1 = rep0;
|
---|
163 | rep0 = distance;
|
---|
164 | }
|
---|
165 | RemainLen = RangeDecoder.LzmaLenDecode(probs, RepLenCoder, posState);
|
---|
166 | State = State < 7 ? 8 : 11;
|
---|
167 | } else {
|
---|
168 | rep3 = rep2;
|
---|
169 | rep2 = rep1;
|
---|
170 | rep1 = rep0;
|
---|
171 | State = State < 7 ? 7 : 10;
|
---|
172 | RemainLen = RangeDecoder.LzmaLenDecode(probs, LenCoder, posState);
|
---|
173 | int posSlot = RangeDecoder.BitTreeDecode(probs , PosSlot +
|
---|
174 | ((RemainLen < kNumLenToPosStates ? RemainLen : kNumLenToPosStates - 1) <<
|
---|
175 | kNumPosSlotBits), kNumPosSlotBits);
|
---|
176 | if (posSlot >= kStartPosModelIndex) {
|
---|
177 | int numDirectBits = ((posSlot >> 1) - 1);
|
---|
178 | rep0 = ((2 | (posSlot & 1)) << numDirectBits);
|
---|
179 | if (posSlot < kEndPosModelIndex) {
|
---|
180 | rep0 += RangeDecoder.ReverseBitTreeDecode(
|
---|
181 | probs, SpecPos + rep0 - posSlot - 1, numDirectBits);
|
---|
182 | } else {
|
---|
183 | rep0 += RangeDecoder.DecodeDirectBits(
|
---|
184 | numDirectBits - kNumAlignBits) << kNumAlignBits;
|
---|
185 | rep0 += RangeDecoder.ReverseBitTreeDecode(probs, Align, kNumAlignBits);
|
---|
186 | }
|
---|
187 | } else
|
---|
188 | rep0 = posSlot;
|
---|
189 | rep0++;
|
---|
190 | }
|
---|
191 | if (rep0 == 0) {
|
---|
192 |
|
---|
193 | RemainLen = -1;
|
---|
194 | break;
|
---|
195 | }
|
---|
196 | if (rep0 > uncompressed_size
|
---|
197 |
|
---|
198 | + GlobalPos
|
---|
199 |
|
---|
200 | ) {
|
---|
201 | throw new LzmaException ("LZMA : Data Error");
|
---|
202 | }
|
---|
203 | RemainLen += kMatchMinLen;
|
---|
204 | do {
|
---|
205 |
|
---|
206 | int pos = dictionaryPos - rep0;
|
---|
207 | if (pos < 0)
|
---|
208 | pos += dictionarySize;
|
---|
209 | previousbyte = dictionary[pos];
|
---|
210 | dictionary[dictionaryPos] = previousbyte;
|
---|
211 | if (++dictionaryPos == dictionarySize)
|
---|
212 | dictionaryPos = 0;
|
---|
213 |
|
---|
214 | uncompressed_buffer[uncompressed_size++] = previousbyte;
|
---|
215 | RemainLen--;
|
---|
216 | } while(RemainLen > 0 && uncompressed_size < outSize);
|
---|
217 | }
|
---|
218 | }
|
---|
219 |
|
---|
220 | GlobalPos = GlobalPos + uncompressed_size;
|
---|
221 | }
|
---|
222 |
|
---|
223 | private void fill_buffer() throws IOException {
|
---|
224 | if (GlobalNowPos < GlobalOutSize) {
|
---|
225 | uncompressed_offset = 0;
|
---|
226 | long lblockSize = GlobalOutSize - GlobalNowPos;
|
---|
227 | int blockSize;
|
---|
228 | if (lblockSize > kBlockSize)
|
---|
229 | blockSize = kBlockSize;
|
---|
230 | else
|
---|
231 | blockSize = (int)lblockSize;
|
---|
232 |
|
---|
233 | LzmaDecode(blockSize);
|
---|
234 |
|
---|
235 | if (uncompressed_size == 0) {
|
---|
236 | GlobalOutSize = GlobalNowPos;
|
---|
237 | } else {
|
---|
238 | GlobalNowPos += uncompressed_size;
|
---|
239 | }
|
---|
240 | }
|
---|
241 | }
|
---|
242 |
|
---|
243 | private void readHeader() throws IOException {
|
---|
244 | byte [] properties = new byte[5];
|
---|
245 |
|
---|
246 | if (5 != in.read(properties))
|
---|
247 | throw new LzmaException ("LZMA header corrupted : Properties error");
|
---|
248 |
|
---|
249 | GlobalOutSize = 0;
|
---|
250 | for (int ii = 0; ii < 8; ii++) {
|
---|
251 | int b = in.read();
|
---|
252 | if (b == -1)
|
---|
253 | throw new LzmaException ("LZMA header corrupted : Size error");
|
---|
254 | GlobalOutSize += ((long)b) << (ii * 8);
|
---|
255 | }
|
---|
256 |
|
---|
257 | if (GlobalOutSize == -1) GlobalOutSize=Long.MAX_VALUE;
|
---|
258 |
|
---|
259 | int prop0 = properties[0] & 0xFF;
|
---|
260 | if (prop0 >= (9*5*5)) {
|
---|
261 | throw new LzmaException ("LZMA header corrupted : Properties error");
|
---|
262 | }
|
---|
263 |
|
---|
264 | for (pb = 0; prop0 >= (9 * 5); pb++, prop0 -= (9 * 5))
|
---|
265 | ;
|
---|
266 | for (lp = 0; prop0 >= 9; lp++, prop0 -= 9)
|
---|
267 | ;
|
---|
268 | lc = prop0;
|
---|
269 |
|
---|
270 | int lzmaInternalSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)));
|
---|
271 |
|
---|
272 | probs = new int[lzmaInternalSize];
|
---|
273 |
|
---|
274 | dictionarySize = 0;
|
---|
275 | for (int i = 0; i < 4; i++)
|
---|
276 | dictionarySize += (properties[1 + i]&0xFF) << (i * 8);
|
---|
277 | dictionary = new byte[dictionarySize];
|
---|
278 | if (dictionary == null) {
|
---|
279 | throw new LzmaException ("LZMA : can't allocate");
|
---|
280 | }
|
---|
281 |
|
---|
282 | int numProbs = Literal + (LZMA_LIT_SIZE << (lc + lp));
|
---|
283 |
|
---|
284 | RangeDecoder = new CRangeDecoder(in);
|
---|
285 | dictionaryPos = 0;
|
---|
286 | GlobalPos = 0;
|
---|
287 | rep0 = rep1 = rep2 = rep3 = 1;
|
---|
288 | State = 0;
|
---|
289 | PreviousIsMatch = false;
|
---|
290 | RemainLen = 0;
|
---|
291 | dictionary[dictionarySize - 1] = 0;
|
---|
292 | for (int i = 0; i < numProbs; i++)
|
---|
293 | probs[i] = CRangeDecoder.kBitModelTotal >> 1;
|
---|
294 |
|
---|
295 | uncompressed_buffer = new byte [kBlockSize];
|
---|
296 | uncompressed_size = 0;
|
---|
297 | uncompressed_offset = 0;
|
---|
298 |
|
---|
299 | GlobalNowPos = 0;
|
---|
300 | }
|
---|
301 |
|
---|
302 | public int read (byte[] buf, int off, int len) throws IOException {
|
---|
303 | if (isClosed)
|
---|
304 | throw new IOException ("stream closed");
|
---|
305 |
|
---|
306 | if ((off | len | (off + len) | (buf.length - (off + len))) < 0) {
|
---|
307 | throw new IndexOutOfBoundsException();
|
---|
308 | }
|
---|
309 | if (len == 0)
|
---|
310 | return 0;
|
---|
311 |
|
---|
312 | if (uncompressed_offset == uncompressed_size)
|
---|
313 | fill_buffer();
|
---|
314 | if (uncompressed_offset == uncompressed_size)
|
---|
315 | return -1;
|
---|
316 |
|
---|
317 | int l = Math.min(len,uncompressed_size-uncompressed_offset);
|
---|
318 | System.arraycopy (uncompressed_buffer, uncompressed_offset, buf, off, l);
|
---|
319 | uncompressed_offset += l;
|
---|
320 | return l;
|
---|
321 | }
|
---|
322 |
|
---|
323 | public void close () throws IOException {
|
---|
324 | isClosed = true;
|
---|
325 | super.close ();
|
---|
326 | }
|
---|
327 | }
|
---|
328 |
|
---|