PageRenderTime 29ms CodeModel.GetById 16ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/src/mahonia/writer.go

https://code.google.com/p/landproxy/
Go | 110 lines | 80 code | 25 blank | 5 comment | 21 complexity | 7cc14955520eb874f4e87b4880091dcf MD5 | raw file
  1package mahonia
  2
  3import (
  4	"io"
  5	//"unicode/utf8"
  6	"utf8"
  7	"os"
  8)
  9
 10// Writer implements character-set encoding for an io.Writer object.
 11type Writer struct {
 12	wr     io.Writer
 13	encode Encoder
 14	inbuf  []byte
 15	outbuf []byte
 16}
 17
 18// NewWriter creates a new Writer that uses the receiver to encode text.
 19func (e Encoder) NewWriter(wr io.Writer) *Writer {
 20	w := new(Writer)
 21	w.wr = wr
 22	w.encode = e
 23	return w
 24}
 25
 26// Write encodes and writes the data from p.
 27func (w *Writer) Write(p []byte) (n int, err os.Error) {
 28	n = len(p)
 29
 30	if len(w.inbuf) > 0 {
 31		w.inbuf = append(w.inbuf, p...)
 32		p = w.inbuf
 33	}
 34
 35	if len(w.outbuf) < len(p) {
 36		w.outbuf = make([]byte, len(p)+10)
 37	}
 38
 39	outpos := 0
 40
 41	for len(p) > 0 {
 42		int, size := utf8.DecodeRune(p)
 43		if int == 0xfffd && !utf8.FullRune(p) {
 44			break
 45		}
 46
 47		p = p[size:]
 48
 49	retry:
 50		size, status := w.encode(w.outbuf[outpos:], int)
 51
 52		if status == NO_ROOM {
 53			newDest := make([]byte, len(w.outbuf)*2)
 54			copy(newDest, w.outbuf)
 55			w.outbuf = newDest
 56			goto retry
 57		}
 58
 59		if status == STATE_ONLY {
 60			outpos += size
 61			goto retry
 62		}
 63
 64		outpos += size
 65	}
 66
 67	w.inbuf = w.inbuf[:0]
 68	if len(p) > 0 {
 69		w.inbuf = append(w.inbuf, p...)
 70	}
 71
 72	n1, err := w.wr.Write(w.outbuf[0:outpos])
 73
 74	if err != nil && n1 < n {
 75		n = n1
 76	}
 77
 78	return
 79}
 80
 81func (w *Writer) WriteRune(c int) (size int, err os.Error) {
 82	if len(w.inbuf) > 0 {
 83		// There are leftover bytes, a partial UTF-8 sequence.
 84		w.inbuf = w.inbuf[:0]
 85		w.WriteRune(0xfffd)
 86	}
 87
 88	if w.outbuf == nil {
 89		w.outbuf = make([]byte, 16)
 90	}
 91
 92	outpos := 0
 93
 94retry:
 95	size, status := w.encode(w.outbuf[outpos:], c)
 96
 97	if status == NO_ROOM {
 98		w.outbuf = make([]byte, len(w.outbuf)*2)
 99		goto retry
100	}
101
102	if status == STATE_ONLY {
103		outpos += size
104		goto retry
105	}
106
107	outpos += size
108
109	return w.wr.Write(w.outbuf[0:outpos])
110}