示例#1
0
        private void FlushLogicalLine(LogicalLinesHistoryQueue logicalLinesHistoryQueue = null)
        {
            if (_logicalLine.IsEmpty)
            {
                return;
            }

            _logicalLine.IsVisible = !ShouldBeHided() && ShouldBeShown();

            if (
                (_logicalLine.IsVisible || _afterCounter > 0) &&
                !SkipFromNumLines())
            {
                var forPrinting = new LogicalLinesHistoryQueue();
                PrepareLogicalLineForPrinting(_logicalLine, forPrinting);

                if (logicalLinesHistoryQueue == null)
                {
                    PrintLogicalLines(forPrinting);
                }
                else
                {
                    logicalLinesHistoryQueue.Enqueue(forPrinting);
                }

                if (_logicalLine.IsVisible)
                {
                    _afterCounter = Configs.ContextAfter;
                }
            }

            _logicalLinesHistoryQueue.Enqueue(_logicalLine);
            _logicalLine = new LogicalLine();
        }
示例#2
0
        private void ProcessStreamFromLastPosToEnd(Stream stream, LogicalLinesHistoryQueue logicalLines)
        {
            var encoding = Encoding.Default;

            if (FileType == FileTypes.Console)
            {
                if (!stream.CanRead)
                {
                    return;
                }

                encoding = Console.InputEncoding;
            }

            using var sr = new StreamReader(stream, encoding, true);
            SeekToLastPos(sr);
            var s = ReadLine(sr);

            while (s != null)
            {
                ProcessReadLine(s, logicalLines);
                s = ReadLine(sr);
            }

            // for archives, LastPos remains 0, so update-it to FileSize
            // NOTE: do not set LastPos = FileSize for files, cause FileSize is just
            //       a cached value, and do not reflect actual file size!
            if (!sr.BaseStream.CanSeek)
            {
                LastPos = FileSize;
            }
        }
示例#3
0
        public File(string file, TailPbl bl, int fileIndex)
        {
            if (string.IsNullOrEmpty(file))
            {
                throw new ArgumentException(@"Param cannot be empty", nameof(file));
            }
            _bl        = bl ?? throw new ArgumentNullException(nameof(bl));
            _file      = file;
            _fileIndex = fileIndex;
            _logicalLinesHistoryQueue = new LogicalLinesHistoryQueue(Math.Max(1, Configs.ContextBefore));
            _startFromNum             = Configs.LinesStartNumber;

            if (_file == Constants.CONSOLE_FILENAME)
            {
                _fileType = FileTypes.Console;
            }
            else if (ArchiveSupport.TryGetArchivePath(file, out var archive, out var finalFile) &&
                     ArchiveSupport.IsValidArchive(archive))
            {
                _fileType = string.IsNullOrWhiteSpace(finalFile)
                            ? FileTypes.Archive
                            : FileTypes.ArchivedFile;
            }

            UpdateFileInfo();
            ResetCounters();
        }
        public void Enqueue(LogicalLinesHistoryQueue historyQueue)
        {
            if (historyQueue is null)
            {
                throw new ArgumentNullException(nameof(historyQueue));
            }

            foreach (var line in historyQueue)
            {
                Enqueue(line);
            }
        }
示例#5
0
        private void PrepareLogicalLineForPrinting(LogicalLine logicalLine, LogicalLinesHistoryQueue prepared)
        {
            if (Configs.IsContextBeforeUsed &&
                _logicalLinesHistoryQueue.Any() &&
                _logicalLine.IsVisible)
            {
                prepared.Enqueue(_logicalLinesHistoryQueue);
                _logicalLinesHistoryQueue.Clear();
            }

            prepared.Enqueue(logicalLine);

            if (_afterCounter > 0)
            {
                --_afterCounter;
            }
        }
示例#6
0
        private void FindLastLinesInStream(Stream stream)
        {
            if (_lastLinesProcessed ||
                Configs.LinesStartFrom != NumLinesStart.End)
            {
                return;
            }

            if (_startFromNum != 0)
            {
                var logicalLinesHistory = new LogicalLinesHistoryQueue(
                    _startFromNum * (Configs.ContextLines + 1));
                if (stream.CanSeek)
                {
                    if (!ProcessStreamInPages(stream, logicalLinesHistory))
                    {
                        // optimization is not working, try without optimization
                        ResetCounters();
                        logicalLinesHistory.Clear();
                        ProcessStreamFromLastPosToEnd(stream, logicalLinesHistory);
                    }
                }
                else
                {
                    ProcessStreamFromLastPosToEnd(stream, logicalLinesHistory);
                }

                FlushLogicalLine(logicalLinesHistory);
                while (logicalLinesHistory.Any())
                {
                    var forPrinting = new LogicalLinesHistoryQueue();
                    PrepareLogicalLineForPrinting(logicalLinesHistory.Dequeue(), forPrinting);
                    PrintLogicalLines(forPrinting);
                }
            }

            LastPos             = FileSize;
            _lastLinesProcessed = true;
        }
示例#7
0
        private void ProcessReadLine(string readLine, LogicalLinesHistoryQueue logicalLinesHistoryQueue)
        {
            var isLogicalContinuation =
                !string.IsNullOrEmpty(Configs.LogicalLineMarker) &&
                (
                    readLine.Length < Configs.LogicalLineMarker.Length ||
                    readLine.Substring(0, Configs.LogicalLineMarker.Length)
                    .Contains(Configs.LogicalLineMarker, Configs.ComparisonOptions)
                );

            if (!isLogicalContinuation) // a new line begins, flush memory
            {
                ++_lineNumber;
                FlushLogicalLine(logicalLinesHistoryQueue);
            }

            var line = new Line(readLine, isLogicalContinuation, _lineNumber);

            line.CheckFilters(Configs.FiltersShow, Configs.FiltersHide, Configs.FiltersHighlight);
            AddLineNumberIfApplicable(line);
            TruncateIfApplicable(line);
            _logicalLine.Add(line);
        }
示例#8
0
        private void PrintLogicalLines(LogicalLinesHistoryQueue logicalLines)
        {
            lock (_bl.PrintLock)
            {
                PrintFileName();

                while (logicalLines.Any())
                {
                    var logicalLine = logicalLines.Dequeue();

                    if (!logicalLine.IsPrinted)
                    {
                        if (Configs.IsContextUsed &&
                            Math.Abs(logicalLine.LineNumber - _lastPrintedLine) > 1)
                        {
                            _bl.PrintLogicalLine(TailPbl.GetContextDelimiter(), _fileIndex);
                        }

                        _bl.PrintLogicalLine(logicalLine, _fileIndex);
                        _lastPrintedLine = logicalLine.LineNumber;
                    }
                }
            }
        }
示例#9
0
        // Optimization used:
        //       read from end in pages by XXX bytes to a memory stream
        //       and stops to read if _startFromNum lines found
        //
        //       Will not works, if line length is greater than PAGE_SIZE
        private bool ProcessStreamInPages(Stream stream, LogicalLinesHistoryQueue logicalLines)
        {
            if (!CanProcessInPages())
            {
                return(false);
            }

            var encoding    = DetectEncoding(stream);
            var historyDeep = _startFromNum * (Configs.ContextLines + 1);
            var foundLines  = new LogicalLinesHistoryQueue(historyDeep);
            var from        = FileSize;

            while (from != 0 && foundLines.Count != historyDeep)
            {
                var buf       = new byte[Constants.REVERS_SEARCH_PAGE_SIZE];
                var pageLines = new LogicalLinesHistoryQueue(historyDeep);

                from = Math.Max(0, from - Constants.REVERS_SEARCH_PAGE_SIZE);
                stream.Seek(from, SeekOrigin.Begin);
                var sz = stream.Read(buf, 0, Constants.REVERS_SEARCH_PAGE_SIZE);

                Stream ms = null;
                try
                {
                    ms           = new MemoryStream(buf, 0, sz);
                    using var sr = new StreamReader(ms, encoding,
                                                    from == 0 // ignore BOM only at file beginning
                                                    );
                    ms = null;                                // prevent disposing several times

                    if (from != 0)
                    {
                        var nul     = sr.ReadLine();                      // ignore first line, may be incomplete
                        var szBytes = encoding.GetByteCount(nul ?? string.Empty);
                        if (szBytes >= Constants.REVERS_SEARCH_PAGE_SIZE) // extra long line
                        {
                            return(false);
                        }
                        from += szBytes;
                    }

                    var s = sr.ReadLine();
                    while (s != null)
                    {
                        if (encoding.GetByteCount(s) >= Constants.REVERS_SEARCH_PAGE_SIZE)
                        {
                            return(false);
                        }
                        ProcessReadLine(s, pageLines);
                        s = sr.ReadLine();
                    }
                }
                finally
                {
#pragma warning disable CA1508 // Avoid dead conditional code
                    ms?.Dispose();
#pragma warning restore CA1508 // Avoid dead conditional code
                }
                FlushLogicalLine(pageLines);
                pageLines.Enqueue(foundLines);
                foundLines.ReplaceBy(pageLines);
                LastPos = FileSize - from;
            }

            logicalLines.ReplaceBy(foundLines);
            // because lines was searched in pages, line numbers are irrelevant
            logicalLines.SetLinesNumberToUnknown();

            LastPos = FileSize;

            return(true);
        }
 public void ReplaceBy(LogicalLinesHistoryQueue historyQueue)
 {
     Clear();
     Enqueue(historyQueue);
 }