aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/strings/replace.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2011-09-28 09:34:26 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2011-09-28 09:34:26 -0700
commit7b0f3caa26a46f2d8ef277ff677efec899618871 (patch)
treee6060321e4eb713d311f4a624579591eab4cdd32 /src/pkg/strings/replace.go
parent58a5f1e84f4e6679ffb70a0cc81d786e078b4ef7 (diff)
downloadgo-7b0f3caa26a46f2d8ef277ff677efec899618871.tar.xz
strings: add Replacer, NewReplacer
This is just a new API to do many replacements at once. While the point of this API is to be faster than doing replacements one at a time, the implementation in this CL has the optimizations removed and may actually be slower. Future CLs will bring back & add optimizations. R=r, rsc, rogpeppe CC=golang-dev https://golang.org/cl/5081042
Diffstat (limited to 'src/pkg/strings/replace.go')
-rw-r--r--src/pkg/strings/replace.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/pkg/strings/replace.go b/src/pkg/strings/replace.go
new file mode 100644
index 0000000000..cf2c023be0
--- /dev/null
+++ b/src/pkg/strings/replace.go
@@ -0,0 +1,84 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings
+
+import (
+ "io"
+ "os"
+)
+
+// Can't import ioutil for ioutil.Discard, due to ioutil/tempfile.go -> strconv -> strings
+var discard io.Writer = devNull(0)
+
+type devNull int
+
+func (devNull) Write(p []byte) (int, os.Error) {
+ return len(p), nil
+}
+
+type pair struct{ old, new string }
+
+// A Replacer replaces a list of strings with replacements.
+type Replacer struct {
+ p []pair
+}
+
+// NewReplacer returns a new Replacer from a list of old, new string pairs.
+// Replacements are performed in order, without overlapping matches.
+func NewReplacer(oldnew ...string) *Replacer {
+ if len(oldnew)%2 == 1 {
+ panic("strings.NewReplacer: odd argument count")
+ }
+ r := new(Replacer)
+ for len(oldnew) >= 2 {
+ r.p = append(r.p, pair{oldnew[0], oldnew[1]})
+ oldnew = oldnew[2:]
+ }
+ return r
+}
+
+type appendSliceWriter struct {
+ b []byte
+}
+
+func (w *appendSliceWriter) Write(p []byte) (int, os.Error) {
+ w.b = append(w.b, p...)
+ return len(p), nil
+}
+
+// Replace returns a copy of s with all replacements performed.
+func (r *Replacer) Replace(s string) string {
+ // TODO(bradfitz): optimized version
+ n, _ := r.WriteString(discard, s)
+ w := appendSliceWriter{make([]byte, 0, n)}
+ r.WriteString(&w, s)
+ return string(w.b)
+}
+
+// WriteString writes s to w with all replacements performed.
+func (r *Replacer) WriteString(w io.Writer, s string) (n int, err os.Error) {
+Input:
+ // TODO(bradfitz): optimized version
+ for i := 0; i < len(s); {
+ for _, p := range r.p {
+ if HasPrefix(s[i:], p.old) {
+ wn, err := w.Write([]byte(p.new))
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ i += len(p.old)
+ continue Input
+ }
+ }
+ wn, err := w.Write([]byte{s[i]})
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ i++
+ }
+ return n, nil
+}