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