67 lines
1.2 KiB
Go
67 lines
1.2 KiB
Go
|
package gut
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type LineParser struct {
|
||
|
lines []string
|
||
|
i int
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
var ErrUnexpectedEnd = errors.New("unexpected end of file")
|
||
|
|
||
|
func (p *LineParser) EOF() bool { return p.i == len(p.lines) }
|
||
|
|
||
|
func (p *LineParser) EmitErr(err error) ParseLineFn {
|
||
|
p.err = err
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *LineParser) Next() string {
|
||
|
i := p.i
|
||
|
p.i++
|
||
|
return p.lines[i]
|
||
|
}
|
||
|
|
||
|
func (p *LineParser) Peek() string { return p.lines[p.i] }
|
||
|
|
||
|
func (p *LineParser) SkipSpaceEOF() bool {
|
||
|
for !p.EOF() && len(strings.TrimSpace(p.Peek())) == 0 {
|
||
|
p.Next()
|
||
|
}
|
||
|
return p.EOF()
|
||
|
}
|
||
|
|
||
|
func SkipSpaceBeforeContent(next ParseLineFn) ParseLineFn {
|
||
|
return func(p *LineParser) ParseLineFn {
|
||
|
if p.SkipSpaceEOF() {
|
||
|
return p.EmitErr(ErrUnexpectedEnd)
|
||
|
}
|
||
|
return next
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type ParseLineFn func(p *LineParser) ParseLineFn
|
||
|
|
||
|
func ParseLines(r io.Reader, fn ParseLineFn) error {
|
||
|
content, err := ioutil.ReadAll(r)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
lines := strings.Split(string(content), "\n")
|
||
|
for i, line := range lines {
|
||
|
lines[i] = strings.TrimRight(line, "\r\n")
|
||
|
}
|
||
|
|
||
|
parser := &LineParser{lines: lines}
|
||
|
for fn != nil {
|
||
|
fn = fn(parser)
|
||
|
}
|
||
|
return parser.err
|
||
|
}
|