| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 | package mahoniaimport (	"io"	"unicode/utf8")// Writer implements character-set encoding for an io.Writer object.type Writer struct {	wr     io.Writer	encode Encoder	inbuf  []byte	outbuf []byte}// NewWriter creates a new Writer that uses the receiver to encode text.func (e Encoder) NewWriter(wr io.Writer) *Writer {	w := new(Writer)	w.wr = wr	w.encode = e	return w}// Write encodes and writes the data from p.func (w *Writer) Write(p []byte) (n int, err error) {	n = len(p)	if len(w.inbuf) > 0 {		w.inbuf = append(w.inbuf, p...)		p = w.inbuf	}	if len(w.outbuf) < len(p) {		w.outbuf = make([]byte, len(p)+10)	}	outpos := 0	for len(p) > 0 {		rune, size := utf8.DecodeRune(p)		if rune == 0xfffd && !utf8.FullRune(p) {			break		}		p = p[size:]	retry:		size, status := w.encode(w.outbuf[outpos:], rune)		if status == NO_ROOM {			newDest := make([]byte, len(w.outbuf)*2)			copy(newDest, w.outbuf)			w.outbuf = newDest			goto retry		}		if status == STATE_ONLY {			outpos += size			goto retry		}		outpos += size	}	w.inbuf = w.inbuf[:0]	if len(p) > 0 {		w.inbuf = append(w.inbuf, p...)	}	n1, err := w.wr.Write(w.outbuf[0:outpos])	if err != nil && n1 < n {		n = n1	}	return}func (w *Writer) WriteRune(c rune) (size int, err error) {	if len(w.inbuf) > 0 {		// There are leftover bytes, a partial UTF-8 sequence.		w.inbuf = w.inbuf[:0]		w.WriteRune(0xfffd)	}	if w.outbuf == nil {		w.outbuf = make([]byte, 16)	}	outpos := 0retry:	size, status := w.encode(w.outbuf[outpos:], c)	if status == NO_ROOM {		w.outbuf = make([]byte, len(w.outbuf)*2)		goto retry	}	if status == STATE_ONLY {		outpos += size		goto retry	}	outpos += size	return w.wr.Write(w.outbuf[0:outpos])}
 |