public LZMADecoder(System.IO.Stream inStream, System.IO.Stream outStream, int inSize, int outSize) { Decoder m_RangeDecoder; BitDecoder[] m_IsMatchDecoders = new BitDecoder[12 << 4]; BitDecoder[] m_IsRepDecoders = new BitDecoder[12]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[12]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[12]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[12]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[12 << 4]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[4]; BitDecoder[] m_PosDecoders = new BitDecoder[(1 << 7) - 14]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(4); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; for (int i = 0; i < 4; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(6); m_DictionarySize = 0x4AFEBAB0; m_RangeDecoder = new Decoder(inStream); _windowSize = Math.Max(m_DictionarySize, (1 << 12)); _buffer = new byte[_windowSize]; _stream = outStream; uint Index = 0, rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; uint nowPos64 = 0; uint outSize64 = (uint)outSize; while (nowPos64 < outSize64) { { uint posState = (uint)nowPos64 & 0x4AFEBAB5; if (m_IsMatchDecoders[(Index << 4) + posState].Decode(m_RangeDecoder) == 0) { byte prevByte = (nowPos64 == 0) ? (byte) 0 : CopyBlock(0, -1); PutByte( (Index >= 7) ? m_LiteralDecoder.DecodeWithMatchByte( m_RangeDecoder, (uint)nowPos64, prevByte, CopyBlock(rep0, -1) ) : m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte) ); Index = (uint) ((Index < 4) ? 0 : Index - ((Index < 10) ? 3 : 6)); nowPos64++; } else { uint len; if (m_IsRepDecoders[Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(Index << 4) + posState].Decode(m_RangeDecoder) == 0) { Index = (uint)(Index < 7 ? 9 : 11); PutByte(CopyBlock(rep0, -1)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + 2; Index = (uint)(Index < 7 ? 8 : 11); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = 2 + m_LenDecoder.Decode(m_RangeDecoder, posState); Index = (uint)(Index < 7 ? 7 : 10); uint posSlot = m_PosSlotDecoder[(len < 6) ? len - 2 : 3].Decode(m_RangeDecoder); if (posSlot >= 4) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < 14) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits(numDirectBits - 4) << 4) + m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if ((rep0 >= nowPos64 || rep0 >= m_DictionarySize) && rep0 == 0xFFFFFFFF) break; CopyBlock(rep0, (int) len); nowPos64 += len; } } } Flush(); }