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