source: other-projects/trunk/7z-ant/src/LZMA/LzmaInputStream.java@ 17387

Last change on this file since 17387 was 17387, checked in by oranfry, 16 years ago

Modified ant task which works with the updated 7zip API

File size: 9.1 KB
Line 
1package LZMA;
2
3import java.io.InputStream;
4import java.io.IOException;
5
6public 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
Note: See TracBrowser for help on using the repository browser.