1 // LzmaDecoder.cs
2 
3 using System;
4 
5 namespace SevenZip.Compression.LZMA
6 {
7 	using RangeCoder;
8 
9 	public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
10 	{
11 		class LenDecoder
12 		{
13 			BitDecoder m_Choice = new BitDecoder();
14 			BitDecoder m_Choice2 = new BitDecoder();
15 			BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
16 			BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
17 			BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
18 			uint m_NumPosStates = 0;
19 
Create(uint numPosStates)20 			public void Create(uint numPosStates)
21 			{
22 				for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
23 				{
24 					m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
25 					m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
26 				}
27 				m_NumPosStates = numPosStates;
28 			}
29 
Init()30 			public void Init()
31 			{
32 				m_Choice.Init();
33 				for (uint posState = 0; posState < m_NumPosStates; posState++)
34 				{
35 					m_LowCoder[posState].Init();
36 					m_MidCoder[posState].Init();
37 				}
38 				m_Choice2.Init();
39 				m_HighCoder.Init();
40 			}
41 
Decode(RangeCoder.Decoder rangeDecoder, uint posState)42 			public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
43 			{
44 				if (m_Choice.Decode(rangeDecoder) == 0)
45 					return m_LowCoder[posState].Decode(rangeDecoder);
46 				else
47 				{
48 					uint symbol = Base.kNumLowLenSymbols;
49 					if (m_Choice2.Decode(rangeDecoder) == 0)
50 						symbol += m_MidCoder[posState].Decode(rangeDecoder);
51 					else
52 					{
53 						symbol += Base.kNumMidLenSymbols;
54 						symbol += m_HighCoder.Decode(rangeDecoder);
55 					}
56 					return symbol;
57 				}
58 			}
59 		}
60 
61 		class LiteralDecoder
62 		{
63 			struct Decoder2
64 			{
65 				BitDecoder[] m_Decoders;
CreateSevenZip.Compression.LZMA.Decoder.LiteralDecoder.Decoder266 				public void Create() { m_Decoders = new BitDecoder[0x300]; }
InitSevenZip.Compression.LZMA.Decoder.LiteralDecoder.Decoder267 				public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
68 
DecodeNormalSevenZip.Compression.LZMA.Decoder.LiteralDecoder.Decoder269 				public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
70 				{
71 					uint symbol = 1;
72 					do
73 						symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
74 					while (symbol < 0x100);
75 					return (byte)symbol;
76 				}
77 
DecodeWithMatchByteSevenZip.Compression.LZMA.Decoder.LiteralDecoder.Decoder278 				public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
79 				{
80 					uint symbol = 1;
81 					do
82 					{
83 						uint matchBit = (uint)(matchByte >> 7) & 1;
84 						matchByte <<= 1;
85 						uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
86 						symbol = (symbol << 1) | bit;
87 						if (matchBit != bit)
88 						{
89 							while (symbol < 0x100)
90 								symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
91 							break;
92 						}
93 					}
94 					while (symbol < 0x100);
95 					return (byte)symbol;
96 				}
97 			}
98 
99 			Decoder2[] m_Coders;
100 			int m_NumPrevBits;
101 			int m_NumPosBits;
102 			uint m_PosMask;
103 
Create(int numPosBits, int numPrevBits)104 			public void Create(int numPosBits, int numPrevBits)
105 			{
106 				if (m_Coders != null && m_NumPrevBits == numPrevBits &&
107 					m_NumPosBits == numPosBits)
108 					return;
109 				m_NumPosBits = numPosBits;
110 				m_PosMask = ((uint)1 << numPosBits) - 1;
111 				m_NumPrevBits = numPrevBits;
112 				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
113 				m_Coders = new Decoder2[numStates];
114 				for (uint i = 0; i < numStates; i++)
115 					m_Coders[i].Create();
116 			}
117 
Init()118 			public void Init()
119 			{
120 				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
121 				for (uint i = 0; i < numStates; i++)
122 					m_Coders[i].Init();
123 			}
124 
GetState(uint pos, byte prevByte)125 			uint GetState(uint pos, byte prevByte)
126 			{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
127 
DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)128 			public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
129 			{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
130 
DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)131 			public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
132 			{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
133 		};
134 
135 		LZ.OutWindow m_OutWindow = new LZ.OutWindow();
136 		RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
137 
138 		BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
139 		BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
140 		BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
141 		BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
142 		BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
143 		BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
144 
145 		BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
146 		BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
147 
148 		BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
149 
150 		LenDecoder m_LenDecoder = new LenDecoder();
151 		LenDecoder m_RepLenDecoder = new LenDecoder();
152 
153 		LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
154 
155 		uint m_DictionarySize;
156 		uint m_DictionarySizeCheck;
157 
158 		uint m_PosStateMask;
159 
Decoder()160 		public Decoder()
161 		{
162 			m_DictionarySize = 0xFFFFFFFF;
163 			for (int i = 0; i < Base.kNumLenToPosStates; i++)
164 				m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
165 		}
166 
SetDictionarySize(uint dictionarySize)167 		void SetDictionarySize(uint dictionarySize)
168 		{
169 			if (m_DictionarySize != dictionarySize)
170 			{
171 				m_DictionarySize = dictionarySize;
172 				m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
173 				uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
174 				m_OutWindow.Create(blockSize);
175 			}
176 		}
177 
SetLiteralProperties(int lp, int lc)178 		void SetLiteralProperties(int lp, int lc)
179 		{
180 			if (lp > 8)
181 				throw new InvalidParamException();
182 			if (lc > 8)
183 				throw new InvalidParamException();
184 			m_LiteralDecoder.Create(lp, lc);
185 		}
186 
SetPosBitsProperties(int pb)187 		void SetPosBitsProperties(int pb)
188 		{
189 			if (pb > Base.kNumPosStatesBitsMax)
190 				throw new InvalidParamException();
191 			uint numPosStates = (uint)1 << pb;
192 			m_LenDecoder.Create(numPosStates);
193 			m_RepLenDecoder.Create(numPosStates);
194 			m_PosStateMask = numPosStates - 1;
195 		}
196 
197 		bool _solid = false;
Init(System.IO.Stream inStream, System.IO.Stream outStream)198 		void Init(System.IO.Stream inStream, System.IO.Stream outStream)
199 		{
200 			m_RangeDecoder.Init(inStream);
201 			m_OutWindow.Init(outStream, _solid);
202 
203 			uint i;
204 			for (i = 0; i < Base.kNumStates; i++)
205 			{
206 				for (uint j = 0; j <= m_PosStateMask; j++)
207 				{
208 					uint index = (i << Base.kNumPosStatesBitsMax) + j;
209 					m_IsMatchDecoders[index].Init();
210 					m_IsRep0LongDecoders[index].Init();
211 				}
212 				m_IsRepDecoders[i].Init();
213 				m_IsRepG0Decoders[i].Init();
214 				m_IsRepG1Decoders[i].Init();
215 				m_IsRepG2Decoders[i].Init();
216 			}
217 
218 			m_LiteralDecoder.Init();
219 			for (i = 0; i < Base.kNumLenToPosStates; i++)
220 				m_PosSlotDecoder[i].Init();
221 			// m_PosSpecDecoder.Init();
222 			for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
223 				m_PosDecoders[i].Init();
224 
225 			m_LenDecoder.Init();
226 			m_RepLenDecoder.Init();
227 			m_PosAlignDecoder.Init();
228 		}
229 
Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress)230 		public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
231 			Int64 inSize, Int64 outSize, ICodeProgress progress)
232 		{
233 			Init(inStream, outStream);
234 
235 			Base.State state = new Base.State();
236 			state.Init();
237 			uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
238 
239 			UInt64 nowPos64 = 0;
240 			UInt64 outSize64 = (UInt64)outSize;
241 			if (nowPos64 < outSize64)
242 			{
243 				if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
244 					throw new DataErrorException();
245 				state.UpdateChar();
246 				byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
247 				m_OutWindow.PutByte(b);
248 				nowPos64++;
249 			}
250 			while (nowPos64 < outSize64)
251 			{
252 				// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
253 					// while(nowPos64 < next)
254 				{
255 					uint posState = (uint)nowPos64 & m_PosStateMask;
256 					if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
257 					{
258 						byte b;
259 						byte prevByte = m_OutWindow.GetByte(0);
260 						if (!state.IsCharState())
261 							b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
262 								(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
263 						else
264 							b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
265 						m_OutWindow.PutByte(b);
266 						state.UpdateChar();
267 						nowPos64++;
268 					}
269 					else
270 					{
271 						uint len;
272 						if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
273 						{
274 							if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
275 							{
276 								if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
277 								{
278 									state.UpdateShortRep();
279 									m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
280 									nowPos64++;
281 									continue;
282 								}
283 							}
284 							else
285 							{
286 								UInt32 distance;
287 								if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
288 								{
289 									distance = rep1;
290 								}
291 								else
292 								{
293 									if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
294 										distance = rep2;
295 									else
296 									{
297 										distance = rep3;
298 										rep3 = rep2;
299 									}
300 									rep2 = rep1;
301 								}
302 								rep1 = rep0;
303 								rep0 = distance;
304 							}
305 							len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
306 							state.UpdateRep();
307 						}
308 						else
309 						{
310 							rep3 = rep2;
311 							rep2 = rep1;
312 							rep1 = rep0;
313 							len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
314 							state.UpdateMatch();
315 							uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
316 							if (posSlot >= Base.kStartPosModelIndex)
317 							{
318 								int numDirectBits = (int)((posSlot >> 1) - 1);
319 								rep0 = ((2 | (posSlot & 1)) << numDirectBits);
320 								if (posSlot < Base.kEndPosModelIndex)
321 									rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
322 											rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
323 								else
324 								{
325 									rep0 += (m_RangeDecoder.DecodeDirectBits(
326 										numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
327 									rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
328 								}
329 							}
330 							else
331 								rep0 = posSlot;
332 						}
333 						if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
334 						{
335 							if (rep0 == 0xFFFFFFFF)
336 								break;
337 							throw new DataErrorException();
338 						}
339 						m_OutWindow.CopyBlock(rep0, len);
340 						nowPos64 += len;
341 					}
342 				}
343 			}
344 			m_OutWindow.Flush();
345 			m_OutWindow.ReleaseStream();
346 			m_RangeDecoder.ReleaseStream();
347 		}
348 
SetDecoderProperties(byte[] properties)349 		public void SetDecoderProperties(byte[] properties)
350 		{
351 			if (properties.Length < 5)
352 				throw new InvalidParamException();
353 			int lc = properties[0] % 9;
354 			int remainder = properties[0] / 9;
355 			int lp = remainder % 5;
356 			int pb = remainder / 5;
357 			if (pb > Base.kNumPosStatesBitsMax)
358 				throw new InvalidParamException();
359 			UInt32 dictionarySize = 0;
360 			for (int i = 0; i < 4; i++)
361 				dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
362 			SetDictionarySize(dictionarySize);
363 			SetLiteralProperties(lp, lc);
364 			SetPosBitsProperties(pb);
365 		}
366 
Train(System.IO.Stream stream)367 		public bool Train(System.IO.Stream stream)
368 		{
369 			_solid = true;
370 			return m_OutWindow.Train(stream);
371 		}
372 
373 		/*
374 		public override bool CanRead { get { return true; }}
375 		public override bool CanWrite { get { return true; }}
376 		public override bool CanSeek { get { return true; }}
377 		public override long Length { get { return 0; }}
378 		public override long Position
379 		{
380 			get { return 0;	}
381 			set { }
382 		}
383 		public override void Flush() { }
384 		public override int Read(byte[] buffer, int offset, int count)
385 		{
386 			return 0;
387 		}
388 		public override void Write(byte[] buffer, int offset, int count)
389 		{
390 		}
391 		public override long Seek(long offset, System.IO.SeekOrigin origin)
392 		{
393 			return 0;
394 		}
395 		public override void SetLength(long value) {}
396 		*/
397 	}
398 }
399