readTailLinesInternal reads the last lineCount lines from the reader, excluding the last lineOffset lines. For example, lineCount=10 and lineOffset=5 would return lines -15 through -6 (the 10 lines before the last 5). keepFirst indicates whether the first line should be kept (true if starting at fil
(rs io.ReadSeeker, lineCount int, lineOffset int, keepFirst bool)
| 110 | // Returns the lines (with trailing newlines), a hasMore flag, and any error. |
| 111 | // hasMore is true if there are lines before our window (didn't hit BOF), false if we read from the very beginning. |
| 112 | func readTailLinesInternal(rs io.ReadSeeker, lineCount int, lineOffset int, keepFirst bool) ([]string, bool, error) { |
| 113 | maxOffsets := lineCount + lineOffset |
| 114 | offsets, totalLines, err := ReadLastNLineOffsets(rs, maxOffsets, keepFirst) |
| 115 | if err != nil { |
| 116 | return nil, false, err |
| 117 | } |
| 118 | |
| 119 | if totalLines <= lineOffset { |
| 120 | return []string{}, false, nil |
| 121 | } |
| 122 | |
| 123 | linesToRead := lineCount |
| 124 | if totalLines-lineOffset < lineCount { |
| 125 | linesToRead = totalLines - lineOffset |
| 126 | } |
| 127 | startIdx := len(offsets) - lineOffset - linesToRead |
| 128 | hasMore := totalLines > lineCount+lineOffset |
| 129 | |
| 130 | if _, err := rs.Seek(offsets[startIdx], io.SeekStart); err != nil { |
| 131 | return nil, false, err |
| 132 | } |
| 133 | |
| 134 | lines, _, err := ReadLines(rs, linesToRead, 0, 0) |
| 135 | if err != nil { |
| 136 | return nil, false, err |
| 137 | } |
| 138 | |
| 139 | return lines, hasMore, nil |
| 140 | } |
| 141 | |
| 142 | // ReadTailLines reads the last lineCount lines from a file, excluding the last lineOffset lines. |
| 143 | // It progressively reads larger windows from the end of the file (starting at 1MB, doubling up to readLimit) |
no test coverage detected