1370b324cSopenharmony_cipackage SevenZip.Compression.LZMA;
2370b324cSopenharmony_ci
3370b324cSopenharmony_ciimport SevenZip.Compression.RangeCoder.BitTreeDecoder;
4370b324cSopenharmony_ciimport SevenZip.Compression.LZMA.Base;
5370b324cSopenharmony_ciimport SevenZip.Compression.LZ.OutWindow;
6370b324cSopenharmony_ciimport java.io.IOException;
7370b324cSopenharmony_ci
8370b324cSopenharmony_cipublic class Decoder
9370b324cSopenharmony_ci{
10370b324cSopenharmony_ci	class LenDecoder
11370b324cSopenharmony_ci	{
12370b324cSopenharmony_ci		short[] m_Choice = new short[2];
13370b324cSopenharmony_ci		BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
14370b324cSopenharmony_ci		BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
15370b324cSopenharmony_ci		BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
16370b324cSopenharmony_ci		int m_NumPosStates = 0;
17370b324cSopenharmony_ci
18370b324cSopenharmony_ci		public void Create(int numPosStates)
19370b324cSopenharmony_ci		{
20370b324cSopenharmony_ci			for (; m_NumPosStates < numPosStates; m_NumPosStates++)
21370b324cSopenharmony_ci			{
22370b324cSopenharmony_ci				m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits);
23370b324cSopenharmony_ci				m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits);
24370b324cSopenharmony_ci			}
25370b324cSopenharmony_ci		}
26370b324cSopenharmony_ci
27370b324cSopenharmony_ci		public void Init()
28370b324cSopenharmony_ci		{
29370b324cSopenharmony_ci			SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice);
30370b324cSopenharmony_ci			for (int posState = 0; posState < m_NumPosStates; posState++)
31370b324cSopenharmony_ci			{
32370b324cSopenharmony_ci				m_LowCoder[posState].Init();
33370b324cSopenharmony_ci				m_MidCoder[posState].Init();
34370b324cSopenharmony_ci			}
35370b324cSopenharmony_ci			m_HighCoder.Init();
36370b324cSopenharmony_ci		}
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci		public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException
39370b324cSopenharmony_ci		{
40370b324cSopenharmony_ci			if (rangeDecoder.DecodeBit(m_Choice, 0) == 0)
41370b324cSopenharmony_ci				return m_LowCoder[posState].Decode(rangeDecoder);
42370b324cSopenharmony_ci			int symbol = Base.kNumLowLenSymbols;
43370b324cSopenharmony_ci			if (rangeDecoder.DecodeBit(m_Choice, 1) == 0)
44370b324cSopenharmony_ci				symbol += m_MidCoder[posState].Decode(rangeDecoder);
45370b324cSopenharmony_ci			else
46370b324cSopenharmony_ci				symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder);
47370b324cSopenharmony_ci			return symbol;
48370b324cSopenharmony_ci		}
49370b324cSopenharmony_ci	}
50370b324cSopenharmony_ci
51370b324cSopenharmony_ci	class LiteralDecoder
52370b324cSopenharmony_ci	{
53370b324cSopenharmony_ci		class Decoder2
54370b324cSopenharmony_ci		{
55370b324cSopenharmony_ci			short[] m_Decoders = new short[0x300];
56370b324cSopenharmony_ci
57370b324cSopenharmony_ci			public void Init()
58370b324cSopenharmony_ci			{
59370b324cSopenharmony_ci				SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders);
60370b324cSopenharmony_ci			}
61370b324cSopenharmony_ci
62370b324cSopenharmony_ci			public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException
63370b324cSopenharmony_ci			{
64370b324cSopenharmony_ci				int symbol = 1;
65370b324cSopenharmony_ci				do
66370b324cSopenharmony_ci					symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
67370b324cSopenharmony_ci				while (symbol < 0x100);
68370b324cSopenharmony_ci				return (byte)symbol;
69370b324cSopenharmony_ci			}
70370b324cSopenharmony_ci
71370b324cSopenharmony_ci			public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException
72370b324cSopenharmony_ci			{
73370b324cSopenharmony_ci				int symbol = 1;
74370b324cSopenharmony_ci				do
75370b324cSopenharmony_ci				{
76370b324cSopenharmony_ci					int matchBit = (matchByte >> 7) & 1;
77370b324cSopenharmony_ci					matchByte <<= 1;
78370b324cSopenharmony_ci					int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol);
79370b324cSopenharmony_ci					symbol = (symbol << 1) | bit;
80370b324cSopenharmony_ci					if (matchBit != bit)
81370b324cSopenharmony_ci					{
82370b324cSopenharmony_ci						while (symbol < 0x100)
83370b324cSopenharmony_ci							symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
84370b324cSopenharmony_ci						break;
85370b324cSopenharmony_ci					}
86370b324cSopenharmony_ci				}
87370b324cSopenharmony_ci				while (symbol < 0x100);
88370b324cSopenharmony_ci				return (byte)symbol;
89370b324cSopenharmony_ci			}
90370b324cSopenharmony_ci		}
91370b324cSopenharmony_ci
92370b324cSopenharmony_ci		Decoder2[] m_Coders;
93370b324cSopenharmony_ci		int m_NumPrevBits;
94370b324cSopenharmony_ci		int m_NumPosBits;
95370b324cSopenharmony_ci		int m_PosMask;
96370b324cSopenharmony_ci
97370b324cSopenharmony_ci		public void Create(int numPosBits, int numPrevBits)
98370b324cSopenharmony_ci		{
99370b324cSopenharmony_ci			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
100370b324cSopenharmony_ci				return;
101370b324cSopenharmony_ci			m_NumPosBits = numPosBits;
102370b324cSopenharmony_ci			m_PosMask = (1 << numPosBits) - 1;
103370b324cSopenharmony_ci			m_NumPrevBits = numPrevBits;
104370b324cSopenharmony_ci			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
105370b324cSopenharmony_ci			m_Coders = new Decoder2[numStates];
106370b324cSopenharmony_ci			for (int i = 0; i < numStates; i++)
107370b324cSopenharmony_ci				m_Coders[i] = new Decoder2();
108370b324cSopenharmony_ci		}
109370b324cSopenharmony_ci
110370b324cSopenharmony_ci		public void Init()
111370b324cSopenharmony_ci		{
112370b324cSopenharmony_ci			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
113370b324cSopenharmony_ci			for (int i = 0; i < numStates; i++)
114370b324cSopenharmony_ci				m_Coders[i].Init();
115370b324cSopenharmony_ci		}
116370b324cSopenharmony_ci
117370b324cSopenharmony_ci		Decoder2 GetDecoder(int pos, byte prevByte)
118370b324cSopenharmony_ci		{
119370b324cSopenharmony_ci			return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))];
120370b324cSopenharmony_ci		}
121370b324cSopenharmony_ci	}
122370b324cSopenharmony_ci
123370b324cSopenharmony_ci	OutWindow m_OutWindow = new OutWindow();
124370b324cSopenharmony_ci	SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();
125370b324cSopenharmony_ci
126370b324cSopenharmony_ci	short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
127370b324cSopenharmony_ci	short[] m_IsRepDecoders = new short[Base.kNumStates];
128370b324cSopenharmony_ci	short[] m_IsRepG0Decoders = new short[Base.kNumStates];
129370b324cSopenharmony_ci	short[] m_IsRepG1Decoders = new short[Base.kNumStates];
130370b324cSopenharmony_ci	short[] m_IsRepG2Decoders = new short[Base.kNumStates];
131370b324cSopenharmony_ci	short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
132370b324cSopenharmony_ci
133370b324cSopenharmony_ci	BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
134370b324cSopenharmony_ci	short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex];
135370b324cSopenharmony_ci
136370b324cSopenharmony_ci	BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
137370b324cSopenharmony_ci
138370b324cSopenharmony_ci	LenDecoder m_LenDecoder = new LenDecoder();
139370b324cSopenharmony_ci	LenDecoder m_RepLenDecoder = new LenDecoder();
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci	LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
142370b324cSopenharmony_ci
143370b324cSopenharmony_ci	int m_DictionarySize = -1;
144370b324cSopenharmony_ci	int m_DictionarySizeCheck =  -1;
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci	int m_PosStateMask;
147370b324cSopenharmony_ci
148370b324cSopenharmony_ci	public Decoder()
149370b324cSopenharmony_ci	{
150370b324cSopenharmony_ci		for (int i = 0; i < Base.kNumLenToPosStates; i++)
151370b324cSopenharmony_ci			m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
152370b324cSopenharmony_ci	}
153370b324cSopenharmony_ci
154370b324cSopenharmony_ci	boolean SetDictionarySize(int dictionarySize)
155370b324cSopenharmony_ci	{
156370b324cSopenharmony_ci		if (dictionarySize < 0)
157370b324cSopenharmony_ci			return false;
158370b324cSopenharmony_ci		if (m_DictionarySize != dictionarySize)
159370b324cSopenharmony_ci		{
160370b324cSopenharmony_ci			m_DictionarySize = dictionarySize;
161370b324cSopenharmony_ci			m_DictionarySizeCheck = Math.max(m_DictionarySize, 1);
162370b324cSopenharmony_ci			m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12)));
163370b324cSopenharmony_ci		}
164370b324cSopenharmony_ci		return true;
165370b324cSopenharmony_ci	}
166370b324cSopenharmony_ci
167370b324cSopenharmony_ci	boolean SetLcLpPb(int lc, int lp, int pb)
168370b324cSopenharmony_ci	{
169370b324cSopenharmony_ci		if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax)
170370b324cSopenharmony_ci			return false;
171370b324cSopenharmony_ci		m_LiteralDecoder.Create(lp, lc);
172370b324cSopenharmony_ci		int numPosStates = 1 << pb;
173370b324cSopenharmony_ci		m_LenDecoder.Create(numPosStates);
174370b324cSopenharmony_ci		m_RepLenDecoder.Create(numPosStates);
175370b324cSopenharmony_ci		m_PosStateMask = numPosStates - 1;
176370b324cSopenharmony_ci		return true;
177370b324cSopenharmony_ci	}
178370b324cSopenharmony_ci
179370b324cSopenharmony_ci	void Init() throws IOException
180370b324cSopenharmony_ci	{
181370b324cSopenharmony_ci		m_OutWindow.Init(false);
182370b324cSopenharmony_ci
183370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders);
184370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders);
185370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders);
186370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders);
187370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders);
188370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders);
189370b324cSopenharmony_ci		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders);
190370b324cSopenharmony_ci
191370b324cSopenharmony_ci		m_LiteralDecoder.Init();
192370b324cSopenharmony_ci		int i;
193370b324cSopenharmony_ci		for (i = 0; i < Base.kNumLenToPosStates; i++)
194370b324cSopenharmony_ci			m_PosSlotDecoder[i].Init();
195370b324cSopenharmony_ci		m_LenDecoder.Init();
196370b324cSopenharmony_ci		m_RepLenDecoder.Init();
197370b324cSopenharmony_ci		m_PosAlignDecoder.Init();
198370b324cSopenharmony_ci		m_RangeDecoder.Init();
199370b324cSopenharmony_ci	}
200370b324cSopenharmony_ci
201370b324cSopenharmony_ci	public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream,
202370b324cSopenharmony_ci			long outSize) throws IOException
203370b324cSopenharmony_ci	{
204370b324cSopenharmony_ci		m_RangeDecoder.SetStream(inStream);
205370b324cSopenharmony_ci		m_OutWindow.SetStream(outStream);
206370b324cSopenharmony_ci		Init();
207370b324cSopenharmony_ci
208370b324cSopenharmony_ci		int state = Base.StateInit();
209370b324cSopenharmony_ci		int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
210370b324cSopenharmony_ci
211370b324cSopenharmony_ci		long nowPos64 = 0;
212370b324cSopenharmony_ci		byte prevByte = 0;
213370b324cSopenharmony_ci		while (outSize < 0 || nowPos64 < outSize)
214370b324cSopenharmony_ci		{
215370b324cSopenharmony_ci			int posState = (int)nowPos64 & m_PosStateMask;
216370b324cSopenharmony_ci			if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
217370b324cSopenharmony_ci			{
218370b324cSopenharmony_ci				LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte);
219370b324cSopenharmony_ci				if (!Base.StateIsCharState(state))
220370b324cSopenharmony_ci					prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0));
221370b324cSopenharmony_ci				else
222370b324cSopenharmony_ci					prevByte = decoder2.DecodeNormal(m_RangeDecoder);
223370b324cSopenharmony_ci				m_OutWindow.PutByte(prevByte);
224370b324cSopenharmony_ci				state = Base.StateUpdateChar(state);
225370b324cSopenharmony_ci				nowPos64++;
226370b324cSopenharmony_ci			}
227370b324cSopenharmony_ci			else
228370b324cSopenharmony_ci			{
229370b324cSopenharmony_ci				int len;
230370b324cSopenharmony_ci				if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1)
231370b324cSopenharmony_ci				{
232370b324cSopenharmony_ci					len = 0;
233370b324cSopenharmony_ci					if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0)
234370b324cSopenharmony_ci					{
235370b324cSopenharmony_ci						if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
236370b324cSopenharmony_ci						{
237370b324cSopenharmony_ci							state = Base.StateUpdateShortRep(state);
238370b324cSopenharmony_ci							len = 1;
239370b324cSopenharmony_ci						}
240370b324cSopenharmony_ci					}
241370b324cSopenharmony_ci					else
242370b324cSopenharmony_ci					{
243370b324cSopenharmony_ci						int distance;
244370b324cSopenharmony_ci						if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0)
245370b324cSopenharmony_ci							distance = rep1;
246370b324cSopenharmony_ci						else
247370b324cSopenharmony_ci						{
248370b324cSopenharmony_ci							if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0)
249370b324cSopenharmony_ci								distance = rep2;
250370b324cSopenharmony_ci							else
251370b324cSopenharmony_ci							{
252370b324cSopenharmony_ci								distance = rep3;
253370b324cSopenharmony_ci								rep3 = rep2;
254370b324cSopenharmony_ci							}
255370b324cSopenharmony_ci							rep2 = rep1;
256370b324cSopenharmony_ci						}
257370b324cSopenharmony_ci						rep1 = rep0;
258370b324cSopenharmony_ci						rep0 = distance;
259370b324cSopenharmony_ci					}
260370b324cSopenharmony_ci					if (len == 0)
261370b324cSopenharmony_ci					{
262370b324cSopenharmony_ci						len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
263370b324cSopenharmony_ci						state = Base.StateUpdateRep(state);
264370b324cSopenharmony_ci					}
265370b324cSopenharmony_ci				}
266370b324cSopenharmony_ci				else
267370b324cSopenharmony_ci				{
268370b324cSopenharmony_ci					rep3 = rep2;
269370b324cSopenharmony_ci					rep2 = rep1;
270370b324cSopenharmony_ci					rep1 = rep0;
271370b324cSopenharmony_ci					len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
272370b324cSopenharmony_ci					state = Base.StateUpdateMatch(state);
273370b324cSopenharmony_ci					int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
274370b324cSopenharmony_ci					if (posSlot >= Base.kStartPosModelIndex)
275370b324cSopenharmony_ci					{
276370b324cSopenharmony_ci						int numDirectBits = (posSlot >> 1) - 1;
277370b324cSopenharmony_ci						rep0 = ((2 | (posSlot & 1)) << numDirectBits);
278370b324cSopenharmony_ci						if (posSlot < Base.kEndPosModelIndex)
279370b324cSopenharmony_ci							rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
280370b324cSopenharmony_ci									rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
281370b324cSopenharmony_ci						else
282370b324cSopenharmony_ci						{
283370b324cSopenharmony_ci							rep0 += (m_RangeDecoder.DecodeDirectBits(
284370b324cSopenharmony_ci									numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
285370b324cSopenharmony_ci							rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
286370b324cSopenharmony_ci							if (rep0 < 0)
287370b324cSopenharmony_ci							{
288370b324cSopenharmony_ci								if (rep0 == -1)
289370b324cSopenharmony_ci									break;
290370b324cSopenharmony_ci								return false;
291370b324cSopenharmony_ci							}
292370b324cSopenharmony_ci						}
293370b324cSopenharmony_ci					}
294370b324cSopenharmony_ci					else
295370b324cSopenharmony_ci						rep0 = posSlot;
296370b324cSopenharmony_ci				}
297370b324cSopenharmony_ci				if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck)
298370b324cSopenharmony_ci				{
299370b324cSopenharmony_ci					// m_OutWindow.Flush();
300370b324cSopenharmony_ci					return false;
301370b324cSopenharmony_ci				}
302370b324cSopenharmony_ci				m_OutWindow.CopyBlock(rep0, len);
303370b324cSopenharmony_ci				nowPos64 += len;
304370b324cSopenharmony_ci				prevByte = m_OutWindow.GetByte(0);
305370b324cSopenharmony_ci			}
306370b324cSopenharmony_ci		}
307370b324cSopenharmony_ci		m_OutWindow.Flush();
308370b324cSopenharmony_ci		m_OutWindow.ReleaseStream();
309370b324cSopenharmony_ci		m_RangeDecoder.ReleaseStream();
310370b324cSopenharmony_ci		return true;
311370b324cSopenharmony_ci	}
312370b324cSopenharmony_ci
313370b324cSopenharmony_ci	public boolean SetDecoderProperties(byte[] properties)
314370b324cSopenharmony_ci	{
315370b324cSopenharmony_ci		if (properties.length < 5)
316370b324cSopenharmony_ci			return false;
317370b324cSopenharmony_ci		int val = properties[0] & 0xFF;
318370b324cSopenharmony_ci		int lc = val % 9;
319370b324cSopenharmony_ci		int remainder = val / 9;
320370b324cSopenharmony_ci		int lp = remainder % 5;
321370b324cSopenharmony_ci		int pb = remainder / 5;
322370b324cSopenharmony_ci		int dictionarySize = 0;
323370b324cSopenharmony_ci		for (int i = 0; i < 4; i++)
324370b324cSopenharmony_ci			dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8);
325370b324cSopenharmony_ci		if (!SetLcLpPb(lc, lp, pb))
326370b324cSopenharmony_ci			return false;
327370b324cSopenharmony_ci		return SetDictionarySize(dictionarySize);
328370b324cSopenharmony_ci	}
329370b324cSopenharmony_ci}
330