Commit c544e0fb authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

strings: select Replacer algorithm and build machine lazily

Saves 22KB of memory in stdlib packages.

Updates #26775

Change-Id: Ia19fe7aff61f6e2ddd83cd35969d7ff94526591f
Reviewed-on: https://go-review.googlesource.com/127661
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 9087d13e
......@@ -5,10 +5,12 @@
package strings
func (r *Replacer) Replacer() interface{} {
r.once.Do(r.buildOnce)
return r.r
}
func (r *Replacer) PrintTrie() string {
r.once.Do(r.buildOnce)
gen := r.r.(*genericReplacer)
return gen.printNode(&gen.root, 0)
}
......
......@@ -4,12 +4,17 @@
package strings
import "io"
import (
"io"
"sync"
)
// Replacer replaces a list of strings with replacements.
// It is safe for concurrent use by multiple goroutines.
type Replacer struct {
r replacer
once sync.Once // guards buildOnce method
r replacer
oldnew []string
}
// replacer is the interface that a replacement algorithm needs to implement.
......@@ -25,15 +30,24 @@ func NewReplacer(oldnew ...string) *Replacer {
if len(oldnew)%2 == 1 {
panic("strings.NewReplacer: odd argument count")
}
return &Replacer{oldnew: append([]string(nil), oldnew...)}
}
func (r *Replacer) buildOnce() {
r.r = r.build()
r.oldnew = nil
}
func (b *Replacer) build() replacer {
oldnew := b.oldnew
if len(oldnew) == 2 && len(oldnew[0]) > 1 {
return &Replacer{r: makeSingleStringReplacer(oldnew[0], oldnew[1])}
return makeSingleStringReplacer(oldnew[0], oldnew[1])
}
allNewBytes := true
for i := 0; i < len(oldnew); i += 2 {
if len(oldnew[i]) != 1 {
return &Replacer{r: makeGenericReplacer(oldnew)}
return makeGenericReplacer(oldnew)
}
if len(oldnew[i+1]) != 1 {
allNewBytes = false
......@@ -52,7 +66,7 @@ func NewReplacer(oldnew ...string) *Replacer {
n := oldnew[i+1][0]
r[o] = n
}
return &Replacer{r: &r}
return &r
}
r := byteStringReplacer{toReplace: make([]string, 0, len(oldnew)/2)}
......@@ -71,16 +85,18 @@ func NewReplacer(oldnew ...string) *Replacer {
r.replacements[o] = []byte(n)
}
return &Replacer{r: &r}
return &r
}
// Replace returns a copy of s with all replacements performed.
func (r *Replacer) Replace(s string) string {
r.once.Do(r.buildOnce)
return r.r.Replace(s)
}
// WriteString writes s to w with all replacements performed.
func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
r.once.Do(r.buildOnce)
return r.r.WriteString(w, s)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment