Skip to content

Commit

Permalink
url/ParseScheme: Minor performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
tkw1536 committed Oct 7, 2024
1 parent 6b1d98f commit 3f5bbc8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,8 @@ ggman comes with the following builtin aliases:

### 1.23.0 (Upcoming)

- minor performance improvements

### 1.22.0 (Released [Sep 22 2024](https://github.com/tkw1536/ggman/releases/tag/v1.22.0))

- update to `go 1.23`
Expand Down
54 changes: 38 additions & 16 deletions internal/url/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,50 @@ func IsValidURLScheme(s string) bool {
// regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9+\-\.]*$`).MatchString(s)
// However such an implementation would be a lot slower when called repeatedly.
// Instead we directly build code that implements this regex.
//
// For this we first check that the string is non-empty.
// Then we check that the first character is not a '+', '-' or '.'
// Then we check that each character is either alphanumeric or a '+', '-' or '.'

if len(s) == 0 {
// Iterate over the bytes in this string.
// We can do this safely, because any valid scheme must be ascii.
bytes := []byte(s)
if len(bytes) == 0 {
return false
}

// if the first rune is invalid, no need to check everything else
if s[0] == '+' || s[0] == '-' || s[0] == '.' {
return false
var (
idx = 0 // current index
c = bytes[0] // current character
)

// scheme must start with a letter
// so omit the loop preamble
goto start

nextLetter:
// go to the next letter
// or be done
idx++
if idx >= len(bytes) {
return true
}

for _, r := range s {
if !(('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z')) && // more efficient version of [email protected](r) for ascii
r != '+' &&
r != '-' &&
r != '.' {
return false
}
// get the current letter
c = bytes[idx]

if '0' <= c && c <= '9' {
goto nextLetter
}

if c == '+' || c == '-' || c == '.' {
goto nextLetter
}

start:
if 'a' <= c && c <= 'z' {
goto nextLetter
}

if 'A' <= c && c <= 'Z' {
goto nextLetter
}

return true
return false
}
1 change: 1 addition & 0 deletions internal/url/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func Test_IsValidURLScheme(t *testing.T) {
{"https scheme is valid", args{"https"}, true},
{"git scheme is valid", args{"git"}, true},
{"ssh scheme is valid", args{"ssh"}, true},
{"ssh2 scheme is valid", args{"ssh2"}, true},
{"file scheme is valid", args{"file"}, true},
{"combined with + scheme is valid", args{"ssh+git"}, true},
{"combined with - scheme is valid", args{"ssh-git"}, true},
Expand Down

0 comments on commit 3f5bbc8

Please sign in to comment.