/// <summary> /// Find all instances of the search pattern stored in <paramref /// name="compiledTextSearchData"/> within the passed in <paramref /// name="textRange"/> /// </summary> public IList<TextRange> FindAll( CompiledTextSearchData compiledTextSearchData, TextRange textRange, IOperationProgressTracker progressTracker) { var textFragment = CreateFragmentFromRange(textRange); var providerForMainEntry = compiledTextSearchData .GetSearchContainer(compiledTextSearchData.ParsedSearchString.MainEntry); var textSearch = GetCompiledTextSearch(providerForMainEntry); var postProcessSearchHit = CreateFilterForOtherEntries(compiledTextSearchData); var result = textSearch.FindAll(textFragment, postProcessSearchHit, progressTracker); return result; }
private unsafe List<TextRange> FindWorker( TextFragment textFragment, Func<TextRange, TextRange?> postProcess, IOperationProgressTracker progressTracker, int maxResultSize) { List<TextRange> result = null; // Note: From C# spec: If E is zero, then no allocation is made, and // the pointer returned is implementation-defined. byte* searchBuffer = stackalloc byte[this.SearchBufferSize]; var searchParams = new NativeMethods.SearchParams { TextStart = textFragment.StartPtr, TextLength = textFragment.Length, SearchBuffer = new IntPtr(searchBuffer), }; while (true) { // Perform next search Search(ref searchParams); if (searchParams.MatchStart == IntPtr.Zero) break; // Convert match from *byte* pointers to a *text* range var matchFragment = textFragment.Sub(searchParams.MatchStart, searchParams.MatchLength); var matchRange = new TextRange(matchFragment.Position, matchFragment.Length); // Post process match, maybe skipping it var postMatchRange = postProcess(matchRange); if (postMatchRange == null) continue; matchRange = postMatchRange.Value; // Add to result collection if (result == null) result = new List<TextRange>(); result.Add(matchRange); // Check it is time to end processing early. maxResultSize--; progressTracker.AddResults(1); if (maxResultSize <= 0 || progressTracker.ShouldEndProcessing) { CancelSearch(ref searchParams); break; } } return result ?? NoResult; }
public TextRange? FilterSearchHit(TextRange match) { var lineExtentStart = _getLineExtentCache.GetLineExtent(match.Position); var lineExtentEnd = _getLineExtentCache.GetLineExtent(match.EndPosition); var lineExtent = new TextRange( lineExtentStart.Position, lineExtentEnd.EndPosition - lineExtentStart.Position); if (_previousMatch.HasValue) { // If match overlaps with previous one, fail if (match.Position < _previousMatch.Value.EndPosition) { return null; } // If line extent overlaps with previous match, shrink it. if (lineExtent.Position < _previousMatch.Value.EndPosition) { lineExtent = new TextRange( _previousMatch.Value.EndPosition, lineExtent.EndPosition - _previousMatch.Value.EndPosition); } } // We got the line extent, the offset at which we found the MainEntry. // Now we need to check that "OtherEntries" are present (in order) and // in appropriate intervals. var range1 = new TextRange( lineExtent.Position, match.Position - lineExtent.Position); var entriesInterval1 = _parsedSearchString.EntriesBeforeMainEntry; var foundRange1 = entriesInterval1.Any() ? CheckEntriesInRange(range1, entriesInterval1) : match; var range2 = new TextRange( match.EndPosition, lineExtent.EndPosition - match.EndPosition); var entriesInterval2 = _parsedSearchString.EntriesAfterMainEntry; var foundRange2 = entriesInterval2.Any() ? CheckEntriesInRange(range2, entriesInterval2) : match; if (foundRange1.HasValue && foundRange2.HasValue) { var newMatch = new TextRange( foundRange1.Value.Position, foundRange2.Value.EndPosition - foundRange1.Value.Position); // Save the this match for next iteration _previousMatch = newMatch; return newMatch; } return null; }
public FileContentsPiece CreatePiece(FileName fileName, int fileId, TextRange range) { return new FileContentsPiece(fileName, this, fileId, range); }
private TextFragment CreateFragmentFromRange(TextRange textRange) { return TextFragment.Sub(textRange.Position, textRange.Length); }
public FileContentsPiece(FileName fileName, FileContents fileContents, int fileId, TextRange textRange) { _fileName = fileName; _fileContents = fileContents; _fileId = fileId; _textRange = textRange; }
/// <summary> /// Create chunks of 100KB for files larger than 100KB. /// </summary> private static IEnumerable<FileContentsPiece> SplitFileContents(FileData fileData, int fileId) { var range = fileData.Contents.TextRange; while (range.Length > 0) { // TODO(rpaquay): Be smarter and split around new lines characters. var chunkLength = Math.Min(range.Length, ChunkSize); var chunk = new TextRange(range.Position, chunkLength); yield return fileData.Contents.CreatePiece(fileData.FileName, fileId, chunk); range = new TextRange(chunk.EndPosition, range.EndPosition - chunk.EndPosition); } }
private TextRange? CheckEntriesInRange( TextRange textRange, IEnumerable<ParsedSearchString.Entry> entries) { TextRange? result = null; foreach (var entry in entries) { var entryRange = _findEntry(textRange, entry); if (entryRange == null) { return null; } var newOffset = entryRange.Value.EndPosition; textRange = new TextRange(newOffset, textRange.EndPosition - newOffset); if (result == null) { result = entryRange; } else { result = new TextRange(result.Value.Position, newOffset - result.Value.Position); } } return result; }