Skip to content

Instantly share code, notes, and snippets.

@egonelbre
Last active August 29, 2015 14:19
Show Gist options
  • Save egonelbre/dbe66ea24edd4db6dac5 to your computer and use it in GitHub Desktop.
Save egonelbre/dbe66ea24edd4db6dac5 to your computer and use it in GitHub Desktop.
encoding optimizations
diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go
index ad3abe6..bff443f 100644
--- a/src/encoding/base64/base64.go
+++ b/src/encoding/base64/base64.go
@@ -22,7 +22,7 @@ import (
// (RFC 1421). RFC 4648 also defines an alternate encoding, which is
// the standard encoding with - and _ substituted for + and /.
type Encoding struct {
- encode string
+ encode [64]byte
decodeMap [256]byte
}
@@ -33,7 +33,10 @@ const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678
// which must be a 64-byte string.
func NewEncoding(encoder string) *Encoding {
e := new(Encoding)
- e.encode = encoder
+
+ for i, b := range encoder {
+ e.encode[i] = byte(b)
+ }
for i := 0; i < len(e.decodeMap); i++ {
e.decodeMap[i] = 0xFF
}
@@ -73,42 +76,38 @@ func (enc *Encoding) Encode(dst, src []byte) {
return
}
- for len(src) > 0 {
- var b0, b1, b2, b3 byte
+ di, si := 0, 0
+ N := (len(src) / 3) * 3
+ for si < N {
+ val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
- // Unpack 4x 6-bit source blocks into a 4 byte
- // destination quantum
- switch len(src) {
- default:
- b3 = src[2] & 0x3F
- b2 = src[2] >> 6
- fallthrough
- case 2:
- b2 |= (src[1] << 2) & 0x3F
- b1 = src[1] >> 4
- fallthrough
- case 1:
- b1 |= (src[0] << 4) & 0x3F
- b0 = src[0] >> 2
- }
+ dst[di+0] = enc.encode[val>>18]
+ dst[di+1] = enc.encode[val>>12&0x3F]
+ dst[di+2] = enc.encode[val>>6&0x3F]
+ dst[di+3] = enc.encode[val&0x3F]
- // Encode 6-bit blocks using the base64 alphabet
- dst[0] = enc.encode[b0]
- dst[1] = enc.encode[b1]
- dst[2] = enc.encode[b2]
- dst[3] = enc.encode[b3]
-
- // Pad the final quantum
- if len(src) < 3 {
- dst[3] = '='
- if len(src) < 2 {
- dst[2] = '='
- }
- break
+ si += 3
+ di += 4
+ }
+
+ remain := len(src) - si
+ if remain > 0 {
+ val := uint(src[si+0]) << 16
+ if remain == 2 {
+ val |= uint(src[si+1]) << 8
}
- src = src[3:]
- dst = dst[4:]
+ dst[di+0] = enc.encode[val>>18]
+ dst[di+1] = enc.encode[val>>12&0x3f]
+
+ switch remain {
+ case 2:
+ dst[di+2] = enc.encode[val>>6&0x3f]
+ dst[di+3] = '='
+ case 1:
+ dst[di+2] = '='
+ dst[di+3] = '='
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment