Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small optimizations to base64decode #319

Merged
merged 2 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions transformations/base64decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

package transformations

import "strings"

var base64DecMap = []byte{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
Expand Down Expand Up @@ -42,11 +44,13 @@ func base64decode(data string) (string, error) {
return res, nil
}

func doBase64decode(input string) string {
slen := len(input)
src := []byte(input)
func doBase64decode(src string) string {
slen := len(src)
if slen == 0 {
return src
}

var j, x, i, n int
dst := make([]byte, slen)

/* First pass: check for validity and get output length */
for ; i < slen; i++ {
Expand All @@ -72,41 +76,42 @@ func doBase64decode(input string) string {

/* Space inside a line is an error */
if x != 0 {
return input
return src
}
if src[i] == '=' {
j++
if j > 2 {
// ERROR
return input
return src
}
}

if src[i] > 127 || base64DecMap[src[i]] == 127 {
// ERROR
return input
return src
}

if base64DecMap[src[i]] < 64 && j != 0 {
// ERROR
return input
return src
}
n++
}

n = ((n * 6) + 7) >> 3
n -= j
if len(dst) == 0 || slen < n {
if slen < n {
// ERROR
return input
return src
}

j = 3
n = 0
x = 0
srcc := 0

dstc := 0
var dst strings.Builder
dst.Grow(slen)

for ; i > 0; i-- {
if src[srcc] == '\r' || src[srcc] == '\n' || src[srcc] == ' ' {
Expand All @@ -122,20 +127,17 @@ func doBase64decode(input string) string {
if n == 4 {
n = 0
if j > 0 {
dst[dstc] = byte(x >> 16)
dstc++
dst.WriteByte(byte(x >> 16))
}
if j > 1 {
dst[dstc] = byte(x >> 8)
dstc++
dst.WriteByte(byte(x >> 8))
}
if j > 2 {
dst[dstc] = byte(x)
dstc++
dst.WriteByte(byte(x))
}
}
srcc++
}

return string(dst[:dstc])
return dst.String()
}
22 changes: 22 additions & 0 deletions transformations/base64decode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package transformations

import "testing"

func BenchmarkB64Decode(b *testing.B) {
tests := []string{
"VGVzdENhc2U=",
"P.HNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==",
"VGVzdABDYXNl",
}

for _, tt := range tests {
b.Run(tt, func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := base64decode(tt)
if err != nil {
b.Error(err)
}
}
})
}
}