writer.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package fwd
  2. import "io"
  3. const (
  4. // DefaultWriterSize is the
  5. // default write buffer size.
  6. DefaultWriterSize = 2048
  7. minWriterSize = minReaderSize
  8. )
  9. // Writer is a buffered writer
  10. type Writer struct {
  11. w io.Writer // writer
  12. buf []byte // 0:len(buf) is bufered data
  13. }
  14. // NewWriter returns a new writer
  15. // that writes to 'w' and has a buffer
  16. // that is `DefaultWriterSize` bytes.
  17. func NewWriter(w io.Writer) *Writer {
  18. if wr, ok := w.(*Writer); ok {
  19. return wr
  20. }
  21. return &Writer{
  22. w: w,
  23. buf: make([]byte, 0, DefaultWriterSize),
  24. }
  25. }
  26. // NewWriterSize returns a new writer that
  27. // writes to 'w' and has a buffer size 'n'.
  28. func NewWriterSize(w io.Writer, n int) *Writer {
  29. if wr, ok := w.(*Writer); ok && cap(wr.buf) >= n {
  30. return wr
  31. }
  32. buf := make([]byte, 0, max(n, minWriterSize))
  33. return NewWriterBuf(w, buf)
  34. }
  35. // NewWriterBuf returns a new writer
  36. // that writes to 'w' and has 'buf' as a buffer.
  37. // 'buf' is not used when has smaller capacity than 18,
  38. // custom buffer is allocated instead.
  39. func NewWriterBuf(w io.Writer, buf []byte) *Writer {
  40. if cap(buf) < minWriterSize {
  41. buf = make([]byte, 0, minWriterSize)
  42. }
  43. buf = buf[:0]
  44. return &Writer{
  45. w: w,
  46. buf: buf,
  47. }
  48. }
  49. // Buffered returns the number of buffered bytes
  50. // in the reader.
  51. func (w *Writer) Buffered() int { return len(w.buf) }
  52. // BufferSize returns the maximum size of the buffer.
  53. func (w *Writer) BufferSize() int { return cap(w.buf) }
  54. // Flush flushes any buffered bytes
  55. // to the underlying writer.
  56. func (w *Writer) Flush() error {
  57. l := len(w.buf)
  58. if l > 0 {
  59. n, err := w.w.Write(w.buf)
  60. // if we didn't write the whole
  61. // thing, copy the unwritten
  62. // bytes to the beginnning of the
  63. // buffer.
  64. if n < l && n > 0 {
  65. w.pushback(n)
  66. if err == nil {
  67. err = io.ErrShortWrite
  68. }
  69. }
  70. if err != nil {
  71. return err
  72. }
  73. w.buf = w.buf[:0]
  74. return nil
  75. }
  76. return nil
  77. }
  78. // Write implements `io.Writer`
  79. func (w *Writer) Write(p []byte) (int, error) {
  80. c, l, ln := cap(w.buf), len(w.buf), len(p)
  81. avail := c - l
  82. // requires flush
  83. if avail < ln {
  84. if err := w.Flush(); err != nil {
  85. return 0, err
  86. }
  87. l = len(w.buf)
  88. }
  89. // too big to fit in buffer;
  90. // write directly to w.w
  91. if c < ln {
  92. return w.w.Write(p)
  93. }
  94. // grow buf slice; copy; return
  95. w.buf = w.buf[:l+ln]
  96. return copy(w.buf[l:], p), nil
  97. }
  98. // WriteString is analogous to Write, but it takes a string.
  99. func (w *Writer) WriteString(s string) (int, error) {
  100. c, l, ln := cap(w.buf), len(w.buf), len(s)
  101. avail := c - l
  102. // requires flush
  103. if avail < ln {
  104. if err := w.Flush(); err != nil {
  105. return 0, err
  106. }
  107. l = len(w.buf)
  108. }
  109. // too big to fit in buffer;
  110. // write directly to w.w
  111. //
  112. // yes, this is unsafe. *but*
  113. // io.Writer is not allowed
  114. // to mutate its input or
  115. // maintain a reference to it,
  116. // per the spec in package io.
  117. //
  118. // plus, if the string is really
  119. // too big to fit in the buffer, then
  120. // creating a copy to write it is
  121. // expensive (and, strictly speaking,
  122. // unnecessary)
  123. if c < ln {
  124. return w.w.Write(unsafestr(s))
  125. }
  126. // grow buf slice; copy; return
  127. w.buf = w.buf[:l+ln]
  128. return copy(w.buf[l:], s), nil
  129. }
  130. // WriteByte implements `io.ByteWriter`
  131. func (w *Writer) WriteByte(b byte) error {
  132. if len(w.buf) == cap(w.buf) {
  133. if err := w.Flush(); err != nil {
  134. return err
  135. }
  136. }
  137. w.buf = append(w.buf, b)
  138. return nil
  139. }
  140. // Next returns the next 'n' free bytes
  141. // in the write buffer, flushing the writer
  142. // as necessary. Next will return `io.ErrShortBuffer`
  143. // if 'n' is greater than the size of the write buffer.
  144. // Calls to 'next' increment the write position by
  145. // the size of the returned buffer.
  146. func (w *Writer) Next(n int) ([]byte, error) {
  147. c, l := cap(w.buf), len(w.buf)
  148. if n > c {
  149. return nil, io.ErrShortBuffer
  150. }
  151. avail := c - l
  152. if avail < n {
  153. if err := w.Flush(); err != nil {
  154. return nil, err
  155. }
  156. l = len(w.buf)
  157. }
  158. w.buf = w.buf[:l+n]
  159. return w.buf[l:], nil
  160. }
  161. // take the bytes from w.buf[n:len(w.buf)]
  162. // and put them at the beginning of w.buf,
  163. // and resize to the length of the copied segment.
  164. func (w *Writer) pushback(n int) {
  165. w.buf = w.buf[:copy(w.buf, w.buf[n:])]
  166. }
  167. // ReadFrom implements `io.ReaderFrom`
  168. func (w *Writer) ReadFrom(r io.Reader) (int64, error) {
  169. // anticipatory flush
  170. if err := w.Flush(); err != nil {
  171. return 0, err
  172. }
  173. w.buf = w.buf[0:cap(w.buf)] // expand buffer
  174. var nn int64 // written
  175. var err error // error
  176. var x int // read
  177. // 1:1 reads and writes
  178. for err == nil {
  179. x, err = r.Read(w.buf)
  180. if x > 0 {
  181. n, werr := w.w.Write(w.buf[:x])
  182. nn += int64(n)
  183. if err != nil {
  184. if n < x && n > 0 {
  185. w.pushback(n - x)
  186. }
  187. return nn, werr
  188. }
  189. if n < x {
  190. w.pushback(n - x)
  191. return nn, io.ErrShortWrite
  192. }
  193. } else if err == nil {
  194. err = io.ErrNoProgress
  195. break
  196. }
  197. }
  198. if err != io.EOF {
  199. return nn, err
  200. }
  201. // we only clear here
  202. // because we are sure
  203. // the writes have
  204. // succeeded. otherwise,
  205. // we retain the data in case
  206. // future writes succeed.
  207. w.buf = w.buf[0:0]
  208. return nn, nil
  209. }