go-eol/readeol.go

108 lines
2.8 KiB
Go
Raw Normal View History

2023-11-27 15:13:38 +00:00
package eol
import (
"io"
2023-11-28 16:09:58 +00:00
"sourcecode.social/reiver/go-opt"
2024-02-18 17:09:29 +00:00
"sourcecode.social/reiver/go-eol/cr"
2024-02-18 17:27:47 +00:00
"sourcecode.social/reiver/go-eol/crlf"
2024-02-18 17:09:29 +00:00
"sourcecode.social/reiver/go-eol/lf"
"sourcecode.social/reiver/go-eol/ls"
"sourcecode.social/reiver/go-eol/nel"
2023-11-27 15:13:38 +00:00
)
2023-11-28 16:14:55 +00:00
// ReadEOL tries to read an end-of-line sequence.
2023-11-27 15:13:38 +00:00
//
// The end-of-line sequences it supports are:
//
2023-11-27 19:20:41 +00:00
// line-feed (LF) (U+000A) ('\n')
// carriage-return (CR) (U+000D) ('\r')
2023-11-27 15:13:38 +00:00
// carriage-return, line-feed ("\r\n")
2023-11-27 19:20:41 +00:00
// next-line (NEL) (U+0085)
// line-separator (LS) (U+2028)
2023-11-27 15:13:38 +00:00
//
2023-11-28 16:10:46 +00:00
// If successful, ReadEOL return the end-of-line sequence it found and the number-of-bytes read (to read in end-of-line sequence it found).
2023-11-28 16:14:55 +00:00
//
// Example usage:
///
2023-11-29 14:57:58 +00:00
// eolSequence, size, err := eol.ReadEOL(runescanner)
2023-11-27 15:13:38 +00:00
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 {
2023-11-28 16:09:58 +00:00
const characterNumber uint64 = 1
var eolSequence opt.Optional[string] // = opt.Nothing[string]() // i.e., unknown
var circumstance internalCircumstance = specifyCircumstance(eolSequence, characterNumber)
return "", size0, errProblemReadingRune(circumstance, err)
2023-11-27 15:13:38 +00:00
}
}
switch r0 {
2024-02-18 17:09:29 +00:00
case lf.Rune:
2024-02-18 17:27:47 +00:00
return lf.String, size0, nil
2024-02-18 17:09:29 +00:00
case cr.Rune:
2023-11-27 15:13:38 +00:00
// Nothing here.
2024-02-18 17:09:29 +00:00
case nel.Rune:
2024-02-18 17:27:47 +00:00
return nel.String, size0, nil
2024-02-18 17:09:29 +00:00
case ls.Rune:
2024-02-18 17:27:47 +00:00
return ls.String, size0, nil
2023-11-27 15:13:38 +00:00
default:
err := runescanner.UnreadRune()
if nil != err {
2023-11-28 16:09:58 +00:00
const characterNumber uint64 = 1
var eolSequence opt.Optional[string] // = opt.Nothing[string]() // i.e., unknown
var circumstance internalCircumstance = specifyCircumstance(eolSequence, characterNumber)
return "", size0, errProblemUnreadingRune(circumstance, err, r0)
2023-11-27 15:13:38 +00:00
}
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 {
2024-02-18 17:27:47 +00:00
return cr.String, size0, nil
2023-11-27 15:13:38 +00:00
}
if nil != err {
2023-11-28 16:09:58 +00:00
const characterNumber uint64 = 2
var eolSequence opt.Optional[string] // = opt.Nothing[string]() // i.e., unknown
var circumstance internalCircumstance = specifyCircumstance(eolSequence, characterNumber)
return "", size1+size0, errProblemReadingRune(circumstance, err)
2023-11-27 15:13:38 +00:00
}
}
switch r1 {
2024-02-18 17:09:29 +00:00
case lf.Rune:
2024-02-18 17:27:47 +00:00
return crlf.String, size1+size0, nil
2023-11-27 15:13:38 +00:00
default:
err := runescanner.UnreadRune()
if nil != err {
2023-11-28 16:09:58 +00:00
const characterNumber uint64 = 2
var eolSequence opt.Optional[string] // = opt.Nothing[string]() // i.e., unknown
var circumstance internalCircumstance = specifyCircumstance(eolSequence, characterNumber)
return "", size1+size0, errProblemUnreadingRune(circumstance, err, r1)
2023-11-27 15:13:38 +00:00
}
2024-02-18 17:27:47 +00:00
return cr.String, size0, nil
2023-11-27 15:13:38 +00:00
}
}