1 package SevenZip.Compression.LZMA;
2 
3 import SevenZip.Compression.RangeCoder.BitTreeDecoder;
4 import SevenZip.Compression.LZMA.Base;
5 import SevenZip.Compression.LZ.OutWindow;
6 import java.io.IOException;
7 
8 public class Decoder
9 {
10 	class LenDecoder
11 	{
12 		short[] m_Choice = new short[2];
13 		BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
14 		BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
15 		BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
16 		int m_NumPosStates = 0;
17 
Create(int numPosStates)18 		public void Create(int numPosStates)
19 		{
20 			for (; m_NumPosStates < numPosStates; m_NumPosStates++)
21 			{
22 				m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits);
23 				m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits);
24 			}
25 		}
26 
Init()27 		public void Init()
28 		{
29 			SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice);
30 			for (int posState = 0; posState < m_NumPosStates; posState++)
31 			{
32 				m_LowCoder[posState].Init();
33 				m_MidCoder[posState].Init();
34 			}
35 			m_HighCoder.Init();
36 		}
37 
Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState)38 		public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException
39 		{
40 			if (rangeDecoder.DecodeBit(m_Choice, 0) == 0)
41 				return m_LowCoder[posState].Decode(rangeDecoder);
42 			int symbol = Base.kNumLowLenSymbols;
43 			if (rangeDecoder.DecodeBit(m_Choice, 1) == 0)
44 				symbol += m_MidCoder[posState].Decode(rangeDecoder);
45 			else
46 				symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder);
47 			return symbol;
48 		}
49 	}
50 
51 	class LiteralDecoder
52 	{
53 		class Decoder2
54 		{
55 			short[] m_Decoders = new short[0x300];
56 
Init()57 			public void Init()
58 			{
59 				SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders);
60 			}
61 
DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder)62 			public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException
63 			{
64 				int symbol = 1;
65 				do
66 					symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
67 				while (symbol < 0x100);
68 				return (byte)symbol;
69 			}
70 
DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte)71 			public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException
72 			{
73 				int symbol = 1;
74 				do
75 				{
76 					int matchBit = (matchByte >> 7) & 1;
77 					matchByte <<= 1;
78 					int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol);
79 					symbol = (symbol << 1) | bit;
80 					if (matchBit != bit)
81 					{
82 						while (symbol < 0x100)
83 							symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
84 						break;
85 					}
86 				}
87 				while (symbol < 0x100);
88 				return (byte)symbol;
89 			}
90 		}
91 
92 		Decoder2[] m_Coders;
93 		int m_NumPrevBits;
94 		int m_NumPosBits;
95 		int m_PosMask;
96 
Create(int numPosBits, int numPrevBits)97 		public void Create(int numPosBits, int numPrevBits)
98 		{
99 			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
100 				return;
101 			m_NumPosBits = numPosBits;
102 			m_PosMask = (1 << numPosBits) - 1;
103 			m_NumPrevBits = numPrevBits;
104 			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
105 			m_Coders = new Decoder2[numStates];
106 			for (int i = 0; i < numStates; i++)
107 				m_Coders[i] = new Decoder2();
108 		}
109 
Init()110 		public void Init()
111 		{
112 			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
113 			for (int i = 0; i < numStates; i++)
114 				m_Coders[i].Init();
115 		}
116 
GetDecoder(int pos, byte prevByte)117 		Decoder2 GetDecoder(int pos, byte prevByte)
118 		{
119 			return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))];
120 		}
121 	}
122 
123 	OutWindow m_OutWindow = new OutWindow();
124 	SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();
125 
126 	short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
127 	short[] m_IsRepDecoders = new short[Base.kNumStates];
128 	short[] m_IsRepG0Decoders = new short[Base.kNumStates];
129 	short[] m_IsRepG1Decoders = new short[Base.kNumStates];
130 	short[] m_IsRepG2Decoders = new short[Base.kNumStates];
131 	short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
132 
133 	BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
134 	short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex];
135 
136 	BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
137 
138 	LenDecoder m_LenDecoder = new LenDecoder();
139 	LenDecoder m_RepLenDecoder = new LenDecoder();
140 
141 	LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
142 
143 	int m_DictionarySize = -1;
144 	int m_DictionarySizeCheck =  -1;
145 
146 	int m_PosStateMask;
147 
Decoder()148 	public Decoder()
149 	{
150 		for (int i = 0; i < Base.kNumLenToPosStates; i++)
151 			m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
152 	}
153 
SetDictionarySize(int dictionarySize)154 	boolean SetDictionarySize(int dictionarySize)
155 	{
156 		if (dictionarySize < 0)
157 			return false;
158 		if (m_DictionarySize != dictionarySize)
159 		{
160 			m_DictionarySize = dictionarySize;
161 			m_DictionarySizeCheck = Math.max(m_DictionarySize, 1);
162 			m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12)));
163 		}
164 		return true;
165 	}
166 
SetLcLpPb(int lc, int lp, int pb)167 	boolean SetLcLpPb(int lc, int lp, int pb)
168 	{
169 		if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax)
170 			return false;
171 		m_LiteralDecoder.Create(lp, lc);
172 		int numPosStates = 1 << pb;
173 		m_LenDecoder.Create(numPosStates);
174 		m_RepLenDecoder.Create(numPosStates);
175 		m_PosStateMask = numPosStates - 1;
176 		return true;
177 	}
178 
Init()179 	void Init() throws IOException
180 	{
181 		m_OutWindow.Init(false);
182 
183 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders);
184 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders);
185 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders);
186 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders);
187 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders);
188 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders);
189 		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders);
190 
191 		m_LiteralDecoder.Init();
192 		int i;
193 		for (i = 0; i < Base.kNumLenToPosStates; i++)
194 			m_PosSlotDecoder[i].Init();
195 		m_LenDecoder.Init();
196 		m_RepLenDecoder.Init();
197 		m_PosAlignDecoder.Init();
198 		m_RangeDecoder.Init();
199 	}
200 
Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize)201 	public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream,
202 			long outSize) throws IOException
203 	{
204 		m_RangeDecoder.SetStream(inStream);
205 		m_OutWindow.SetStream(outStream);
206 		Init();
207 
208 		int state = Base.StateInit();
209 		int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
210 
211 		long nowPos64 = 0;
212 		byte prevByte = 0;
213 		while (outSize < 0 || nowPos64 < outSize)
214 		{
215 			int posState = (int)nowPos64 & m_PosStateMask;
216 			if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
217 			{
218 				LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte);
219 				if (!Base.StateIsCharState(state))
220 					prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0));
221 				else
222 					prevByte = decoder2.DecodeNormal(m_RangeDecoder);
223 				m_OutWindow.PutByte(prevByte);
224 				state = Base.StateUpdateChar(state);
225 				nowPos64++;
226 			}
227 			else
228 			{
229 				int len;
230 				if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1)
231 				{
232 					len = 0;
233 					if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0)
234 					{
235 						if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
236 						{
237 							state = Base.StateUpdateShortRep(state);
238 							len = 1;
239 						}
240 					}
241 					else
242 					{
243 						int distance;
244 						if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0)
245 							distance = rep1;
246 						else
247 						{
248 							if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0)
249 								distance = rep2;
250 							else
251 							{
252 								distance = rep3;
253 								rep3 = rep2;
254 							}
255 							rep2 = rep1;
256 						}
257 						rep1 = rep0;
258 						rep0 = distance;
259 					}
260 					if (len == 0)
261 					{
262 						len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
263 						state = Base.StateUpdateRep(state);
264 					}
265 				}
266 				else
267 				{
268 					rep3 = rep2;
269 					rep2 = rep1;
270 					rep1 = rep0;
271 					len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
272 					state = Base.StateUpdateMatch(state);
273 					int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
274 					if (posSlot >= Base.kStartPosModelIndex)
275 					{
276 						int numDirectBits = (posSlot >> 1) - 1;
277 						rep0 = ((2 | (posSlot & 1)) << numDirectBits);
278 						if (posSlot < Base.kEndPosModelIndex)
279 							rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
280 									rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
281 						else
282 						{
283 							rep0 += (m_RangeDecoder.DecodeDirectBits(
284 									numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
285 							rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
286 							if (rep0 < 0)
287 							{
288 								if (rep0 == -1)
289 									break;
290 								return false;
291 							}
292 						}
293 					}
294 					else
295 						rep0 = posSlot;
296 				}
297 				if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck)
298 				{
299 					// m_OutWindow.Flush();
300 					return false;
301 				}
302 				m_OutWindow.CopyBlock(rep0, len);
303 				nowPos64 += len;
304 				prevByte = m_OutWindow.GetByte(0);
305 			}
306 		}
307 		m_OutWindow.Flush();
308 		m_OutWindow.ReleaseStream();
309 		m_RangeDecoder.ReleaseStream();
310 		return true;
311 	}
312 
SetDecoderProperties(byte[] properties)313 	public boolean SetDecoderProperties(byte[] properties)
314 	{
315 		if (properties.length < 5)
316 			return false;
317 		int val = properties[0] & 0xFF;
318 		int lc = val % 9;
319 		int remainder = val / 9;
320 		int lp = remainder % 5;
321 		int pb = remainder / 5;
322 		int dictionarySize = 0;
323 		for (int i = 0; i < 4; i++)
324 			dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8);
325 		if (!SetLcLpPb(lc, lp, pb))
326 			return false;
327 		return SetDictionarySize(dictionarySize);
328 	}
329 }
330