/// <summary> /// This method searches through the slidingWindow /// dictionary for the longest sequence matching the MAX_CODED /// long string stored in the uncodedLookahead /// </summary> /// <param name="uncodedHead">Index of the character from which the coding begins</param> private static EncodedString FindMatch(int uncodedHead) { var matchData = new EncodedString(); var i = HashTable[GetHashKey(uncodedHead, true)]; var j = 0; while (i != Constants.NullIndex) { // We've matched the first symbol if (SlidingWindow[i] == UncodedLookahead[uncodedHead]) { j = 1; while (SlidingWindow[(i + j) % Constants.WindowSize] == UncodedLookahead[(uncodedHead + j) % Constants.MaxCoded]) { if (j >= Constants.MaxCoded) { break; } j++; } if (j > matchData.Length) { matchData.Length = j; matchData.Offset = i; } } if (j >= Constants.MaxCoded) { matchData.Length = Constants.MaxCoded; break; } i = Next[i]; } return(matchData); }
/// <summary> /// Performs LZSS algorithm decoding /// </summary> /// <param name="inputStream">Input file</param> /// <param name="outputStream">Output file</param> public static void Decode(Stream inputStream, Stream outputStream) { var reader = new BinaryReader(inputStream); var writer = new BinaryWriter(outputStream); InitializeDataStructures(); var flags = 0; // Encoded flag var flagsUsed = 8; // Not encoded flag var nextChar = Constants.WindowSize - 16 - 2; // Next char in sliding window var code = new EncodedString(); while (true) { // Shifted out all the flag bits -> read a new flag byte readChar = 0; if (flagsUsed >= 8) { if (reader.BaseStream.Position >= reader.BaseStream.Length) { break; } readChar = reader.ReadByte(); flags = readChar; flagsUsed = 0; } // Uncoded character if ((flags & 1) != 0) { if (reader.BaseStream.Position >= reader.BaseStream.Length) { break; } readChar = reader.ReadByte(); // Write out byte and put it in sliding window writer.Write(readChar); SlidingWindow[nextChar] = readChar; nextChar = (nextChar + 1) % Constants.WindowSize; } else { if (reader.BaseStream.Position >= reader.BaseStream.Length) { break; } code.Offset = reader.ReadByte(); if (reader.BaseStream.Position >= reader.BaseStream.Length) { break; } code.Length = reader.ReadByte(); // Unpack offset and length code.Offset |= ((code.Length & 0x00F0) << 4); code.Length = (code.Length & 0x000F) + Constants.MaxUncoded + 1; // Write out decoded string to file and lookahead for (var i = 0; i < code.Length; i++) { readChar = SlidingWindow[(code.Offset + i) % Constants.WindowSize]; writer.Write(readChar); SlidingWindow[(nextChar + i) % Constants.WindowSize] = readChar; } nextChar = (nextChar + code.Length) % Constants.WindowSize; // PrintSlidingWindow(); // PrintUncodedLookahead(); // Console.WriteLine(); } flags >>= 1; flagsUsed++; } }
/// <summary> /// Performs LZSS algorithm decoding /// </summary> /// <param name="inputFileNameForDecode">Input file</param> /// <param name="outputFileNameForDecode">Output file</param> public static void Decode(string inputFileNameForDecode, string outputFileNameForDecode) { using (var reader = new StreamReader(inputFileNameForDecode)) { using (var writer = new StreamWriter(outputFileNameForDecode)) { InitializeDataStructures(); var flags = 0; // Encoded flag var flagsUsed = 7; // Not encoded flag var nextChar = 0; // Next char in sliding window var code = new EncodedString(); while (true) { flags >>= 1; flagsUsed++; // Shifted out all the flag bits -> read a new flag var readChar = 0; if (flagsUsed == 8) { if ((readChar = reader.Read()) == -1) { break; } flags = readChar & 0xFF; flagsUsed = 0; } // Uncoded character if ((flags & 1) != 0) { if ((readChar = reader.Read()) == -1) { break; } // Write out byte and put it in sliding window writer.Write((char)readChar); SlidingWindow[nextChar] = (char)readChar; nextChar = (nextChar + 1) % Constants.WindowSize; } else { if ((code.Offset = reader.Read()) == -1) { break; } if ((code.Length = reader.Read()) == -1) { break; } // Unpack offset and length code.Offset <<= 4; code.Offset |= (code.Length & 0x00F0) >> 4; code.Length = (code.Length & 0x000F) + Constants.MaxUncoded + 1; // Write out decoded string to file and lookahead for (var i = 0; i < code.Length; i++) { readChar = SlidingWindow[(code.Offset + i) % Constants.WindowSize]; writer.Write((char)readChar); UncodedLookahead[i] = (char)readChar; } // Write out decoded string to sliding window for (var i = 0; i < code.Length; i++) { SlidingWindow[(nextChar + i) % Constants.WindowSize] = UncodedLookahead[i]; } nextChar = (nextChar + code.Length) % Constants.WindowSize; // PrintSlidingWindow(); // PrintUncodedLookahead(); // Console.WriteLine(); } } } } }