diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2018-08-02 20:02:24 +0000 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2018-08-21 02:50:58 +0000 |
commit | c544e0fbdb7344b2025650aaf70bab3b09d72003 (patch) | |
tree | 284bee6c1ae58b7fcf8a4371ed09c2402e394da3 /src/strings | |
parent | 9087d13ec3e39e50aae6c6a8cf99dc66225ab132 (diff) | |
download | go-c544e0fbdb7344b2025650aaf70bab3b09d72003.tar.gz go-c544e0fbdb7344b2025650aaf70bab3b09d72003.zip |
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: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/strings')
-rw-r--r-- | src/strings/export_test.go | 2 | ||||
-rw-r--r-- | src/strings/replace.go | 28 |
2 files changed, 24 insertions, 6 deletions
diff --git a/src/strings/export_test.go b/src/strings/export_test.go index 17c806aa56..b39cee6b1d 100644 --- a/src/strings/export_test.go +++ b/src/strings/export_test.go @@ -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) } diff --git a/src/strings/replace.go b/src/strings/replace.go index 58a11a63db..dbda950194 100644 --- a/src/strings/replace.go +++ b/src/strings/replace.go @@ -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) } |