/// <summary> /// Reads the text content of a file and determines its Encoding. /// </summary> /// <param name="fileName"></param> /// <param name="ignoreInsignificantWhiteSpace"></param> /// <param name="progress"></param> /// <returns></returns> public static FileContentInfo GetXmlText(string fileName, bool ignoreInsignificantWhiteSpace, IDiffProgress progress) { var contentInfo = new FileContentInfo(); //// This should be created from in-memory text to save IO and support editing //// using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true)) //// { //// contentInfo.Lines = GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress); //// } // Read the RAW text content const int DefaultBufferSize = 4096; const FileOptions DefaultOptions = FileOptions.Asynchronous | FileOptions.SequentialScan; using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultOptions)) { var bom = new byte[4]; // Decode bom (if any) and continue to read text content stream.Read(bom, 0, 4); stream.Seek(0, SeekOrigin.Begin); contentInfo.TextEncoding = FileEx.GetEncoding(bom); using (StreamReader reader = new StreamReader(stream, contentInfo.TextEncoding)) { contentInfo.TextContent = reader.ReadToEnd(); } } return(contentInfo); }
public static IList <string> GetFileTextLines(string fileName, IDiffProgress progress) { using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true)) { return(GetTextLines(reader, progress)); } }
private static void GetTextLines(string textA, string textB, TextBinaryDiffArgs args, out IList <string> a, out IList <string> b, IDiffProgress progress) { a = null; b = null; CompareType compareType = args.CompareType; bool isAuto = compareType == CompareType.Auto; if (compareType == CompareType.Xml || isAuto) { a = TryGetXmlLines(DiffUtility.GetXmlTextLinesFromXml, "the left side text", textA, !isAuto, args, progress); // If A failed to parse with Auto, then there's no reason to try B. if (a != null) { b = TryGetXmlLines(DiffUtility.GetXmlTextLinesFromXml, "the right side text", textB, !isAuto, args, progress); } // If we get here and the compare type was XML, then both // inputs parsed correctly, and both lists should be non-null. // If we get here and the compare type was Auto, then one // or both lists may be null, so we'll fallthrough to the text // handling logic. } if (a == null || b == null) { a = DiffUtility.GetStringTextLines(textA, progress); b = DiffUtility.GetStringTextLines(textB, progress); } }
private static IList <string> TryGetXmlLines( Func <string, bool, IDiffProgress, IList <string> > converter, string name, string input, bool throwOnError, TextBinaryDiffArgs args, IDiffProgress progress) { IList <string> result = null; try { result = converter(input, args.IgnoreXmlWhitespace, progress); } catch (XmlException ex) { if (throwOnError) { StringBuilder sb = new StringBuilder("An XML comparison was attempted, but an XML exception occurred while parsing "); sb.Append(name).AppendLine(".").AppendLine(); sb.AppendLine("Exception Message:").Append(ex.Message); throw new XmlException(sb.ToString(), ex); } } return(result); }
public IList <string> TryGetXmlLines( Func <string, bool, IDiffProgress, IList <string> > converter, bool throwOnError, TextBinaryDiffArgs args, IDiffProgress progress) { IList <string> result = null; try { if (FileExists) { result = converter(FileNamePath, args.IgnoreXmlWhitespace, progress); _typeOfFile = FileType.Xml; } } catch (XmlException ex) { if (throwOnError) { StringBuilder sb = new StringBuilder("An XML comparison was attempted, but an XML exception occurred while parsing "); sb.Append("'" + FileNamePath + "'").AppendLine(".").AppendLine(); sb.AppendLine("Exception Message:").Append(ex.Message); throw new XmlException(sb.ToString(), ex); } } return(result); }
public static IList <string> GetStringTextLines(string text, IDiffProgress progress) { using (StringReader reader = new StringReader(text)) { return(GetTextLines(reader, progress)); } }
public IList <T> GetLongestCommonSubsequence(IDiffProgress progress) { List <T> result = new List <T>(); this.GetLcs(new SubArray <T>(this.listA), new SubArray <T>(this.listB), progress, result); return(result); }
/// <summary>Compare to files or string contents and return result via progress object.</summary> /// <param name="progress"></param> /// <param name="dataSource"></param> /// <returns></returns> public IDiffProgress ProcessDiff(IDiffProgress progress, IDataSource dataSource) { try { DiffBinaryTextResults result = null; if (_Args.DiffType == DiffType.File) { var fileA = dataSource.CreateFile(_Args.A); var fileB = dataSource.CreateFile(_Args.B); result = GetFileLines(fileA, fileB, _Args, progress); } else { // DiffType in-memory text content result = GetTextLines(TextContentA, TextContentB, _Args, progress); } if (result.IsComparedAs == CompareType.Text || result.IsComparedAs == CompareType.Xml) { // Render Text or XML lines from in-memory text content if (_Args.DiffType == DiffType.File) { result = GetTextLines(result, _Args, progress); } // Assumption: Binary cannot be edit and RAW data cannot be stored in string // Therefore, binary lines are rendered only once directly from file TextOriginalA = result.A.TextContent; TextContentA = result.A.TextContent; TextEncodingA = result.A.TextEncoding; TextOriginalB = result.B.TextContent; TextContentB = result.B.TextContent; TextEncodingB = result.B.TextEncoding; } ListA = result.A.Lines; ListB = result.B.Lines; IsComparedAs = result.IsComparedAs; IgnoreCase = result.IgnoreCase; IgnoreTextWhitespace = result.IgnoreTextWhitespace; TextDiff diff = new TextDiff(_Args.HashType, IgnoreCase, IgnoreTextWhitespace, result.LeadingCharactersToIgnore, !_Args.ShowChangeAsDeleteInsert); Script = diff.Execute(ListA, ListB, progress); progress.ResultData = this; return(progress); } finally { } }
public static IList <string> GetXmlTextLines(string fileName, bool ignoreInsignificantWhiteSpace, IDiffProgress progress) { using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true)) { return(GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress)); } }
public static IList <string> GetXmlTextLinesFromXml(string xml, bool ignoreInsignificantWhiteSpace, IDiffProgress progress) { using (StringReader reader = new StringReader(xml)) { return(GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress)); } }
private static void GetFileLines(string fileNameA, string fileNameB, out IList <string> a, out IList <string> b, out int leadingCharactersToIgnore, TextBinaryDiffArgs args, IDiffProgress progress) { a = null; b = null; leadingCharactersToIgnore = 0; CompareType compareType = args.CompareType; if (compareType == CompareType.Binary || (args.IsAuto && (DiffUtility.IsBinaryFile(fileNameA) || DiffUtility.IsBinaryFile(fileNameB)))) { using (FileStream fileA = File.OpenRead(fileNameA)) using (FileStream fileB = File.OpenRead(fileNameB)) { BinaryDiff diff = new BinaryDiff { FootprintLength = args.BinaryFootprintLength }; AddCopyCollection addCopy = diff.Execute(fileA, fileB); BinaryDiffLines lines = new BinaryDiffLines(fileA, addCopy, args.BinaryFootprintLength); a = lines.BaseLines; b = lines.VersionLines; leadingCharactersToIgnore = BinaryDiffLines.PrefixLength; } } if (compareType == CompareType.Xml || (args.IsAuto && (a == null || b == null))) { a = TryGetXmlLines(DiffUtility.GetXmlTextLines, fileNameA, fileNameA, !args.IsAuto, args, progress); // If A failed to parse with Auto, then there's no reason to try B. if (a != null) { b = TryGetXmlLines(DiffUtility.GetXmlTextLines, fileNameB, fileNameB, !args.IsAuto, args, progress); } // If we get here and the compare type was XML, then both // inputs parsed correctly, and both lists should be non-null. // If we get here and the compare type was Auto, then one // or both lists may be null, so we'll fallthrough to the text // handling logic. } if (a == null || b == null) { a = DiffUtility.GetFileTextLines(fileNameA, progress); b = DiffUtility.GetFileTextLines(fileNameB, progress); } }
public static IList <string> GetTextLines(TextReader reader, IDiffProgress progress) { IList <string> result = new List <string>(); while (reader.Peek() > -1) { progress.Token.ThrowIfCancellationRequested(); string line = reader.ReadLine(); result.Add(line); } return(result); }
public static FileContentInfo GetXmlTextFromXml(string xml, bool ignoreInsignificantWhiteSpace, IDiffProgress progress) { var result = new FileContentInfo(); result.TextContent = xml; using (StringReader reader = new StringReader(xml)) { result.Lines = GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress); } return(result); }
/// <summary> /// Gets an <see cref="EditScript"/> for comparing a list of right and left strings /// (sometimes also refered to as stringA and stringB or sequenceA and sequenceB). /// </summary> /// <param name="listA">sequenceA</param> /// <param name="listB">sequenceB</param> public EditScript Execute(IList <string> listA, IList <string> listB , IDiffProgress progress) { // Convert input string lists into arrays of integer hash values int[] hashA = this.HashStringList(listA); int[] hashB = this.HashStringList(listB); // Construct MyersDiff<int> object from arrays of int hash values that represent the original string input MyersDiff <int> diff = new MyersDiff <int>(hashA, hashB, this.supportChangeEditType); // Gets an EditScript instance that describes all Edits necessary to transform ListA into ListB. EditScript result = diff.Execute(progress); return(result); }
/// <summary> /// Gets an edit script instance that gives all the Edits necessary to transform A into B. /// </summary> /// <returns>The edit script which is a list of <see cref="Edit"/> objects that describes the transformation.</returns> public EditScript Execute(IDiffProgress progress) { List <Point> matchPoints = new List <Point>(); SubArray <T> subArrayA = new SubArray <T>(this.listA); SubArray <T> subArrayB = new SubArray <T>(this.listB); this.GetMatchPoints(subArrayA, subArrayB, matchPoints, progress); Debug.Assert(matchPoints.Count == this.GetLongestCommonSubsequenceLength(), "The number of match points must equal the LCS length."); EditScript result = this.ConvertMatchPointsToEditScript(subArrayA.Length, subArrayB.Length, matchPoints); Debug.Assert(result.TotalEditLength == this.GetShortestEditScriptLength(), "The total edit length must equal the SES length."); return(result); }
/// <summary> /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison /// options as defined in the constructor of this class. /// </summary> /// <param name="directoryA"></param> /// <param name="directoryB"></param> /// <returns>Null if an unkown error occured or if either directory cannot be accessed /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object /// where the <see cref="IDiffProgress.ResultData"/> property contains a /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory /// differences in detail.</returns> public IDiffProgress Execute(string directoryA, string directoryB, IDiffProgress progress) { try { var dirA = new DirectoryInfo(directoryA); var dirB = new DirectoryInfo(directoryB); return(this.Execute(dirA, dirB, progress)); } catch { return(null); } }
/// <summary> /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison /// options as defined in the constructor of this class. /// </summary> /// <param name="directoryA"></param> /// <param name="directoryB"></param> /// <param name="progress"></param> /// <param name="source"></param> /// <returns>Null if an unkown error occured or if either directory cannot be accessed /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object /// where the <see cref="IDiffProgress.ResultData"/> property contains a /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory /// differences in detail.</returns> public IDiffProgress Execute(string directoryA, string directoryB, IDiffProgress progress, IDataSource source) { try { var dirA = source.CreateDirectory(directoryA); var dirB = source.CreateDirectory(directoryB); return(this.Execute(dirA, dirB, progress, source)); } catch { return(null); } }
public IDiffProgress ProcessDiff(IDiffProgress progress) { progress.ShowIndeterminatedProgress(); try { if (System.IO.File.Exists(_Args.A) == false || System.IO.File.Exists(_Args.B) == false) { return(progress); } IList <string> a, b; int leadingCharactersToIgnore = 0; if (_Args.DiffType == DiffType.File) { GetFileLines(_Args.A, _Args.B, out a, out b, out leadingCharactersToIgnore, _Args, progress); } else { GetTextLines(_Args.A, _Args.B, _Args, out a, out b, progress); } IsBinaryCompare = leadingCharactersToIgnore > 0; IgnoreCase = IsBinaryCompare ? false : _Args.IgnoreCase; IgnoreTextWhitespace = IsBinaryCompare ? false : _Args.IgnoreTextWhitespace; TextDiff diff = new TextDiff(_Args.HashType, IgnoreCase, IgnoreTextWhitespace, leadingCharactersToIgnore, !_Args.ShowChangeAsDeleteInsert); ListA = a; ListB = b; Script = diff.Execute(a, b); progress.ResultData = this; return(progress); } finally { progress.ProgressDisplayOff(); } }
private static IList <string> GetXmlTextLines(TextReader textReader, bool ignoreInsignificantWhitespace, IDiffProgress progress) { XmlReaderSettings settings = new XmlReaderSettings { CheckCharacters = false, CloseInput = true, DtdProcessing = DtdProcessing.Ignore, IgnoreWhitespace = ignoreInsignificantWhitespace, ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None, ValidationType = ValidationType.None, XmlResolver = null }; using (XmlReader xmlReader = XmlReader.Create(textReader, settings)) { IList <string> result = GetXmlTextLines(xmlReader, progress); return(result); } }
private DiffBinaryTextResults GetTextLines(string textA, string textB , TextBinaryDiffArgs args , IDiffProgress progress) { FileContentInfo af = null, bf = null; bool isAuto = args.CompareType == CompareType.Auto; if (args.CompareType == CompareType.Xml || isAuto) { af = TryGetXmlText(DiffUtility.GetXmlTextFromXml, "the left side text", textA, !isAuto, args, progress); // If A failed to parse with Auto, then there's no reason to try B. if (af != null) { bf = TryGetXmlText(DiffUtility.GetXmlTextFromXml, "the right side text", textB, !isAuto, args, progress); } // If we get here and the compare type was XML, then both // inputs parsed correctly, and both lists should be non-null. // If we get here and the compare type was Auto, then one // or both lists may be null, so we'll fallthrough to the text // handling logic. } if (af == null || bf == null) { af = new FileContentInfo(); bf = new FileContentInfo(); af.Lines = DiffUtility.GetStringTextLines(textA, progress); bf.Lines = DiffUtility.GetStringTextLines(textB, progress); } af.TextContent = textA; bf.TextContent = textB; DiffBinaryTextResults result = new DiffBinaryTextResults(CompareType.Text, af, bf); return(result); }
private DiffBinaryTextResults GetTextLines(DiffBinaryTextResults src , TextBinaryDiffArgs args , IDiffProgress progress) { IList <string> a = null, b = null; bool isAuto = args.CompareType == CompareType.Auto; if (args.CompareType == CompareType.Xml || isAuto) { a = TryGetXmlText(DiffUtility.GetXmlTextLinesFromXml, "the left side text", src.A.TextContent, !isAuto, args, progress); // If A failed to parse with Auto, then there's no reason to try B. if (a != null) { b = TryGetXmlText(DiffUtility.GetXmlTextLinesFromXml, "the right side text", src.B.TextContent, !isAuto, args, progress); } // If we get here and the compare type was XML, then both // inputs parsed correctly, and both lists should be non-null. // If we get here and the compare type was Auto, then one // or both lists may be null, so we'll fallthrough to the text // handling logic. } if (a == null || b == null) { a = DiffUtility.GetStringTextLines(src.A.TextContent, progress); b = DiffUtility.GetStringTextLines(src.B.TextContent, progress); } else { src.IsComparedAs = CompareType.Xml; } src.A.Lines = a; src.B.Lines = b; return(src); }
private void GetLcs(SubArray <T> subArrayA, SubArray <T> subArrayB , IDiffProgress progress , List <T> output) { if (subArrayA.Length > 0 && subArrayB.Length > 0) { // Find the length D and the middle snake from (x,y) to (u,v) int x, u, k; int d = this.FindMiddleSnake(subArrayA, subArrayB, progress, out x, out u, out k); int y = x - k; int v = u - k; if (d > 1) { this.GetLcs(new SubArray <T>(subArrayA, 1, x), new SubArray <T>(subArrayB, 1, y), progress, output); for (int i = x + 1; i <= u; i++) { output.Add(subArrayA[i]); } this.GetLcs(new SubArray <T>(subArrayA, u + 1, subArrayA.Length - u), new SubArray <T>(subArrayB, v + 1, subArrayB.Length - v), progress, output); } else if (subArrayB.Length > subArrayA.Length) { for (int i = 1; i <= subArrayA.Length; i++) { output.Add(subArrayA[i]); } } else { for (int i = 1; i <= subArrayB.Length; i++) { output.Add(subArrayB[i]); } } } }
public static IList <string> GetXmlTextLines(XmlReader reader, IDiffProgress progress) { XmlWriterSettings settings = new XmlWriterSettings { CheckCharacters = false, CloseOutput = true, Indent = true, IndentChars = "\t", NewLineOnAttributes = true }; StringBuilder sb = new StringBuilder(); using (XmlWriter writer = XmlWriter.Create(sb, settings)) { writer.WriteNode(reader, false); } IList <string> result = GetStringTextLines(sb.ToString(), progress); return(result); }
/// <summary> /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison /// options as defined in the constructor of this class. /// </summary> /// <param name="directoryA"></param> /// <param name="directoryB"></param> /// <param name="progress"></param> /// <param name="source"></param> /// <returns>Null if an unkown error occured or if either directory cannot be accessed /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object /// where the <see cref="IDiffProgress.ResultData"/> property contains a /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory /// differences in detail.</returns> public IDiffProgress Execute(IDirectoryInfo directoryA, IDirectoryInfo directoryB, IDiffProgress progress, IDataSource source) { try { // Create a faux base entry to pass to Execute var diffRoot = new DirectoryDiffRoot(directoryA.FullName, directoryB.FullName, _Recursive, _Filter, _DiffMode, source); progress.ResultData = diffRoot; progress.ShowIndeterminatedProgress(); if (directoryA.Exists == false || directoryB.Exists == false) { return(null); } // directory diff match int directories = this.BuildSubDirs(directoryA, directoryB, _Recursive, _Filter, diffRoot); progress.ShowDeterminatedProgress(0, 0, directories); this.AddFiles(diffRoot, progress); return(progress); } catch (Exception exp) { progress.LogException(exp); return(null); } finally { progress.ProgressDisplayOff(); } }
/// <summary> /// Compares two files using binary or text comparison methods. /// </summary> /// <param name="fileA"></param> /// <param name="fileB"></param> /// <param name="a"></param> /// <param name="b"></param> /// <param name="args"></param> /// <param name="progress"></param> private DiffBinaryTextResults GetFileLines(IFileInfo fileA , IFileInfo fileB , TextBinaryDiffArgs args , IDiffProgress progress) { // Nothing to compare if both files do not exist if (fileA.FileExists == false && fileB.FileExists == false) { return(new DiffBinaryTextResults(CompareType.Text, new FileContentInfo(), new FileContentInfo())); } if (args.CompareType == CompareType.Binary || (args.IsAuto && fileA.Is == FileType.Binary || fileB.Is == FileType.Binary)) { return(GetBinaryFileLines(fileA, fileB, args, progress)); } FileContentInfo af = null, bf = null; if (fileA.FileExists) { af = AsyncPump.Run(() => FileEx.GetFileTextAsync(fileA.FullName)); } else { af = new FileContentInfo(); } if (fileB.FileExists) { bf = AsyncPump.Run(() => FileEx.GetFileTextAsync(fileB.FullName)); } else { bf = new FileContentInfo(); } return(new DiffBinaryTextResults(CompareType.Text, af, bf)); }
public static IList <string> GetTextLines(TextReader reader, IDiffProgress progress) { IList <string> result = new List <string>(); try { while (reader.Peek() > -1) { progress.Token.ThrowIfCancellationRequested(); string line = reader.ReadLine(); result.Add(line); } } catch { // Not catching this but returning at default empty list } return(result); }
/// <summary> /// Adds files into a given <paramref name="root"/> directory structure of sub-directories /// and re-evaluates their status in terms of difference. /// /// The algorithm used implements a Post-Order traversal algorithm which also allows us /// to aggregate results (sub-directory is different, size) up-wards through the hierarchy. /// </summary> /// <param name="root"></param> private void AddFiles(DirectoryDiffRoot root, IDiffProgress progress) { int CountDirs = 0; // If the base paths are the same, we don't need to check for file differences. bool checkIfFilesAreDifferent = string.Compare(root.RootPathA, root.RootPathB, true) != 0; var toVisit = new Stack <IDirectoryDiffEntry>(); var visitedAncestors = new Stack <IDirectoryDiffEntry>(); toVisit.Push(root.RootEntry); while (toVisit.Count > 0) { if (progress != null) { if (progress.Token.IsCancellationRequested) { progress.Token.ThrowIfCancellationRequested(); } } var node = toVisit.Peek(); if (node.CountSubDirectories() > 0) { if (PeekOrDefault(visitedAncestors) != node) { visitedAncestors.Push(node); PushReverse(toVisit, node.Subentries.ToList()); continue; } visitedAncestors.Pop(); } // Load files only if either directory is available and recursion is on // -> Load files only for root directory if recursion is turned off if ((node.InA == true || node.InB == true) && (this._Recursive || string.IsNullOrEmpty(node.BasePath))) { if (node.CountSubDirectories() > 0) { foreach (var item in node.Subentries) // Aggregate size of sub-directories up { if (progress != null) { if (progress.Token.IsCancellationRequested) { progress.Token.ThrowIfCancellationRequested(); } } CountDirs++; if (progress != null) { if (progress != null) { progress.UpdateDeterminatedProgress(CountDirs); } } if (node.InA == true) { node.LengthA += item.LengthA; } if (node.InB == true) { node.LengthB += item.LengthB; } } } string sDirA, sDirB; IDirectoryInfo dirA = null, dirB = null; bool dirA_Exists = false; bool dirB_Exists = false; try { if (node.InA) { sDirA = root.Source.Combine(root.RootPathA, node.BasePath); dirA = root.Source.CreateDirectory(sDirA); dirA_Exists = dirA.Exists; } } catch // This may throw on non-existing, authorization issues { // So, we catch it it and ignore these for now dirA_Exists = false; } try { if (node.InB) { sDirB = root.Source.Combine(root.RootPathB, node.BasePath); dirB = root.Source.CreateDirectory(sDirB); dirB_Exists = dirB.Exists; } } catch // This may throw on non-existing, authorization issues { // So, we catch it it and ignore these for now dirB_Exists = false; } if (dirA_Exists == true || dirB_Exists == true) { // Get the arrays of files and merge them into 1 list IFileInfo[] filesA, filesB; Merge.MergeIndex mergeIdx = null; if (root.Filter == null) { if (dirA_Exists) { filesA = dirA.GetFiles(); } else { filesA = null; } if (dirB_Exists) { filesB = dirB.GetFiles(); } else { filesB = null; } mergeIdx = new Merge.MergeIndex(filesA, filesB, false, _ShowOnlyInA, _ShowOnlyInB); } else { if (dirA_Exists) { filesA = root.Filter.Filter(dirA); } else { filesA = null; } if (dirB_Exists) { filesB = root.Filter.Filter(dirB); } else { filesB = null; } // Assumption: Filter generates sorted entries mergeIdx = new Merge.MergeIndex(filesA, filesB, true, _ShowOnlyInA, _ShowOnlyInB); } // Merge and Diff them mergeIdx.Merge(); double lengthSumA, lengthSumB; DiffFiles(root, mergeIdx, node, checkIfFilesAreDifferent, out lengthSumA, out lengthSumB); // Add size of files to size of this directory (which includes size of sub-directories) if (dirA_Exists) { node.LengthA += lengthSumA; } if (dirB_Exists) { node.LengthB += lengthSumB; } node.SetDiffBasedOnChildren(_IgnoreDirectoryComparison); } } toVisit.Pop(); } }
private static void GetBinaryFileLines(FileCompInfo fileA, FileCompInfo fileB, TextBinaryDiffArgs args, IDiffProgress progress, out IList <string> a, out IList <string> b, out int leadingCharactersToIgnore) { a = new List <string>(); b = new List <string>(); leadingCharactersToIgnore = BinaryDiffLines.PrefixLength; // Neither left nor right file exist or cannot be accessed if (fileA.FileExists == false && fileB.FileExists == false) { return; } Stream fileStreamA = null, fileStreamB = null; try { // Open the file or an internal empty stream to compare against if (fileA.FileExists) { fileStreamA = File.OpenRead(fileA.FileNamePath); } else { fileStreamA = Assembly.GetExecutingAssembly().GetManifestResourceStream("AehnlichLib.Binaries.Resources.NonExistingFile.bin"); } // Open the file or an internal empty stream to compare against if (fileB.FileExists) { fileStreamB = File.OpenRead(fileB.FileNamePath); } else { fileStreamB = Assembly.GetExecutingAssembly().GetManifestResourceStream("AehnlichLib.Binaries.Resources.NonExistingFile.bin"); } BinaryDiff diff = new BinaryDiff { FootprintLength = args.BinaryFootprintLength }; AddCopyCollection addCopy = diff.Execute(fileStreamA, fileStreamB, progress); BinaryDiffLines lines = new BinaryDiffLines(fileStreamA, addCopy, args.BinaryFootprintLength); a = lines.BaseLines; b = lines.VersionLines; leadingCharactersToIgnore = BinaryDiffLines.PrefixLength; } finally { if (fileStreamA != null) { fileStreamA.Dispose(); } if (fileStreamB != null) { fileStreamB.Dispose(); } } return; }
private static void GetFileLines(FileCompInfo fileA, FileCompInfo fileB, out IList <string> a, out IList <string> b, out int leadingCharactersToIgnore, TextBinaryDiffArgs args, IDiffProgress progress) { a = null; b = null; leadingCharactersToIgnore = 0; CompareType compareType = args.CompareType; // Nothing to compare if both files do not exist if (fileA.FileExists == false && fileB.FileExists == false) { a = new List <string>(); b = new List <string>(); return; } if (compareType == CompareType.Binary || (args.IsAuto && fileA.Is == FileType.Binary || fileB.Is == FileType.Binary)) { GetBinaryFileLines(fileA, fileB, args, progress, out a, out b, out leadingCharactersToIgnore); return; } if (compareType == CompareType.Xml || (args.IsAuto && (a == null || b == null))) { a = fileA.TryGetXmlLines(DiffUtility.GetXmlTextLines, !args.IsAuto, args, progress); // If A failed to parse with Auto, then there's no reason to try B. if (fileA.Is == FileType.Xml) { b = fileB.TryGetXmlLines(DiffUtility.GetXmlTextLines, !args.IsAuto, args, progress); } // If we get here and the compare type was XML, then both // inputs parsed correctly, and both lists should be non-null. // If we get here and the compare type was Auto, then one // or both lists may be null, so we'll fallthrough to the text // handling logic. } if (fileA.Is != FileType.Xml || fileB.Is != FileType.Xml) { if (fileA.FileExists) { a = DiffUtility.GetFileTextLines(fileA.FileNamePath, progress); } else { a = new List <string>(); } if (fileB.FileExists) { b = DiffUtility.GetFileTextLines(fileB.FileNamePath, progress); } else { b = new List <string>(); } } }
private void GetMatchPoints(SubArray <T> subArrayA, SubArray <T> subArrayB, List <Point> matchPoints, IDiffProgress progress) { if (progress != null) { progress.Token.ThrowIfCancellationRequested(); } if (subArrayA.Length > 0 && subArrayB.Length > 0) { // Find the middle snake from (x,y) to (u,v) int x, u, k; int d = this.FindMiddleSnake(subArrayA, subArrayB, progress, out x, out u, out k); int y = x - k; int v = u - k; if (d > 1) { this.GetMatchPoints(new SubArray <T>(subArrayA, 1, x), new SubArray <T>(subArrayB, 1, y), matchPoints, progress); for (int i = x + 1; i <= u; i++) { // Output absolute X and Y (not relative to the current subarray) matchPoints.Add(new Point(i + subArrayA.Offset, i - k + subArrayB.Offset)); } this.GetMatchPoints( new SubArray <T>(subArrayA, u + 1, subArrayA.Length - u), new SubArray <T>(subArrayB, v + 1, subArrayB.Length - v), matchPoints, progress); } else { // If there are no differences, we have to output all of the points. // If there's only one difference, we have to output all of the // match points, skipping the single point that is different. Debug.Assert(d == 0 || Math.Abs(subArrayA.Length - subArrayB.Length) == 1, "A and B's lengths must differ by 1 if D == 1"); // Only go to the minimum of the two lengths since that's the // most that can possibly match between the two subsequences. int n = subArrayA.Length; int m = subArrayB.Length; if (m > n) { // Output A[1..N] as match points int currentY = 1; for (int i = 1; i <= n; i++) { // We must skip the one difference when we hit it if (subArrayA[i].CompareTo(subArrayB[currentY]) != 0) { currentY++; } matchPoints.Add(new Point(i + subArrayA.Offset, currentY + subArrayB.Offset)); currentY++; } } else { // Output B[1..M] as match points int currentX = 1; for (int i = 1; i <= m; i++) { // We must skip the one difference when we hit it if (subArrayA[currentX].CompareTo(subArrayB[i]) != 0) { currentX++; } matchPoints.Add(new Point(currentX + subArrayA.Offset, i + subArrayB.Offset)); currentX++; } } } } }