-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathline.go
81 lines (66 loc) · 1.21 KB
/
line.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package readers
import (
"bytes"
"errors"
"io"
)
var EOL error = &eolError{}
type eolError struct{}
func (e *eolError) Error() string { return "EOL" }
func (e *eolError) Unwrap() error { return io.EOF }
type LineReader struct {
err error
r io.Reader
over []byte
}
var _ io.Reader = &LineReader{}
func NewLineReader(r io.Reader) *LineReader {
return &LineReader{nil, r, nil}
}
func (l *LineReader) Err() error {
if errors.Is(l.err, io.EOF) {
return nil
}
return l.err
}
func (l *LineReader) Next() bool {
if l.err == nil || errors.Is(l.err, EOL) {
l.err = nil
return true
}
return false
}
func (l *LineReader) Read(p []byte) (n int, err error) {
if errors.Is(l.err, EOL) {
return 0, io.EOF
}
rOver := bytes.NewBuffer(l.over)
r := io.MultiReader(rOver, l.r)
n, l.err = r.Read(p)
if l.err != nil {
err = eolToEof(l.err)
return
}
nFull := n
nStart := n
n2 := bytes.IndexByte(p, '\n')
if n2 != -1 {
l.err = EOL
n = n2
nStart = n2 + 1
}
if n > 0 && p[n-1] == '\r' {
n--
}
l.over = p[nStart:nFull]
if rOver.Len() > 0 {
l.over = append(p[nStart:nFull], rOver.Bytes()...)
}
return
}
func eolToEof(err error) error {
if errors.Is(err, EOL) {
return io.EOF
}
return err
}