hodu/transform.go

83 lines
1.8 KiB
Go
Raw Permalink Normal View History

2024-12-27 14:43:44 +09:00
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
}