]> Cypherpunks repositories - gostls13.git/commitdiff
mime: Remove an allocation in word decoding.
authorJustin Nuß <nuss.justin@gmail.com>
Wed, 9 Sep 2015 19:10:43 +0000 (21:10 +0200)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sun, 18 Oct 2015 17:31:52 +0000 (17:31 +0000)
This fixes a TODO in (*WordDecoder).Decode by replacing a call to strings.Split with
simple prefix/suffix checking and some custom slicing.

Benchmark results:

benchmark                    old ns/op     new ns/op     delta
BenchmarkQEncodeWord-8       740           693           -6.35%
BenchmarkQDecodeWord-8       1291          727           -43.69%
BenchmarkQDecodeHeader-8     1194          767           -35.76%

benchmark                    old allocs     new allocs     delta
BenchmarkQEncodeWord-8       1              1              +0.00%
BenchmarkQDecodeWord-8       3              2              -33.33%
BenchmarkQDecodeHeader-8     3              2              -33.33%

benchmark                    old bytes     new bytes     delta
BenchmarkQEncodeWord-8       48            48            +0.00%
BenchmarkQDecodeWord-8       128           48            -62.50%
BenchmarkQDecodeHeader-8     128           48            -62.50%

Change-Id: I2d6844c75ec2e2b79be2e49b7fc4ca320b7e84e5
Reviewed-on: https://go-review.googlesource.com/14432
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/mime/encodedword.go

index 3b414dd5c4b0a94789f283822fc201898541a234..db4b5f4510ba495d3a27c44df89b94a79061406b 100644 (file)
@@ -194,12 +194,24 @@ type WordDecoder struct {
 
 // Decode decodes an RFC 2047 encoded-word.
 func (d *WordDecoder) Decode(word string) (string, error) {
-       fields := strings.Split(word, "?") // TODO: remove allocation?
-       if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" || len(fields[2]) != 1 {
+       if !strings.HasPrefix(word, "=?") || !strings.HasSuffix(word, "?=") || strings.Count(word, "?") != 4 {
                return "", errInvalidWord
        }
+       word = word[2 : len(word)-2]
 
-       content, err := decode(fields[2][0], fields[3])
+       // split delimits the first 2 fields
+       split := strings.IndexByte(word, '?')
+       // the field after split must only be one byte
+       if word[split+2] != '?' {
+               return "", errInvalidWord
+       }
+
+       // split word "UTF-8?q?ascii" into "UTF-8", 'q', and "ascii"
+       charset := word[:split]
+       encoding := word[split+1]
+       text := word[split+3:]
+
+       content, err := decode(encoding, text)
        if err != nil {
                return "", err
        }
@@ -207,7 +219,7 @@ func (d *WordDecoder) Decode(word string) (string, error) {
        buf := getBuffer()
        defer putBuffer(buf)
 
-       if err := d.convert(buf, fields[1], content); err != nil {
+       if err := d.convert(buf, charset, content); err != nil {
                return "", err
        }