private bool ScanFileForMatches(string Filename) // scan through the specified file to look for search text matches { Regex regex = null; if (Globals.bRegEx) { regex = new Regex(Globals.SearchString, Globals.bCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); } StreamReader sr = null; try { sr = new StreamReader(Filename, true); } catch (Exception e) { Console.WriteLine("ScanFileForMatches() Exception: {0}", e.Message); return(false); } bool bFoundMatchInFile = false; int LineNumber = 0; int NumberOfMatchesInFile = 0; string[] PreviewLines = new string[5]; // circular buffer of preview lines (for displaying before and after matches) int PreviewLineIndex = -1; // we haven't added a line to the circular buffer yet int PreviewLineCount = 0; // number of lines in the preview circular buffer that are valid int LinesSinceMatch = -1; // reset this to 0 when we find a match so we know when to store "after" preview lines following a match string line = ""; while (!Globals.bShouldStopWorkerJobs && (sr.Peek() >= 0)) { line = ReadLine(sr); LineNumber++; ReadLineSleepCount++; if (ReadLineSleepCount >= 1000) { ReadLineSleepCount = 0; Thread.Sleep(0); // force context switch } int MatchesInLine = 0; if (Globals.bRegEx && (regex != null)) { MatchCollection matches = regex.Matches(line); MatchesInLine = matches.Count; if (matches.Count > 0) { List <MatchPos> Matches = new List <MatchPos>(); for (int i = 0; i < matches.Count; i++) { MatchPos Match = new MatchPos(matches[i].Index, matches[i].Length); Matches.Add(Match); } AddMatchLine(ref line, ref Matches, ref PreviewLines, ref PreviewLineIndex, ref PreviewLineCount, ref LineNumber, ref LinesSinceMatch); } } else { int pos = line.IndexOf(Globals.SearchString, 0, Globals.bCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); if (pos >= 0) { List <MatchPos> Matches = new List <MatchPos>(); while (pos >= 0) { if (Globals.bShouldStopWorkerJobs) { sr.Close(); return(false); } MatchesInLine++; MatchPos Match = new MatchPos(pos, Globals.SearchString.Length); Matches.Add(Match); if (pos < (line.Length - 1)) { pos = line.IndexOf(Globals.SearchString, pos + 1, Globals.bCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); } else { pos = -1; } } AddMatchLine(ref line, ref Matches, ref PreviewLines, ref PreviewLineIndex, ref PreviewLineCount, ref LineNumber, ref LinesSinceMatch); } } if (MatchesInLine > 0) { bFoundMatchInFile = true; } else // if no matches, add this line to the circular preview buffer { PreviewLineIndex = (PreviewLineIndex + 1) % 5; PreviewLines[PreviewLineIndex] = line; PreviewLineCount = Math.Min(PreviewLineCount + 1, 5); if (LinesSinceMatch >= 0) { LinesSinceMatch++; try { if ((LinesSinceMatch == 5) || (sr.Peek() == -1)) // if we're read 5 lines or reached the end of the file... { int PreviewIndex = PreviewLineIndex - (PreviewLineCount - 1); // index in the circular buffer of the oldest preview line if (PreviewIndex < 0) { PreviewIndex += 5; } for (int index = 0; index < PreviewLineCount; index++) { Globals.SearchLine PreviewSearchLine = new Globals.SearchLine(); PreviewSearchLine.LineNumber = LineNumber - (PreviewLineCount - index) + 1; PreviewSearchLine.Line = PreviewLines[PreviewIndex++]; if (PreviewIndex == 5) { PreviewIndex = 0; } PreviewSearchLine.bIsSearchTextMatch = false; Globals.SearchFiles[SearchFilesIndex].Lines.Add(PreviewSearchLine); } PreviewLineIndex = -1; // reset the circular buffer PreviewLineCount = 0; LinesSinceMatch = -1; } } catch (Exception e) { Console.WriteLine("ScanFileForMatches() Exception: {0}", e.Message); } } } NumberOfMatchesInFile += MatchesInLine; } try { sr.Close(); } catch (Exception e) { Console.WriteLine("ScanFileForMatches() Exception: {0}", e.Message); } if (Globals.bShouldStopWorkerJobs) { return(false); } Globals.SearchFiles[SearchFilesIndex].SearchMatchCount = NumberOfMatchesInFile; return(bFoundMatchInFile); }
// add a line of text that contains search text match(es) to the 'Lines' list in the SearchFile private void AddMatchLine(ref string line, ref List <MatchPos> Matches, ref string[] PreviewLines, ref int PreviewLineIndex, ref int PreviewLineCount, ref int LineNumber, ref int LinesSinceMatch) { if (Globals.SearchFiles[SearchFilesIndex].Lines == null) { Globals.SearchFiles[SearchFilesIndex].Lines = new List <Globals.SearchLine>(); } if (PreviewLineCount > 0) { int PreviewIndex = PreviewLineIndex - (PreviewLineCount - 1); // index in the circular buffer of the oldest preview line if (PreviewIndex < 0) { PreviewIndex += 5; } for (int index = 0; index < PreviewLineCount; index++) { Globals.SearchLine PreviewSearchLine = new Globals.SearchLine(); PreviewSearchLine.LineNumber = LineNumber - (PreviewLineCount - index); PreviewSearchLine.Line = PreviewLines[PreviewIndex++]; if (PreviewIndex == 5) { PreviewIndex = 0; } PreviewSearchLine.bIsSearchTextMatch = false; PreviewSearchLine.LinesBeforeNextMatch = -1; Globals.SearchFiles[SearchFilesIndex].Lines.Add(PreviewSearchLine); } } Globals.SearchLine SearchLine = new Globals.SearchLine(); SearchLine.LineNumber = LineNumber; SearchLine.Line = line; SearchLine.bIsSearchTextMatch = true; SearchLine.SearchMatchPositions = new List <Globals.SearchMatchPosition>(); SearchLine.LinesBeforeNextMatch = 0; for (int index = 0; index < Matches.Count; index++) { Globals.SearchMatchPosition SearchMatchPosition = new Globals.SearchMatchPosition(); SearchMatchPosition.StartPos = Matches[index].StartPos; SearchMatchPosition.Length = Matches[index].Length; SearchLine.SearchMatchPositions.Add(SearchMatchPosition); } Globals.SearchFiles[SearchFilesIndex].Lines.Add(SearchLine); Globals.SearchFiles[SearchFilesIndex].Matches += Matches.Count; // go back through (up to 5) previous Lines to indicate their position relative to this match int CurrentLineIndex = Globals.SearchFiles[SearchFilesIndex].Lines.Count - 1; for (int index = 1; (index <= 5) && ((CurrentLineIndex - index) >= 0); index++) { if (Globals.SearchFiles[SearchFilesIndex].Lines[CurrentLineIndex - index].bIsSearchTextMatch) { break; } Globals.SearchFiles[SearchFilesIndex].Lines[CurrentLineIndex - index].LinesBeforeNextMatch = index; } PreviewLineIndex = -1; // reset the circular buffer PreviewLineCount = 0; LinesSinceMatch = 0; }