Removed utf8.DecodeRune calls for < RuneSelf

pull/53/head
rwxrob 2 years ago
parent 557d499f87
commit 6ae30d52ca
No known key found for this signature in database
GPG Key ID: 2B9111F33082AE77

@ -32,7 +32,8 @@ import (
type Scanner struct {
// Buf is the data buffer providing infinite look-ahead and behind.
Buf []byte
Buf []byte
BufLen int
// Cur is the active current cursor pointing to the Buf data.
Cur *Cur
@ -65,53 +66,69 @@ func New(i any) (*Scanner, error) {
// scanner appropriately returning an error if anything happens while
// attempting to read and buffer the data (OOM, etc.).
func (s *Scanner) Init(i any) error {
s.Cur = new(Cur)
s.Cur.Pos = Pos{}
s.Cur.Pos.Line = 1
s.Cur.Pos.LineRune = 1
s.Cur.Pos.LineByte = 1
s.Cur.Pos.Rune = 1
if err := s.buffer(i); err != nil {
return err
}
r, ln := utf8.DecodeRune(s.Buf) // scan first
if ln == 0 {
r = tk.EOD
return fmt.Errorf("scanner: failed to scan first rune")
}
s.Cur = new(Cur)
s.Cur.Rune = r
s.Cur.Len = ln
s.Cur.Next = ln
s.Cur.Pos.Line = 1
s.Cur.Pos.LineRune = 1
s.Cur.Pos.LineByte = 1
s.Cur.Pos.Rune = 1
return nil
}
// reads and buffers io.Reader, string, or []byte types
func (s *Scanner) buffer(i any) error {
var err error
switch in := i.(type) {
switch v := i.(type) {
case io.Reader:
s.Buf, err = io.ReadAll(in)
s.Buf, err = io.ReadAll(v)
if err != nil {
return err
}
case string:
s.Buf = []byte(in)
s.Buf = []byte(v)
case []byte:
s.Buf = in
s.Buf = v
default:
return fmt.Errorf("scanner: unsupported input type: %t", i)
}
if len(s.Buf) == 0 {
s.BufLen = len(s.Buf)
if s.BufLen == 0 {
return fmt.Errorf("scanner: no input")
}
return err
}
// Scan decodes the next rune and advances the scanner cursor by one.
// The method of scanning isn't as optimized as other scanner (for
// example, the scanner from the bonzai/json package), but it is
// sufficient for most high level needs.
func (s *Scanner) Scan() {
if s.Done() {
if s.Cur.Next == s.BufLen {
s.Cur.Rune = tk.EOD
return
}
r, ln := utf8.DecodeRune(s.Buf[s.Cur.Next:])
ln := 1
r := rune(s.Buf[s.Cur.Next])
if r > utf8.RuneSelf {
r, ln = utf8.DecodeRune(s.Buf[s.Cur.Next:])
}
if ln != 0 {
s.Cur.Byte = s.Cur.Next
s.Cur.Pos.LineByte += s.Cur.Len
@ -126,19 +143,13 @@ func (s *Scanner) Scan() {
}
// ScanN scans the next n runes advancing n runes forward or returns
// s.Done() if attempted after already at end of data.
// EOD if attempted after already at end of data.
func (s *Scanner) ScanN(n int) {
for i := 0; i < n; i++ {
s.Scan()
}
}
// Done returns true if current cursor rune is tk.EOD and the cursor length
// is also zero.
func (s *Scanner) Done() bool {
return s.Cur.Rune == tk.EOD && s.Cur.Len == 0
}
// String delegates to internal cursor String.
func (s *Scanner) String() string { return s.Cur.String() }
@ -378,7 +389,7 @@ func (s *Scanner) Expect(scannables ...any) (*Cur, error) {
func (s *Scanner) ErrorExpected(this any, args ...any) error {
var msg string
but := fmt.Sprintf(` at %v`, s)
if s.Done() {
if s.Cur != nil && s.Cur.Rune == tk.EOD && s.Cur.Len == 0 {
runes := `runes`
if s.Cur.Pos.Rune == 1 {
runes = `rune`

@ -29,11 +29,9 @@ func ExampleNew_bytes() {
s.Print()
s.ScanN(3)
s.Print()
fmt.Println(s.Done())
//Output:
// U+0073 's' 1,1-1 (1-1)
// <EOD>
// true
}
func ExampleNew_reader() {
@ -73,8 +71,6 @@ func ExampleMark() {
fmt.Println(err)
}
m := s.Mark()
//log.Printf("%p", s.Cur)
//log.Printf("%p", m)
fmt.Println(s.Cur != m)
// Output:
// true
@ -179,17 +175,13 @@ func ExampleExpect_basic() {
s, _ := scan.New("some thing")
c, _ := s.Expect("some", ' ', "thin")
c.Print()
fmt.Println(s.Done())
s.Print()
s.Scan()
s.Print()
fmt.Println(s.Done())
// Output:
// U+006E 'n' 1,9-9 (9-9)
// false
// U+0067 'g' 1,10-10 (10-10)
// <EOD>
// true
}
func ExampleCheck() {
@ -353,3 +345,14 @@ func ExampleSnap() {
// U+0069 'i' 1,8-8 (8-8)
// U+0065 'e' 1,4-4 (4-4)
}
func ExampleScan() {
s, _ := scan.New(`s😈me thing`)
s.Scan()
s.Print()
s.Scan()
s.Print()
// Output:
// U+1F608 '😈' 1,2-2 (2-2)
// U+006D 'm' 1,3-6 (3-6)
}

Loading…
Cancel
Save