예제 #1
0
        public static bool Decompress(Stream input, Stream output)
        {
            if (!input.CanRead || !output.CanWrite)
            {
                return false;
            }
            BinaryReader reader = new BinaryReader(input);
            int header = reader.ReadInt32();
            if ((header & 0xFF) != 0x10)
            {
                return false;
            }
            var slidingWindow = new LinkedList<byte>();
            //var slidingWindow = new LinkedArrayList<byte>(); doesn't work

            int decompSize = header >> 8;
            long startPosition = output.Position;
            while ((output.Position - startPosition) < decompSize)
            {
                if (input.Position >= input.Length)
                    return false;

                byte flags = reader.ReadByte();
                for (int i = 0; i < BlockSize; i++)
                {
                    if ((flags & (0x80 >> i)) != 0)
                    {
                        if (input.Position >= input.Length - 1)
                            return false;

                        byte first = reader.ReadByte();
                        byte second = reader.ReadByte();
                        int position = (((first << 8) + second + 1) & 0xFFF);
                        int amountToCopy = (3 + ((first >> 4) & 0xF));

                        if (position > (output.Position - startPosition))
                            return false;

                        byte[] dataToCopy =
                            slidingWindow
                            .EnumerateLast(position)
                            .Repeat()
                            .Take(amountToCopy)
                            .ToArray();

                        output.Write(dataToCopy, 0, dataToCopy.Length);

                        for (int slidingI = 0; slidingI < dataToCopy.Length; slidingI++)
                        {
                            slidingWindow.AddLast(dataToCopy[slidingI]);
                        }

                        slidingWindow.RemoveExtra(SlidingWindowSize);
                    }
                    else
                    {
                        if (input.Position > input.Length)
                            return false;
                        byte raw = reader.ReadByte();
                        slidingWindow.AddLast(raw);
                        slidingWindow.RemoveExtra(SlidingWindowSize);
                        output.WriteByte(raw);
                    }

                    if ((output.Position - startPosition) >= decompSize)
                        break;
                }
            }
            slidingWindow.Clear();
            return true;
        }