aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/strings/replace.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/strings/replace.go')
-rw-r--r--libgo/go/strings/replace.go38
1 files changed, 25 insertions, 13 deletions
diff --git a/libgo/go/strings/replace.go b/libgo/go/strings/replace.go
index 58a11a6..ace0b8d 100644
--- a/libgo/go/strings/replace.go
+++ b/libgo/go/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)
}
@@ -292,10 +308,6 @@ func (w *appendSliceWriter) WriteString(s string) (int, error) {
return len(s), nil
}
-type stringWriterIface interface {
- WriteString(string) (int, error)
-}
-
type stringWriter struct {
w io.Writer
}
@@ -304,8 +316,8 @@ func (w stringWriter) WriteString(s string) (int, error) {
return w.w.Write([]byte(s))
}
-func getStringWriter(w io.Writer) stringWriterIface {
- sw, ok := w.(stringWriterIface)
+func getStringWriter(w io.Writer) io.StringWriter {
+ sw, ok := w.(io.StringWriter)
if !ok {
sw = stringWriter{w}
}
@@ -447,7 +459,7 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
buf := make([]byte, bufsize)
for len(s) > 0 {
- ncopy := copy(buf, s[:])
+ ncopy := copy(buf, s)
s = s[ncopy:]
for i, b := range buf[:ncopy] {
buf[i] = r[b]