github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/iconv/iconv_writer.go (about)

     1  package iconv
     2  
     3  import "io"
     4  
     5  type Writer struct {
     6  	destination       io.Writer
     7  	converter         *Converter
     8  	buffer            []byte
     9  	readPos, writePos int
    10  	err               error
    11  }
    12  
    13  func NewWriter(destination io.Writer, fromEncoding string, toEncoding string) (*Writer, error) {
    14  	// create a converter
    15  	converter, err := NewConverter(fromEncoding, toEncoding)
    16  	if err == nil {
    17  		return NewWriterFromConverter(destination, converter), err
    18  	}
    19  	// return the error
    20  	return nil, err
    21  }
    22  
    23  func NewWriterFromConverter(destination io.Writer, converter *Converter) (writer *Writer) {
    24  	writer = new(Writer)
    25  	// copy elements
    26  	writer.destination = destination
    27  	writer.converter = converter
    28  	// create 8K buffers
    29  	writer.buffer = make([]byte, 8*1024)
    30  	return writer
    31  }
    32  
    33  func (c *Writer) emptyBuffer() {
    34  	// write new data out of buffer
    35  	bytesWritten, err := c.destination.Write(c.buffer[c.readPos:c.writePos])
    36  	// update read position
    37  	c.readPos += bytesWritten
    38  	// slide existing data to beginning
    39  	if c.readPos > 0 {
    40  		// copy current bytes - is this guaranteed safe?
    41  		copy(c.buffer, c.buffer[c.readPos:c.writePos])
    42  		// adjust positions
    43  		c.writePos -= c.readPos
    44  		c.readPos = 0
    45  	}
    46  	// track any reader error / EOF
    47  	if err != nil {
    48  		c.err = err
    49  	}
    50  }
    51  
    52  // implement the io.Writer interface
    53  func (c *Writer) Write(p []byte) (n int, err error) {
    54  	// write data into our internal buffer
    55  	bytesRead, bytesWritten, err := c.converter.Convert(p, c.buffer[c.writePos:])
    56  	// update bytes written for return
    57  	n += bytesRead
    58  	c.writePos += bytesWritten
    59  	// checks for when we have a full buffer
    60  	for c.writePos > 0 {
    61  		// if we have an error, just return it
    62  		if c.err != nil {
    63  			return
    64  		}
    65  		// else empty the buffer
    66  		c.emptyBuffer()
    67  	}
    68  	return n, err
    69  }