2011-01-29 14:32:55 +08:00
|
|
|
package iconv
|
|
|
|
|
2012-04-11 06:30:42 +08:00
|
|
|
import "io"
|
2011-01-29 14:32:55 +08:00
|
|
|
|
|
|
|
type Writer struct {
|
2012-04-11 06:30:42 +08:00
|
|
|
destination io.Writer
|
|
|
|
converter *Converter
|
|
|
|
buffer []byte
|
2011-01-29 14:32:55 +08:00
|
|
|
readPos, writePos int
|
2012-04-11 06:30:42 +08:00
|
|
|
err error
|
2011-01-29 14:32:55 +08:00
|
|
|
}
|
|
|
|
|
2012-04-11 06:30:42 +08:00
|
|
|
func NewWriter(destination io.Writer, fromEncoding string, toEncoding string) (*Writer, error) {
|
2011-01-29 14:32:55 +08:00
|
|
|
// create a converter
|
|
|
|
converter, err := NewConverter(fromEncoding, toEncoding)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
return NewWriterFromConverter(destination, converter), err
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the error
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewWriterFromConverter(destination io.Writer, converter *Converter) (writer *Writer) {
|
|
|
|
writer = new(Writer)
|
|
|
|
|
|
|
|
// copy elements
|
|
|
|
writer.destination = destination
|
|
|
|
writer.converter = converter
|
|
|
|
|
|
|
|
// create 8K buffers
|
2012-04-11 06:30:42 +08:00
|
|
|
writer.buffer = make([]byte, 8*1024)
|
2011-01-29 14:32:55 +08:00
|
|
|
|
|
|
|
return writer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *Writer) emptyBuffer() {
|
|
|
|
// write new data out of buffer
|
|
|
|
bytesWritten, err := this.destination.Write(this.buffer[this.readPos:this.writePos])
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
// update read position
|
|
|
|
this.readPos += bytesWritten
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
// slide existing data to beginning
|
|
|
|
if this.readPos > 0 {
|
|
|
|
// copy current bytes - is this guaranteed safe?
|
|
|
|
copy(this.buffer, this.buffer[this.readPos:this.writePos])
|
|
|
|
|
|
|
|
// adjust positions
|
|
|
|
this.writePos -= this.readPos
|
|
|
|
this.readPos = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// track any reader error / EOF
|
|
|
|
if err != nil {
|
|
|
|
this.err = err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// implement the io.Writer interface
|
2012-04-11 06:30:42 +08:00
|
|
|
func (this *Writer) Write(p []byte) (n int, err error) {
|
2011-01-29 14:32:55 +08:00
|
|
|
// write data into our internal buffer
|
|
|
|
bytesRead, bytesWritten, err := this.converter.Convert(p, this.buffer[this.writePos:])
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
// update bytes written for return
|
|
|
|
n += bytesRead
|
|
|
|
this.writePos += bytesWritten
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
// checks for when we have a full buffer
|
|
|
|
for this.writePos > 0 {
|
|
|
|
// if we have an error, just return it
|
|
|
|
if this.err != nil {
|
2012-04-11 06:30:42 +08:00
|
|
|
return
|
2011-01-29 14:32:55 +08:00
|
|
|
}
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
// else empty the buffer
|
|
|
|
this.emptyBuffer()
|
|
|
|
}
|
2012-04-11 06:30:42 +08:00
|
|
|
|
2011-01-29 14:32:55 +08:00
|
|
|
return n, err
|
|
|
|
}
|