Speed improvements

This commit is contained in:
Maurice Makaay 2019-07-29 23:51:09 +00:00
parent b9cc91c0ae
commit f70bf8d074
1 changed files with 43 additions and 22 deletions

View File

@ -77,6 +77,7 @@ var A = struct {
AnyByte Handler AnyByte Handler
AnyRune Handler AnyRune Handler
ValidRune Handler ValidRune Handler
ValidRunes Handler
InvalidRune Handler InvalidRune Handler
Str func(string) Handler Str func(string) Handler
StrNoCase func(string) Handler StrNoCase func(string) Handler
@ -166,6 +167,7 @@ var A = struct {
AnyByte: MatchAnyByte(), AnyByte: MatchAnyByte(),
AnyRune: MatchAnyRune(), AnyRune: MatchAnyRune(),
ValidRune: MatchValidRune(), ValidRune: MatchValidRune(),
ValidRunes: MatchValidRunes(),
InvalidRune: MatchInvalidRune(), InvalidRune: MatchInvalidRune(),
Str: MatchStr, Str: MatchStr,
StrNoCase: MatchStrNoCase, StrNoCase: MatchStrNoCase,
@ -990,36 +992,21 @@ func MatchNotFollowedBy(lookAhead Handler, handler Handler) Handler {
} }
func MatchInOptionalBlanks(handler Handler) Handler { func MatchInOptionalBlanks(handler Handler) Handler {
blanks := MatchBlanks()
return func(tokenAPI *API) bool { return func(tokenAPI *API) bool {
skipBlanks(tokenAPI) tokenAPI.Output.Suspend()
blanks(tokenAPI)
tokenAPI.Output.Resume()
if !handler(tokenAPI) { if !handler(tokenAPI) {
return false return false
} }
skipBlanks(tokenAPI) tokenAPI.Output.Suspend()
blanks(tokenAPI)
tokenAPI.Output.Resume()
return true return true
} }
} }
func skipBlanks(tokenAPI *API) {
for {
bs, err := tokenAPI.Input.Byte.PeekMulti(0, 128)
for i, b := range bs {
if b != ' ' && b != '\t' {
if i > 0 {
tokenAPI.Input.Byte.MoveCursorMulti(bs[:i]...)
}
return
}
}
if err != nil {
if len(bs) > 0 {
tokenAPI.Input.Byte.MoveCursorMulti(bs...)
}
return
}
}
}
// MakeInputFlusher creates a Handler that will flush the input buffer when the // MakeInputFlusher creates a Handler that will flush the input buffer when the
// provided handler matches. // provided handler matches.
// //
@ -1182,6 +1169,40 @@ func MatchValidRune() Handler {
} }
} }
func MatchValidRunes() Handler {
return func(tokenAPI *API) bool {
rs := make([]rune, 256, 256)
ok := false
for {
bs, err := tokenAPI.Input.Byte.PeekMulti(0, 256)
end := 0
offset := 0
for offset <= 256-utf8.UTFMax {
r, w := utf8.DecodeRune(bs[offset:])
if r == utf8.RuneError {
if end > 0 {
tokenAPI.Input.Rune.AcceptMulti(rs[:end]...)
}
return ok
}
ok = true
offset += w
rs[end] = r
end++
}
if end > 0 {
tokenAPI.Input.Rune.AcceptMulti(rs[:end]...)
}
if err != nil {
if err == io.EOF {
return ok
}
return false
}
}
}
}
// MatchInvalidRune creates a Handler function that checks if an invalid // MatchInvalidRune creates a Handler function that checks if an invalid
// UTF8 rune can be read from the input. // UTF8 rune can be read from the input.
func MatchInvalidRune() Handler { func MatchInvalidRune() Handler {