private RelativeIndex CalculateRelativeIndex(int index, ref IndexCollection indexCollection, LastValueWrapper lastValueWrapper) { var firstLineInContainer = 0; var lastLineInContainer = 0; while (indexCollection != null) { foreach (var sparseIndex in indexCollection.Indicies) { lastLineInContainer += sparseIndex.LineCount; if (index < lastLineInContainer) { //It could be that the user is scrolling into a part of the file //which is still being indexed [or will never be indexed]. //In this case we need to estimate where to scroll to if (sparseIndex.LineCount != 0 && sparseIndex.Indicies.Count == 0) { //return estimate here! var lines = sparseIndex.LineCount; var bytes = sparseIndex.End - sparseIndex.Start; var bytesPerLine = bytes / lines; var estimate = index * bytesPerLine; return(new RelativeIndex(index, estimate, 0, true)); } var relativePosition = (index - firstLineInContainer); var relativeIndex = relativePosition / sparseIndex.Compression; var offset = relativePosition % sparseIndex.Compression; if (relativeIndex >= sparseIndex.IndexCount) { relativeIndex = sparseIndex.IndexCount - 1; } var start = relativeIndex == 0 ? 0 : sparseIndex.Indicies[relativeIndex - 1]; return(new RelativeIndex(index, start, offset, false)); } firstLineInContainer = firstLineInContainer + sparseIndex.LineCount; } lastValueWrapper.LastEndPosition += indexCollection.Indicies .Where(localIndex => localIndex.IndexCount > 0) .Sum(localIndex => localIndex.Indicies[localIndex.IndexCount - 1]); indexCollection = indexCollection.Previous as IndexCollection; } return(null); }
public IEnumerable <Line> ReadLines(ScrollRequest scroll) { var current = ReverseLinking(this); var page = GetPage(scroll, this); var lastValueWrapper = new LastValueWrapper(); if (page.Size == 0) { yield break; } while (current != null) { using ( var stream = File.Open(current.Info.FullName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite)) { using (var reader = new StreamReaderExtended(stream, current.Encoding, false)) { if (page.Size == 0) { yield break; } if (lastValueWrapper.LastPageIndex == page.Start + page.Size) { yield break; } var counter = 0; long lastEndPos = 0; foreach ( var i in Enumerable.Range( lastValueWrapper.LastPageIndex > 0 ? lastValueWrapper.LastPageIndex : page.Start, page.Size - counter)) { if (i == page.Start + page.Size) { yield break; } if (i - lastValueWrapper.LastMatchesSize > current.Count - 1) { lastValueWrapper.LastEndPosition += lastEndPos + 1; lastValueWrapper.LastMatchesSize += current.Count; break; } var start = current.Matches[i - lastValueWrapper.LastMatchesSize]; var startPosition = reader.AbsolutePosition(); if (startPosition != start) { reader.DiscardBufferedData(); reader.BaseStream.Seek(start, SeekOrigin.Begin); } startPosition = reader.AbsolutePosition(); var line = reader.ReadLine(); var endPosition = reader.AbsolutePosition(); var info = new LineInfo(i + 1, i, startPosition + lastValueWrapper.LastEndPosition, endPosition + lastValueWrapper.LastEndPosition); var ontail = endPosition >= TailInfo.TailStartsAt && DateTime.Now.Subtract(TailInfo.LastTail).TotalSeconds < 1 ? DateTime.Now : (DateTime?)null; yield return(new Line(info, line, ontail)); lastValueWrapper.LastPageIndex = i + 1; counter++; lastEndPos = endPosition; if (reader.EndOfStream) { lastValueWrapper.LastEndPosition += endPosition + 1; lastValueWrapper.LastMatchesSize += current.Count; break; } } } } current = current.Next as FileSearchResult; } }
private IEnumerable <Line> ReadLinesByIndex(ScrollRequest scroll) { var current = this; var lastValueWrapper = new LastValueWrapper(); var iterationCounter = 0; var page = GetPage(scroll, current); var relativeIndex = CalculateRelativeIndex(page.Start, ref current, lastValueWrapper); while (relativeIndex != null && current != null) { if (current.Indicies.Length > 0 && current.Indicies.Any(t => t.Indicies.Count == 0)) { iterationCounter++; current = current.Previous as IndexCollection; continue; } if (lastValueWrapper.LastPageIndex == page.Start + page.Size) { yield break; } var offset = relativeIndex.LinesOffset; using ( var stream = File.Open(current.Info.FullName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite)) { using (var reader = new StreamReaderExtended(stream, current.Encoding, false)) { //go to starting point stream.Seek((iterationCounter > 0) ? 0 : relativeIndex.Start, SeekOrigin.Begin); if (iterationCounter == 0 && offset > 0) { //skip number of lines offset for (var i = 0; i < offset; i++) { reader.ReadLine(); } } //if estimate move to the next start of line if (iterationCounter == 0 && relativeIndex.IsEstimate && relativeIndex.Start != 0) { reader.ReadLine(); } foreach ( var i in Enumerable.Range((iterationCounter > 0) ? lastValueWrapper.LastPageIndex : page.Start, page.Size)) { if (i == page.Start + page.Size) { yield break; } var startPosition = reader.AbsolutePosition() + lastValueWrapper.LastEndPosition; var line = reader.ReadLine(); var endPosition = reader.AbsolutePosition() + lastValueWrapper.LastEndPosition; var info = new LineInfo(i + 1, i, startPosition, endPosition); var ontail = startPosition >= current.TailInfo.TailStartsAt && DateTime.Now.Subtract(current.TailInfo.LastTail).TotalSeconds < 1 ? DateTime.Now : (DateTime?)null; yield return(new Line(info, line, ontail)); lastValueWrapper.LastPageIndex = i + 1; if (reader.EndOfStream) { lastValueWrapper.LastEndPosition += endPosition + 1; break; } } } } iterationCounter++; current = current.Previous as IndexCollection; } }