waveterm/pkg/utilds/readerlinebuffer.go
Mike Sawka 50cc08a769
add tsunami view in wave (#2350)
checkpoint.  good to merge.  we have a working tsunami view inside of wave (with lots of caveats).  but enough for some dev testing.  merge so we dont drift too far from main and while we're at a stable point.
2025-09-15 12:58:59 -07:00

122 lines
2.2 KiB
Go

package utilds
import (
"bufio"
"io"
"sync"
)
type ReaderLineBuffer struct {
lock sync.Mutex
lines []string
maxLines int
totalLineCount int
reader io.Reader
scanner *bufio.Scanner
done bool
lineCallback func(string)
}
func MakeReaderLineBuffer(reader io.Reader, maxLines int) *ReaderLineBuffer {
if maxLines <= 0 {
maxLines = 1000 // default max lines
}
rlb := &ReaderLineBuffer{
lines: make([]string, 0, maxLines),
maxLines: maxLines,
totalLineCount: 0,
reader: reader,
scanner: bufio.NewScanner(reader),
done: false,
}
return rlb
}
func (rlb *ReaderLineBuffer) SetLineCallback(callback func(string)) {
rlb.lock.Lock()
defer rlb.lock.Unlock()
rlb.lineCallback = callback
}
func (rlb *ReaderLineBuffer) IsDone() bool {
rlb.lock.Lock()
defer rlb.lock.Unlock()
return rlb.done
}
func (rlb *ReaderLineBuffer) setDone() {
rlb.lock.Lock()
defer rlb.lock.Unlock()
rlb.done = true
}
func (rlb *ReaderLineBuffer) ReadLine() (string, error) {
if rlb.IsDone() {
return "", io.EOF
}
if rlb.scanner.Scan() {
line := rlb.scanner.Text()
rlb.addLine(line)
return line, nil
}
// Check for scanner error
if err := rlb.scanner.Err(); err != nil {
rlb.setDone()
return "", err
}
rlb.setDone()
return "", io.EOF
}
func (rlb *ReaderLineBuffer) addLine(line string) {
rlb.lock.Lock()
defer rlb.lock.Unlock()
rlb.totalLineCount++
if len(rlb.lines) >= rlb.maxLines {
rlb.lines = append(rlb.lines[1:], line)
} else {
rlb.lines = append(rlb.lines, line)
}
}
func (rlb *ReaderLineBuffer) GetLines() []string {
rlb.lock.Lock()
defer rlb.lock.Unlock()
result := make([]string, len(rlb.lines))
copy(result, rlb.lines)
return result
}
func (rlb *ReaderLineBuffer) GetLineCount() int {
rlb.lock.Lock()
defer rlb.lock.Unlock()
return len(rlb.lines)
}
func (rlb *ReaderLineBuffer) GetTotalLineCount() int {
rlb.lock.Lock()
defer rlb.lock.Unlock()
return rlb.totalLineCount
}
func (rlb *ReaderLineBuffer) ReadAll() {
for {
line, err := rlb.ReadLine()
if err != nil {
break
}
if rlb.lineCallback != nil {
rlb.lineCallback(line)
}
}
}