private static IEnumerable <CopyToken> RemoveRedundantTokens(IEnumerable <CopyToken> tokens) { CopyToken previous = null; foreach (var next in tokens) { if (previous == null) { previous = next; continue; } if (previous.OverlapsWith(next)) { //figure out which one to keep. There can only be one! if (previous.Length >= next.Length) { yield return(previous); // can't return next. } else { yield return(next); } } else { yield return(previous); previous = next; } } }
internal static bool Contains(this CopyToken thisToken, CopyToken otherToken) { var otherTokenStartsAfterThisToken = thisToken.Position <= otherToken.Position; var otherTokenEndsBeforeThisToken = thisToken.Position + thisToken.Length >= otherToken.Position + otherToken.Length; return(otherTokenStartsAfterThisToken && otherTokenEndsBeforeThisToken); }
internal static bool OverlapsWith(this CopyToken thisToken, CopyToken otherToken) { var firstToken = thisToken; var secondToken = otherToken; if (thisToken.Position > otherToken.Position) { firstToken = otherToken; secondToken = thisToken; } return(firstToken.Position + firstToken.Length > secondToken.Position); }
internal static TokenSequence GetFromCompressedData(BinaryReader reader, long position) { var sequence = new TokenSequence { _flagByte = reader.ReadByte() }; for (var i = 0; i <= 7; i++) { if (sequence.GetIsCopyToken(i)) { var token = new CopyToken(reader, position); sequence._tokens.Add(token); position += Convert.ToInt64(token.Length); } else { sequence._tokens.Add(new LiteralToken(reader)); position += 1; } } return(sequence); }
internal static void Match(byte[] uncompressedData, long position, out UInt16 matchedOffset, out UInt16 matchedLength) { var decompressedCurrent = position; var decompressedEnd = uncompressedData.Length; const long decompressedChunkStart = 0; // SET Candidate TO DecompressedCurrent MINUS 1 var candidate = decompressedCurrent - 1L; // SET BestLength TO 0 var bestLength = 0L; var bestCandidate = 0L; // WHILE Candidate is GREATER THAN OR EQUAL TO DecompressedChunkStart while (candidate >= decompressedChunkStart) { // SET C TO Candidate var c = candidate; // SET D TO DecompressedCurrent var d = decompressedCurrent; // SET Len TO 0 var len = 0; // WHILE (D is LESS THAN DecompressedEnd) // and (the byte at D EQUALS the byte at C) while (d < decompressedEnd && uncompressedData[d] == uncompressedData[c]) { // INCREMENT Len len++; // INCREMENT C c++; // INCREMENT D d++; } // END WHILE // IF Len is GREATER THAN BestLength THEN if (len > bestLength) { // SET BestLength TO Len bestLength = len; // SET BestCandidate TO Candidate bestCandidate = candidate; } // ENDIF // DECREMENT Candidate candidate--; } // END WHILE // IF BestLength is GREATER THAN OR EQUAL TO 3 THEN if (bestLength >= 3) { // CALL CopyToken Help (section 2.4.1.3.19.1) returning MaximumLength var result = CopyToken.CopyTokenHelp(decompressedCurrent); // SET Length TO the MINIMUM of BestLength and MaximumLength matchedLength = (UInt16)bestLength; if (bestLength > result.MaximumLength) { matchedLength = result.MaximumLength; } // SET Offset TO DecompressedCurrent MINUS BestCandidate matchedOffset = (UInt16)(decompressedCurrent - bestCandidate); } else // ELSE { // SET Length TO 0 matchedLength = 0; // SET Offset TO 0 matchedOffset = 0; } // ENDIF }