go-eol/readeol.go

84 lines
1.6 KiB
Go

package eol
import (
"io"
)
// ReadEOL tries to read and end-of-line character.
//
// The end-of-line sequences it supports are:
//
// line-feed (LF) (U+000A) ('\n')
// carriage-return (CR) (U+000D) ('\r')
// carriage-return, line-feed ("\r\n")
// next-line (NEL) (U+0085)
// line-separator (LS) (U+2028)
//
// If successful, ReadEOL return the end-of-line sequence and the number-of-bytes read.
func ReadEOL(runescanner io.RuneScanner) (endofline string, size int, err error) {
if nil == runescanner {
return "", 0, errNilRuneScanner
}
var r0 rune
var size0 int
{
var err error
r0, size0, err = runescanner.ReadRune()
if nil != err {
const runeNumber = 1
return "", size0, errProblemReadingRune(err, runeNumber)
}
}
switch r0 {
case lf:
return LF, size0, nil
case cr:
// Nothing here.
case nel:
return NEL, size0, nil
case ls:
return LS, size0, nil
default:
err := runescanner.UnreadRune()
if nil != err {
const runeNumber = 1
return "", size0, errProblemUnreadingRune(err, runeNumber, r0)
}
return "", 0, errNotEOL(r0)
}
// if we got here, then we had a CR
var r1 rune
var size1 int
{
var err error
r1, size1, err = runescanner.ReadRune()
if io.EOF == err {
return CR, size0, nil
}
if nil != err {
const runeNumber = 2
return "", size1+size0, errProblemReadingRune(err, runeNumber)
}
}
switch r1 {
case lf:
return CRLF, size1+size0, nil
default:
err := runescanner.UnreadRune()
if nil != err {
const runeNumber = 2
return "", size1+size0, errProblemUnreadingRune(err, runeNumber, r1)
}
return CR, size0, nil
}
}