misc/libphysfs/lzma/Java/SevenZip/Compression/LZMA/Decoder.java
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     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 }