Beispiel #1
0
        private bool ReadFilter(BitInput Inp, UnpackFilter Filter)
        {
            if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 16)
            {
                if (!UnpReadBuf())
                {
                    return(false);
                }
            }

            Filter.BlockStart  = ReadFilterData(Inp);
            Filter.BlockLength = ReadFilterData(Inp);
            if (Filter.BlockLength > MAX_FILTER_BLOCK_SIZE)
            {
                Filter.BlockLength = 0;
            }

            Filter.Type = (byte)(Inp.fgetbits() >> 13);
            Inp.faddbits(3);

            if (Filter.Type == FILTER_DELTA)
            {
                Filter.Channels = (byte)((Inp.fgetbits() >> 11) + 1);
                Inp.faddbits(5);
            }

            return(true);
        }
Beispiel #2
0
        private bool ReadBlockHeader(BitInput Inp, ref UnpackBlockHeader Header)
        {
            Header.HeaderSize = 0;

            if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 7)
            {
                if (!UnpReadBuf())
                {
                    return(false);
                }
            }

            Inp.faddbits((uint)((8 - Inp.InBit) & 7));

            byte BlockFlags = (byte)(Inp.fgetbits() >> 8);

            Inp.faddbits(8);
            uint ByteCount = (uint)(((BlockFlags >> 3) & 3) + 1); // Block size byte count.

            if (ByteCount == 4)
            {
                return(false);
            }

            Header.HeaderSize = (int)(2 + ByteCount);

            Header.BlockBitSize = (BlockFlags & 7) + 1;

            byte SavedCheckSum = (byte)(Inp.fgetbits() >> 8);

            Inp.faddbits(8);

            int BlockSize = 0;

            for (uint I = 0; I < ByteCount; I++)
            {
                BlockSize += (int)((Inp.fgetbits() >> 8) << (int)(I * 8));
                Inp.addbits(8);
            }

            Header.BlockSize = BlockSize;
            byte CheckSum = (byte)(0x5a ^ BlockFlags ^ BlockSize ^ (BlockSize >> 8) ^ (BlockSize >> 16));

            if (CheckSum != SavedCheckSum)
            {
                return(false);
            }

            Header.BlockStart = Inp.InAddr;
            ReadBorder        = Math.Min(ReadBorder, Header.BlockStart + Header.BlockSize - 1);

            Header.LastBlockInFile = (BlockFlags & 0x40) != 0;
            Header.TablePresent    = (BlockFlags & 0x80) != 0;
            return(true);
        }
Beispiel #3
0
        private uint ReadFilterData(BitInput Inp)
        {
            uint ByteCount = (Inp.fgetbits() >> 14) + 1;

            Inp.addbits(2);

            uint Data = 0;

            for (uint I = 0; I < ByteCount; I++)
            {
                Data += (Inp.fgetbits() >> 8) << (int)(I * 8);
                Inp.addbits(8);
            }
            return(Data);
        }
Beispiel #4
0
        private uint DecodeNumber(BitInput Inp, DecodeTable Dec)
        {
            // Left aligned 15 bit length raw bit field.
            uint BitField = Inp.getbits() & 0xfffe;

            if (BitField < Dec.DecodeLen[Dec.QuickBits])
            {
                uint Code = BitField >> (int)(16 - Dec.QuickBits);
                Inp.addbits(Dec.QuickLen[Code]);
                return(Dec.QuickNum[Code]);
            }

            // Detect the real bit length for current code.
            uint Bits = 15;

            for (uint I = Dec.QuickBits + 1; I < 15; I++)
            {
                if (BitField < Dec.DecodeLen[I])
                {
                    Bits = I;
                    break;
                }
            }

            Inp.addbits(Bits);

            // Calculate the distance from the start code for current bit length.
            uint Dist = BitField - Dec.DecodeLen[Bits - 1];

            // Start codes are left aligned, but we need the normal right aligned
            // number. So we shift the distance to the right.
            Dist >>= (int)(16 - Bits);

            // Now we can calculate the position in the code list. It is the sum
            // of first position for current bit length and right aligned distance
            // between our bit field and start code for current bit length.
            uint Pos = Dec.DecodePos[Bits] + Dist;

            // Out of bounds safety check required for damaged archives.
            if (Pos >= Dec.MaxNum)
            {
                Pos = 0;
            }

            // Convert the position in the code list to position in alphabet
            // and return it.
            return(Dec.DecodeNum[Pos]);
        }
Beispiel #5
0
        private uint SlotToLength(BitInput Inp, uint Slot)
        {
            uint LBits, Length = 2;

            if (Slot < 8)
            {
                LBits   = 0;
                Length += Slot;
            }
            else
            {
                LBits   = Slot / 4 - 1;
                Length += (4 | (Slot & 3)) << (int)LBits;
            }

            if (LBits > 0)
            {
                Length += Inp.getbits() >> (int)(16 - LBits);
                Inp.addbits(LBits);
            }
            return(Length);
        }
Beispiel #6
0
        private bool ReadTables(BitInput Inp, ref UnpackBlockHeader Header, ref UnpackBlockTables Tables)
        {
            if (!Header.TablePresent)
            {
                return(true);
            }

            if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 25)
            {
                if (!UnpReadBuf())
                {
                    return(false);
                }
            }

            byte[] BitLength = new byte[BC];
            for (uint I = 0; I < BC; I++)
            {
                uint Length = (byte)(Inp.fgetbits() >> 12);
                Inp.faddbits(4);
                if (Length == 15)
                {
                    uint ZeroCount = (byte)(Inp.fgetbits() >> 12);
                    Inp.faddbits(4);
                    if (ZeroCount == 0)
                    {
                        BitLength[I] = 15;
                    }
                    else
                    {
                        ZeroCount += 2;
                        while (ZeroCount-- > 0 && I < BitLength.Length)
                        {
                            BitLength[I++] = 0;
                        }

                        I--;
                    }
                }
                else
                {
                    BitLength[I] = (byte)Length;
                }
            }

            MakeDecodeTables(BitLength, 0, Tables.BD, BC);

            byte[]     Table     = new byte[HUFF_TABLE_SIZE];
            const uint TableSize = HUFF_TABLE_SIZE;

            for (uint I = 0; I < TableSize;)
            {
                if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 5)
                {
                    if (!UnpReadBuf())
                    {
                        return(false);
                    }
                }

                uint Number = DecodeNumber(Inp, Tables.BD);
                if (Number < 16)
                {
                    Table[I] = (byte)Number;
                    I++;
                }
                else
                if (Number < 18)
                {
                    uint N;
                    if (Number == 16)
                    {
                        N = (Inp.fgetbits() >> 13) + 3;
                        Inp.faddbits(3);
                    }
                    else
                    {
                        N = (Inp.fgetbits() >> 9) + 11;
                        Inp.faddbits(7);
                    }
                    if (I == 0)
                    {
                        // We cannot have "repeat previous" code at the first position.
                        // Multiple such codes would shift Inp position without changing I,
                        // which can lead to reading beyond of Inp boundary in mutithreading
                        // mode, where Inp.ExternalBuffer disables bounds check and we just
                        // reserve a lot of buffer space to not need such check normally.
                        return(false);
                    }
                    else
                    {
                        while (N-- > 0 && I < TableSize)
                        {
                            Table[I] = Table[I - 1];
                            I++;
                        }
                    }
                }
                else
                {
                    uint N;
                    if (Number == 18)
                    {
                        N = (Inp.fgetbits() >> 13) + 3;
                        Inp.faddbits(3);
                    }
                    else
                    {
                        N = (Inp.fgetbits() >> 9) + 11;
                        Inp.faddbits(7);
                    }
                    while (N-- > 0 && I < TableSize)
                    {
                        Table[I++] = 0;
                    }
                }
            }
            TablesRead5 = true;
            if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop)
            {
                return(false);
            }

            MakeDecodeTables(Table, 0, Tables.LD, NC);
            MakeDecodeTables(Table, (int)NC, Tables.DD, DC);
            MakeDecodeTables(Table, (int)(NC + DC), Tables.LDD, LDC);
            MakeDecodeTables(Table, (int)(NC + DC + LDC), Tables.RD, RC);
            return(true);
        }