Skip to content

Commit

Permalink
Small optimizations to base64decode (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraaga authored Aug 9, 2022
1 parent dfd5dac commit 4bc9ac3
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 18 deletions.
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)
}
}
})
}
}

0 comments on commit 4bc9ac3

Please sign in to comment.