Exemple #1
0
        // Section 2.4.1.3.6
        // page 62
        /// <summary>
        /// Compresses the data given in UncompressedData.
        /// </summary>
        /// <param name="UncompressedData">Uncompressed raw data</param>
        /// <returns>A byte array containing the compressed data</returns>
        public static Byte[] Compress(byte[] UncompressedData)
        {
            if (UncompressedData == null)
            {
                throw new ArgumentNullException("UncompressedData");
            }

            var resultBuffer = new CompressedBuffer(UncompressedData.Length);

            DecompressedBuffer uncompressedDataBuffer = new DecompressedBuffer(UncompressedData);
            var state = new DecompressionState(uncompressedDataBuffer);

            // 2.4.1.3.6 Compression algorithm
            resultBuffer.SetByte(state.CompressedCurrent, 0x01);
            ++state.CompressedCurrent;

            while (state.DecompressedCurrent < state.DecompressedBufferEnd)
            {
                state.CompressedChunkStart   = state.CompressedCurrent;
                state.DecompressedChunkStart = state.DecompressedCurrent;
                CompressDecompressedChunk(UncompressedData, resultBuffer, state);
            }

            return(resultBuffer.GetData());
        }
Exemple #2
0
        // Section 2.4.1.3.8
        // page 63
        private static void CompressTokenSequence(byte[] Data, CompressedBuffer resultBuffer, DecompressionState state, int CompressedEnd, int DecompressedEnd)
        {
            var  FlagByteIndex = state.CompressedCurrent;
            Byte TokenFlags    = 0x0; // 0b00000000

            ++state.CompressedCurrent;

            for (int index = 0; index <= 7; index++)
            {
                if (state.DecompressedCurrent < DecompressedEnd && state.CompressedCurrent < CompressedEnd)
                {
                    TokenFlags = CompressToken(Data, resultBuffer, state, CompressedEnd, DecompressedEnd, index, TokenFlags);
                }
            }

            resultBuffer.SetByte(FlagByteIndex, TokenFlags);
        }
Exemple #3
0
        // section 2.4.1.3.10
        // page 65
        private static void CompressRawChunk(byte[] Data, CompressedBuffer resultBuffer, DecompressionState state, int LastByte)
        {
            state.CompressedCurrent   = state.CompressedChunkStart + 2;
            state.DecompressedCurrent = state.DecompressedChunkStart;
            int PadCount = 4096;

            for (int i = state.DecompressedChunkStart; i <= LastByte; i++)
            {
                Byte B = Data[i]; // issue: do they really mean from Data?
                resultBuffer.SetByte(state.CompressedCurrent, B);

                ++state.CompressedCurrent;
                ++state.DecompressedCurrent;
                --PadCount;
            }

            for (int counter = 1; counter <= PadCount; counter++)
            {
                resultBuffer.SetByte(state.CompressedCurrent, 0x00);
                ++state.CompressedCurrent;
            }
        }
Exemple #4
0
        // 2.4.1.3.7 Compressing a DecompressedChunk
        // page 62
        private static void CompressDecompressedChunk(byte[] Data, CompressedBuffer resultBuffer, DecompressionState state)
        {
            var CompressedEnd = state.CompressedChunkStart + 4098;

            state.CompressedCurrent = state.CompressedChunkStart + 2;
            var DecompressedEnd = Math.Min(state.DecompressedChunkStart + 4096, state.DecompressedBufferEnd);

            while (state.DecompressedCurrent < DecompressedEnd && state.CompressedCurrent < CompressedEnd)
            {
                CompressTokenSequence(Data, resultBuffer, state, CompressedEnd, DecompressedEnd);
            }

            UInt16 CompressedFlag;

            if (state.DecompressedCurrent < DecompressedEnd)
            {
                CompressRawChunk(Data, resultBuffer, state, DecompressedEnd - 1);
                CompressedFlag = 0;
            }
            else
            {
                CompressedFlag = 1;
            }


            UInt16 size   = Convert.ToUInt16(state.CompressedCurrent - state.CompressedChunkStart);
            var    header = new CompressedChunkHeader(0x0000);

            PackCompressedChunkSize(Data, state, size, header);
            PackCompressedChunkFlag(Data, state, CompressedFlag, header);
            PackCompressedChunkSignature(Data, state, header);

            // SET the CompressedChunkHeader (section 2.4.1.1.5) located at CompressedChunkStart TO Header
            var bytes = BitConverter.GetBytes(header.AsUInt16());

            resultBuffer.SetByte(state.CompressedChunkStart, bytes.First());
            resultBuffer.SetByte(state.CompressedChunkStart + 1, bytes.Skip(1).Single());
        }
Exemple #5
0
        // Section 2.4.1.3.9
        // page 64
        private static Byte CompressToken(byte[] Data, CompressedBuffer resultBuffer, DecompressionState state, int CompressedEnd, int DecompressedEnd, int index, Byte Flags)
        {
            UInt16 Offset = 0;

            var match = Matching(Data, state, DecompressedEnd);

            Offset = match.Offset;
            UInt16 Length = match.Length;

            if (Offset != 0)
            {
                if ((state.CompressedCurrent + 1) < CompressedEnd)
                {
                    var Token = PackCopyToken(Data, state, Offset, Length);

                    var bytes = BitConverter.GetBytes(Token.AsUInt16());

                    // Convert to little endian order, if necessary
                    if (!BitConverter.IsLittleEndian)
                    {
                        bytes = bytes.Reverse().ToArray();
                    }

                    Byte byte1 = bytes.First();
                    Byte byte2 = bytes.Skip(1).Single();

                    /*
                     * ////////////////// DEBUG ////////////////////////////////////
                     *
                     * byte[] _debug_all_expected_bytes = .... get expected output e.g. from unit test data ...
                     * byte[] _debug_expected_bytes = new byte[] { _debug_all_expected_bytes.ElementAt(state.CompressedCurrent), _debug_all_expected_bytes.ElementAt(state.CompressedCurrent + 1) };
                     *
                     * var TokenValue_Expected = BitConverter.ToUInt16(_debug_expected_bytes, 0);
                     * var Token_Expected = new CopyToken(TokenValue_Expected);
                     *
                     * CopyToken.UnpackedInfo Actual_Infos = Token.UnpackCopyToken(state.DecompressedCurrent, state.DecompressedChunkStart);
                     * CopyToken.UnpackedInfo Expected_Infos = Token_Expected.UnpackCopyToken(state.DecompressedCurrent, state.DecompressedChunkStart);
                     *
                     * string _debug_bitStr = BitHelper.ToBitString(bytes);
                     * string _debug_str_found = String.Format("ACTUAL:  Token at index {0}: {1} (Bits {2}). Length = {3}, Offset = {4} (-> copy bytes: {5}).", state.CompressedCurrent, BitConverter.ToString(bytes), BitHelper.ToBitString(bytes), Actual_Infos.Length, Actual_Infos.Offset, BitConverter.ToString(Data.Skip(state.DecompressedCurrent - Actual_Infos.Offset).Take(Actual_Infos.Length).ToArray()));
                     * string _debug_str_expected = String.Format("EXPECTED: Token at index {0}: {1} (Bits {2}). Length = {3}, Offset = {4} (-> copy bytes: {5})", state.CompressedCurrent, BitConverter.ToString(_debug_expected_bytes), BitHelper.ToBitString(_debug_expected_bytes), Expected_Infos.Length, Expected_Infos.Offset, BitConverter.ToString(Data.Skip(state.DecompressedCurrent - Expected_Infos.Offset).Take(Expected_Infos.Length).ToArray()));
                     *
                     * Trace.WriteLine(_debug_str_found);
                     * Trace.WriteLine(_debug_str_expected);
                     *
                     *
                     * ////////////////// DEBUG ////////////////////////////////////
                     * */

                    resultBuffer.SetByte(state.CompressedCurrent, byte1);
                    resultBuffer.SetByte(state.CompressedCurrent + 1, byte2);

                    Flags = SetFlagBit(index, 1, Flags);

                    state.CompressedCurrent   += 2;
                    state.DecompressedCurrent += Length;
                }
                else
                {
                    state.CompressedCurrent = CompressedEnd;
                }
            }
            else
            {
                if (state.CompressedCurrent < CompressedEnd)
                {
                    byte LiteralToken = Data[state.DecompressedCurrent];
                    resultBuffer.SetByte(state.CompressedCurrent, LiteralToken);
                    ++state.CompressedCurrent;
                    ++state.DecompressedCurrent;
                }
                else
                {
                    state.CompressedCurrent = CompressedEnd;
                }
            }

            return(Flags);
        }