示例#1
0
        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();
        }