1// LzmaDecoder.cs
2
3using System;
4
5namespace 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
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
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
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;
66				public void Create() { m_Decoders = new BitDecoder[0x300]; }
67				public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
68
69				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
78				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
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
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
125			uint GetState(uint pos, byte prevByte)
126			{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
127
128			public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
129			{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
130
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
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
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
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
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;
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
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
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
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