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.
 
 
 

126 lines
2.9 KiB

  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package norm
  5. import "io"
  6. type normWriter struct {
  7. rb reorderBuffer
  8. w io.Writer
  9. buf []byte
  10. }
  11. // Write implements the standard write interface. If the last characters are
  12. // not at a normalization boundary, the bytes will be buffered for the next
  13. // write. The remaining bytes will be written on close.
  14. func (w *normWriter) Write(data []byte) (n int, err error) {
  15. // Process data in pieces to keep w.buf size bounded.
  16. const chunk = 4000
  17. for len(data) > 0 {
  18. // Normalize into w.buf.
  19. m := len(data)
  20. if m > chunk {
  21. m = chunk
  22. }
  23. w.rb.src = inputBytes(data[:m])
  24. w.rb.nsrc = m
  25. w.buf = doAppend(&w.rb, w.buf, 0)
  26. data = data[m:]
  27. n += m
  28. // Write out complete prefix, save remainder.
  29. // Note that lastBoundary looks back at most 31 runes.
  30. i := lastBoundary(&w.rb.f, w.buf)
  31. if i == -1 {
  32. i = 0
  33. }
  34. if i > 0 {
  35. if _, err = w.w.Write(w.buf[:i]); err != nil {
  36. break
  37. }
  38. bn := copy(w.buf, w.buf[i:])
  39. w.buf = w.buf[:bn]
  40. }
  41. }
  42. return n, err
  43. }
  44. // Close forces data that remains in the buffer to be written.
  45. func (w *normWriter) Close() error {
  46. if len(w.buf) > 0 {
  47. _, err := w.w.Write(w.buf)
  48. if err != nil {
  49. return err
  50. }
  51. }
  52. return nil
  53. }
  54. // Writer returns a new writer that implements Write(b)
  55. // by writing f(b) to w. The returned writer may use an
  56. // internal buffer to maintain state across Write calls.
  57. // Calling its Close method writes any buffered data to w.
  58. func (f Form) Writer(w io.Writer) io.WriteCloser {
  59. wr := &normWriter{rb: reorderBuffer{}, w: w}
  60. wr.rb.init(f, nil)
  61. return wr
  62. }
  63. type normReader struct {
  64. rb reorderBuffer
  65. r io.Reader
  66. inbuf []byte
  67. outbuf []byte
  68. bufStart int
  69. lastBoundary int
  70. err error
  71. }
  72. // Read implements the standard read interface.
  73. func (r *normReader) Read(p []byte) (int, error) {
  74. for {
  75. if r.lastBoundary-r.bufStart > 0 {
  76. n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
  77. r.bufStart += n
  78. if r.lastBoundary-r.bufStart > 0 {
  79. return n, nil
  80. }
  81. return n, r.err
  82. }
  83. if r.err != nil {
  84. return 0, r.err
  85. }
  86. outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
  87. r.outbuf = r.outbuf[0:outn]
  88. r.bufStart = 0
  89. n, err := r.r.Read(r.inbuf)
  90. r.rb.src = inputBytes(r.inbuf[0:n])
  91. r.rb.nsrc, r.err = n, err
  92. if n > 0 {
  93. r.outbuf = doAppend(&r.rb, r.outbuf, 0)
  94. }
  95. if err == io.EOF {
  96. r.lastBoundary = len(r.outbuf)
  97. } else {
  98. r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
  99. if r.lastBoundary == -1 {
  100. r.lastBoundary = 0
  101. }
  102. }
  103. }
  104. }
  105. // Reader returns a new reader that implements Read
  106. // by reading data from r and returning f(data).
  107. func (f Form) Reader(r io.Reader) io.Reader {
  108. const chunk = 4000
  109. buf := make([]byte, chunk)
  110. rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
  111. rr.rb.init(f, buf)
  112. return rr
  113. }