83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
|
package hodu
|
||
|
|
||
|
import "bytes"
|
||
|
import "golang.org/x/text/transform"
|
||
|
|
||
|
type Transformer struct {
|
||
|
replacement []byte
|
||
|
needle []byte
|
||
|
needle_len int
|
||
|
}
|
||
|
|
||
|
func NewBytesTransformer(needle []byte, replacement []byte) *Transformer {
|
||
|
return &Transformer{needle: needle, replacement: replacement, needle_len: len(needle)}
|
||
|
}
|
||
|
|
||
|
func NewStringTransformer(needle string, replacement string) *Transformer {
|
||
|
return NewBytesTransformer([]byte(needle), []byte(replacement))
|
||
|
}
|
||
|
|
||
|
func (t *Transformer) Reset() {
|
||
|
// do nothing
|
||
|
}
|
||
|
|
||
|
func (t *Transformer) Transform(dst []byte, src []byte, at_eof bool) (int, int, error) {
|
||
|
var n int
|
||
|
var i int
|
||
|
var ndst int
|
||
|
var nsrc int
|
||
|
var rem int
|
||
|
var err error
|
||
|
|
||
|
if t.needle_len <= 0 {
|
||
|
n, err = t.copy_all(dst, src)
|
||
|
return n, n, err
|
||
|
}
|
||
|
|
||
|
nsrc = 0; ndst = 0
|
||
|
for {
|
||
|
i = bytes.Index(src[nsrc:], t.needle)
|
||
|
if i == -1 { break }
|
||
|
|
||
|
// copy the part before the match
|
||
|
n, err = t.copy_all(dst[ndst:], src[nsrc:nsrc+i])
|
||
|
nsrc += n; ndst += n
|
||
|
if err != nil { goto done }
|
||
|
|
||
|
// copy the new value in place of the match
|
||
|
n, err = t.copy_all(dst[ndst:], t.replacement)
|
||
|
if err != nil { goto done }
|
||
|
ndst += n; nsrc += t.needle_len
|
||
|
}
|
||
|
|
||
|
if at_eof {
|
||
|
n, err = t.copy_all(dst[ndst:], src[nsrc:])
|
||
|
ndst += n; nsrc += n
|
||
|
goto done
|
||
|
}
|
||
|
|
||
|
rem = len(src[nsrc:])
|
||
|
if rem >= t.needle_len {
|
||
|
n, err = t.copy_all(dst[ndst:], src[nsrc: nsrc + (rem - t.needle_len) + 1])
|
||
|
nsrc += n; ndst += n
|
||
|
if err != nil { goto done }
|
||
|
}
|
||
|
|
||
|
// ErrShortSrc means that the source buffer has insufficient data to
|
||
|
// complete the transformation.
|
||
|
err = transform.ErrShortSrc
|
||
|
|
||
|
done:
|
||
|
return ndst, nsrc, err
|
||
|
}
|
||
|
|
||
|
func (t *Transformer) copy_all(dst []byte, src []byte) (int, error) {
|
||
|
var n int
|
||
|
var err error
|
||
|
n = copy(dst, src)
|
||
|
// ErrShortDst means that the destination buffer was too short to
|
||
|
// receive all of the transformed bytes.
|
||
|
if n < len(src) { err = transform.ErrShortDst }
|
||
|
return n, err
|
||
|
}
|