You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
1.8 KiB

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