readLastNLineOffsets reads all line offsets from the reader, keeping only the last maxLines in a sliding window. keepFirst indicates whether offset 0 should be included (true if starting from file beginning). Returns the offsets and the total number of lines found.
(rs io.ReadSeeker, maxLines int, keepFirst bool)
| 60 | // keepFirst indicates whether offset 0 should be included (true if starting from file beginning). |
| 61 | // Returns the offsets and the total number of lines found. |
| 62 | func ReadLastNLineOffsets(rs io.ReadSeeker, maxLines int, keepFirst bool) ([]int64, int, error) { |
| 63 | if _, err := rs.Seek(0, io.SeekStart); err != nil { |
| 64 | return nil, 0, err |
| 65 | } |
| 66 | |
| 67 | var offsets []int64 |
| 68 | reader := bufio.NewReader(rs) |
| 69 | var currentPos int64 = 0 |
| 70 | totalLines := 0 |
| 71 | |
| 72 | if keepFirst { |
| 73 | offsets = append(offsets, 0) |
| 74 | totalLines = 1 |
| 75 | } |
| 76 | |
| 77 | for { |
| 78 | line, err := reader.ReadBytes('\n') |
| 79 | |
| 80 | if len(line) > 0 { |
| 81 | currentPos += int64(len(line)) |
| 82 | offsets = append(offsets, currentPos) |
| 83 | totalLines++ |
| 84 | // Keep maxLines+1 for sliding window (extra slot for EOF position) |
| 85 | if len(offsets) > maxLines+1 { |
| 86 | offsets = offsets[1:] |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | if err == io.EOF { |
| 91 | break |
| 92 | } |
| 93 | if err != nil { |
| 94 | return nil, 0, err |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Trim the final EOF offset if we have one |
| 99 | if len(offsets) > 0 { |
| 100 | offsets = offsets[:len(offsets)-1] |
| 101 | totalLines-- |
| 102 | } |
| 103 | |
| 104 | return offsets, totalLines, nil |
| 105 | } |
| 106 | |
| 107 | // readTailLinesInternal reads the last lineCount lines from the reader, excluding the last lineOffset lines. |
| 108 | // For example, lineCount=10 and lineOffset=5 would return lines -15 through -6 (the 10 lines before the last 5). |
no outgoing calls
no test coverage detected