Commit 90870e61 authored by Rui Ueyama's avatar Rui Ueyama

strings: remove byteBitmap

Previously we had a bitmap to check whether or not a byte
appears in a string should be replaced. But we don't actually
need a separate bitmap for that purpose. Removing the bitmap
makes the code simpler.

LGTM=dave, iant, nigeltao
R=golang-codereviews, dave, gobot, nigeltao, iant, bradfitz, rsc
CC=golang-codereviews
https://golang.org/cl/110100043
parent 8158b8b6
...@@ -18,19 +18,6 @@ type replacer interface { ...@@ -18,19 +18,6 @@ type replacer interface {
WriteString(w io.Writer, s string) (n int, err error) WriteString(w io.Writer, s string) (n int, err error)
} }
// byteBitmap represents bytes which are sought for replacement.
// byteBitmap is 256 bits wide, with a bit set for each old byte to be
// replaced.
type byteBitmap [256 / 32]uint32
func (m *byteBitmap) set(b byte) {
m[b>>5] |= uint32(1 << (b & 31))
}
func (m *byteBitmap) isSet(b byte) bool {
return m[b>>5]&uint32(1<<(b&31)) != 0
}
// NewReplacer returns a new Replacer from a list of old, new string pairs. // NewReplacer returns a new Replacer from a list of old, new string pairs.
// Replacements are performed in order, without overlapping matches. // Replacements are performed in order, without overlapping matches.
func NewReplacer(oldnew ...string) *Replacer { func NewReplacer(oldnew ...string) *Replacer {
...@@ -53,33 +40,29 @@ func NewReplacer(oldnew ...string) *Replacer { ...@@ -53,33 +40,29 @@ func NewReplacer(oldnew ...string) *Replacer {
} }
if allNewBytes { if allNewBytes {
bb := &byteReplacer{} r := byteReplacer{}
for i := range bb.new { for i := range r {
bb.new[i] = byte(i) r[i] = byte(i)
} }
for i := 0; i < len(oldnew); i += 2 { // The first occurrence of old->new map takes precedence
o, n := oldnew[i][0], oldnew[i+1][0] // over the others with the same old string.
if bb.old.isSet(o) { for i := len(oldnew) - 2; i >= 0; i -= 2 {
// Later old->new maps do not override previous ones with the same old string. o := oldnew[i][0]
continue n := oldnew[i+1][0]
} r[o] = n
bb.old.set(o)
bb.new[o] = n
} }
return &Replacer{r: bb} return &Replacer{r: &r}
} }
bs := &byteStringReplacer{} r := byteStringReplacer{}
for i := 0; i < len(oldnew); i += 2 { // The first occurrence of old->new map takes precedence
o, new := oldnew[i][0], oldnew[i+1] // over the others with the same old string.
if bs.old.isSet(o) { for i := len(oldnew) - 2; i >= 0; i -= 2 {
// Later old->new maps do not override previous ones with the same old string. o := oldnew[i][0]
continue n := oldnew[i+1]
} r[o] = []byte(n)
bs.old.set(o)
bs.new[o] = []byte(new)
} }
return &Replacer{r: bs} return &Replacer{r: &r}
} }
// Replace returns a copy of s with all replacements performed. // Replace returns a copy of s with all replacements performed.
...@@ -426,24 +409,18 @@ func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err er ...@@ -426,24 +409,18 @@ func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err er
// byteReplacer is the implementation that's used when all the "old" // byteReplacer is the implementation that's used when all the "old"
// and "new" values are single ASCII bytes. // and "new" values are single ASCII bytes.
type byteReplacer struct { // The array contains replacement bytes indexed by old byte.
// old has a bit set for each old byte that should be replaced. type byteReplacer [256]byte
old byteBitmap
// replacement byte, indexed by old byte. old byte and new
// byte are the same if corresponding old bit is not set.
new [256]byte
}
func (r *byteReplacer) Replace(s string) string { func (r *byteReplacer) Replace(s string) string {
var buf []byte // lazily allocated var buf []byte // lazily allocated
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
b := s[i] b := s[i]
if r.old.isSet(b) { if r[b] != b {
if buf == nil { if buf == nil {
buf = []byte(s) buf = []byte(s)
} }
buf[i] = r.new[b] buf[i] = r[b]
} }
} }
if buf == nil { if buf == nil {
...@@ -464,7 +441,7 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) { ...@@ -464,7 +441,7 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
ncopy := copy(buf, s[:]) ncopy := copy(buf, s[:])
s = s[ncopy:] s = s[ncopy:]
for i, b := range buf[:ncopy] { for i, b := range buf[:ncopy] {
buf[i] = r.new[b] buf[i] = r[b]
} }
wn, err := w.Write(buf[:ncopy]) wn, err := w.Write(buf[:ncopy])
n += wn n += wn
...@@ -476,27 +453,20 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) { ...@@ -476,27 +453,20 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
} }
// byteStringReplacer is the implementation that's used when all the // byteStringReplacer is the implementation that's used when all the
// "old" values are single ASCII bytes but the "new" values vary in // "old" values are single ASCII bytes but the "new" values vary in size.
// size. // The array contains replacement byte slices indexed by old byte.
type byteStringReplacer struct { // A nil []byte means that the old byte should not be replaced.
// old has a bit set for each old byte that should be replaced. type byteStringReplacer [256][]byte
old byteBitmap
// replacement string, indexed by old byte. only valid if
// corresponding old bit is set.
new [256][]byte
}
func (r *byteStringReplacer) Replace(s string) string { func (r *byteStringReplacer) Replace(s string) string {
newSize := 0 newSize := len(s)
anyChanges := false anyChanges := false
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
b := s[i] b := s[i]
if r.old.isSet(b) { if r[b] != nil {
anyChanges = true anyChanges = true
newSize += len(r.new[b]) // The -1 is because we are replacing 1 byte with len(r[b]) bytes.
} else { newSize += len(r[b]) - 1
newSize++
} }
} }
if !anyChanges { if !anyChanges {
...@@ -506,8 +476,8 @@ func (r *byteStringReplacer) Replace(s string) string { ...@@ -506,8 +476,8 @@ func (r *byteStringReplacer) Replace(s string) string {
bi := buf bi := buf
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
b := s[i] b := s[i]
if r.old.isSet(b) { if r[b] != nil {
n := copy(bi, r.new[b]) n := copy(bi, r[b])
bi = bi[n:] bi = bi[n:]
} else { } else {
bi[0] = b bi[0] = b
...@@ -522,7 +492,7 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro ...@@ -522,7 +492,7 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro
last := 0 last := 0
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
b := s[i] b := s[i]
if !r.old.isSet(b) { if r[b] == nil {
continue continue
} }
if last != i { if last != i {
...@@ -533,7 +503,7 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro ...@@ -533,7 +503,7 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro
} }
} }
last = i + 1 last = i + 1
nw, err := w.Write(r.new[b]) nw, err := w.Write(r[b])
n += nw n += nw
if err != nil { if err != nil {
return n, err return n, err
......
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