Пример #1
0
        public byte[] Compress(byte[] arg)
        {
            var result = new LZNT1_Buffer();

            var chunks = new List <LZNT1_Chunk>();
            int index  = 0;

            while (index < arg.Length)
            {
                int length = Math.Min(arg.Length - index, 4096);

                var chunk = CompressChunk(arg.Skip(index).Take(length).ToArray());

                chunks.Add(chunk);

                index += length;
            }


            result.Chunk = chunks.ToArray();

            var buffer = new LittleEndianByteBuffer();
            int offset = 0;

            result.Marshal(buffer, ref offset);

            return(buffer.GetBytes());
        }
Пример #2
0
        /// <summary>
        /// Decode LZ77 symbols to data.
        /// </summary>
        /// <param name="symbols">LZ77 symbols to be decoded.</param>
        /// <returns>The data after decoded.</returns>
        public byte[] Decode(List <LZ77Symbol> symbols)
        {
            var buffer = new LittleEndianByteBuffer();
            int offset = 0;

            Verify(symbols);

            foreach (var symbol in symbols)
            {
                symbol.Decode(buffer, ref offset);
            }

            return(buffer.GetBytes());
        }
        /// <summary>
        /// Encode LZ77 symbols.
        /// </summary>
        /// <param name="symbols">LZ77 symbols to be encoded.</param>
        /// <returns>Byte array containing encoded result.</returns>
        public byte[] Encode(List <LZ77Symbol> symbols)
        {
            long Flags              = 0;
            int  FlagCount          = 0;
            int  FlagOutputPosition = 0;
            int  OutputPosition     = 4;
            int  LastLengthHalfByte = 0;

            var buffer = new LittleEndianByteBuffer();

            foreach (var symbol in symbols)
            {
                if (symbol is LZ77Literal)
                {
                    var literal = symbol as LZ77Literal;

                    buffer.WriteBytes(OutputPosition, literal.Literal, 1);

                    OutputPosition += 1;

                    Flags <<= 1;

                    FlagCount += 1;
                }
                else if (symbol is LZ77Match)
                {
                    var match       = symbol as LZ77Match;
                    int MatchLength = match.Length;
                    int MatchOffset = match.Distance;

                    MatchLength -= 3;

                    MatchOffset -= 1;

                    MatchOffset <<= 3;

                    if (MatchLength < 7)
                    {
                        MatchOffset += (int)MatchLength;

                        buffer.WriteBytes(OutputPosition, MatchOffset, 2);

                        OutputPosition += 2;
                    }
                    else
                    {
                        MatchOffset |= 7;

                        buffer.WriteBytes(OutputPosition, MatchOffset, 2);

                        OutputPosition += 2;

                        MatchLength -= 7;

                        bool EncodeExtraLen;

                        if (LastLengthHalfByte == 0)
                        {
                            LastLengthHalfByte = OutputPosition;

                            if (MatchLength < 15)
                            {
                                buffer.WriteBytes(OutputPosition, MatchLength, 1);

                                OutputPosition += 1;

                                EncodeExtraLen = false;
                            }
                            else
                            {
                                buffer.WriteBytes(OutputPosition, 15, 1);

                                OutputPosition++;

                                EncodeExtraLen = true;
                            }
                        }
                        else
                        {
                            if (MatchLength < 15)
                            {
                                byte LastLength = buffer[LastLengthHalfByte];

                                LastLength |= (byte)(MatchLength << 4);

                                buffer.WriteBytes(LastLengthHalfByte, LastLength, 1);

                                LastLengthHalfByte = 0;

                                EncodeExtraLen = false;
                            }
                            else
                            {
                                byte LastLength = buffer[LastLengthHalfByte];

                                LastLength |= 15 << 4;

                                buffer.WriteBytes(LastLengthHalfByte, LastLength, 1);

                                LastLengthHalfByte = 0;

                                EncodeExtraLen = true;
                            }
                        }

                        if (EncodeExtraLen)
                        {
                            MatchLength -= 15;

                            if (MatchLength < 255)
                            {
                                buffer.WriteBytes(OutputPosition, MatchLength, 1);

                                OutputPosition += 1;
                            }
                            else
                            {
                                buffer.WriteBytes(OutputPosition, 255, 1);

                                OutputPosition += 1;

                                MatchLength += 7 + 15;

                                if (MatchLength < (1 << 16))
                                {
                                    buffer.WriteBytes(OutputPosition, MatchLength, 2);

                                    OutputPosition += 2;
                                }
                                else
                                {
                                    buffer.WriteBytes(OutputPosition, 0, 2);

                                    OutputPosition += 2;

                                    buffer.WriteBytes(OutputPosition, MatchLength, 4);

                                    OutputPosition += 4;
                                }
                            }
                        }
                    }

                    Flags = (Flags << 1) | 1;

                    FlagCount += 1;
                }
                else if (symbol is LZ77EOF)
                {
                    // Do nothing to EOF.
                }
                else
                {
                    throw new XcaException("Unreachable code!");
                }

                if (FlagCount == 32)
                {
                    buffer.WriteBytes(FlagOutputPosition, (int)Flags, 4);

                    FlagCount = 0;

                    FlagOutputPosition = OutputPosition;

                    OutputPosition += 4;
                }
            }

            Flags <<= (32 - FlagCount);
            Flags  |= (((long)1 << (32 - FlagCount)) - 1);

            buffer.WriteBytes(FlagOutputPosition, (int)Flags, 4);

            return(buffer.GetBytes());
        }