Пример #1
0
        public void Encode(Stream input, Stream output, IEnumerable <Match> matches)
        {
            var matchArray = matches.ToArray();

            var compressedLength = CalculateCompressedLength(input.Length, matchArray, out var lastRawLength);

            var block = new Block();

            using (var inputReverseStream = new ReverseStream(input, input.Length))
                using (var outputReverseStream = new ReverseStream(output, compressedLength + lastRawLength))
                {
                    foreach (var match in matchArray)
                    {
                        while (match.Position < input.Length - inputReverseStream.Position)
                        {
                            if (block.codeBlockPosition == 0)
                            {
                                WriteAndResetBuffer(outputReverseStream, block);
                            }

                            block.codeBlockPosition--;
                            block.buffer[block.bufferLength++] = (byte)inputReverseStream.ReadByte();
                        }

                        var byte1 = ((byte)(match.Length - 3) << 4) | (byte)((match.Displacement - 3) >> 8);
                        var byte2 = match.Displacement - 3;

                        if (block.codeBlockPosition == 0)
                        {
                            WriteAndResetBuffer(outputReverseStream, block);
                        }

                        block.codeBlock |= (byte)(1 << --block.codeBlockPosition);
                        block.buffer[block.bufferLength++] = (byte)byte1;
                        block.buffer[block.bufferLength++] = (byte)byte2;

                        inputReverseStream.Position += match.Length;
                    }

                    // Flush remaining buffer to stream
                    WriteAndResetBuffer(outputReverseStream, block);

                    // Write any data after last match as raw unbuffered data
                    while (inputReverseStream.Position < inputReverseStream.Length)
                    {
                        outputReverseStream.WriteByte((byte)inputReverseStream.ReadByte());
                    }

                    output.Position = compressedLength + lastRawLength;
                    WriteFooterInformation(input, output, lastRawLength);
                }
        }
Пример #2
0
        public void Decode(Stream input, Stream output)
        {
            using var br = new BinaryReaderX(input, true);

            var header = br.ReadType <CrilaylaHeader>();

            if (header.magic != "CRILAYLA" || header.magic == "\0\0\0\0\0\0\0\0")
            {
                throw new InvalidCompressionException("Crilayla");
            }

            // Copy raw part
            input.Position = input.Length - RawSize_;
            output.Write(br.ReadBytes(RawSize_), 0, RawSize_);

            // Decompress
            var compStream          = new SubStream(input, 0x10, input.Length - RawSize_ - 0x10);
            var reverseCompStream   = new ReverseStream(compStream, compStream.Length);
            var reverseOutputStream = new ReverseStream(output, header.decompSize + RawSize_);
            var circularBuffer      = new CircularBuffer(0x2002);

            using var reverseBr = new BinaryReaderX(reverseCompStream, ByteOrder.LittleEndian, BitOrder.MostSignificantBitFirst, 1);

            while (reverseOutputStream.Position < reverseOutputStream.Length - RawSize_)
            {
                if (!reverseBr.ReadBit())
                {
                    var value = reverseBr.ReadBits <byte>(8);

                    reverseOutputStream.WriteByte(value);
                    circularBuffer.WriteByte(value);
                    continue;
                }

                var displacement = reverseBr.ReadBits <short>(13) + 3;
                var length       = ReadLength(reverseBr) + 3;

                circularBuffer.Copy(reverseOutputStream, displacement, length);
            }
        }