1
2
3
4
5 package norm
6
7 import "io"
8
9 type normWriter struct {
10 rb reorderBuffer
11 w io.Writer
12 buf []byte
13 }
14
15
16
17
18 func (w *normWriter) Write(data []byte) (n int, err error) {
19
20 const chunk = 4000
21
22 for len(data) > 0 {
23
24 m := len(data)
25 if m > chunk {
26 m = chunk
27 }
28 w.rb.src = inputBytes(data[:m])
29 w.rb.nsrc = m
30 w.buf = doAppend(&w.rb, w.buf, 0)
31 data = data[m:]
32 n += m
33
34
35
36 i := lastBoundary(&w.rb.f, w.buf)
37 if i == -1 {
38 i = 0
39 }
40 if i > 0 {
41 if _, err = w.w.Write(w.buf[:i]); err != nil {
42 break
43 }
44 bn := copy(w.buf, w.buf[i:])
45 w.buf = w.buf[:bn]
46 }
47 }
48 return n, err
49 }
50
51
52 func (w *normWriter) Close() error {
53 if len(w.buf) > 0 {
54 _, err := w.w.Write(w.buf)
55 if err != nil {
56 return err
57 }
58 }
59 return nil
60 }
61
62
63
64
65
66 func (f Form) Writer(w io.Writer) io.WriteCloser {
67 wr := &normWriter{rb: reorderBuffer{}, w: w}
68 wr.rb.init(f, nil)
69 return wr
70 }
71
72 type normReader struct {
73 rb reorderBuffer
74 r io.Reader
75 inbuf []byte
76 outbuf []byte
77 bufStart int
78 lastBoundary int
79 err error
80 }
81
82
83 func (r *normReader) Read(p []byte) (int, error) {
84 for {
85 if r.lastBoundary-r.bufStart > 0 {
86 n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
87 r.bufStart += n
88 if r.lastBoundary-r.bufStart > 0 {
89 return n, nil
90 }
91 return n, r.err
92 }
93 if r.err != nil {
94 return 0, r.err
95 }
96 outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
97 r.outbuf = r.outbuf[0:outn]
98 r.bufStart = 0
99
100 n, err := r.r.Read(r.inbuf)
101 r.rb.src = inputBytes(r.inbuf[0:n])
102 r.rb.nsrc, r.err = n, err
103 if n > 0 {
104 r.outbuf = doAppend(&r.rb, r.outbuf, 0)
105 }
106 if err == io.EOF {
107 r.lastBoundary = len(r.outbuf)
108 } else {
109 r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
110 if r.lastBoundary == -1 {
111 r.lastBoundary = 0
112 }
113 }
114 }
115 }
116
117
118
119 func (f Form) Reader(r io.Reader) io.Reader {
120 const chunk = 4000
121 buf := make([]byte, chunk)
122 rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
123 rr.rb.init(f, buf)
124 return rr
125 }
126
View as plain text