Home | History | Annotate | Download | only in LZMA
      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 
     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 
     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 
     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 
     57 			public void Init()
     58 			{
     59 				SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders);
     60 			}
     61 
     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 
     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 
     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 
    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 
    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 
    148 	public Decoder()
    149 	{
    150 		for (int i = 0; i < Base.kNumLenToPosStates; i++)
    151 			m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
    152 	}
    153 
    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 
    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 
    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 
    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 
    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