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  }