OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / unicode / norm / readwriter.go
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
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 // Write implements the standard write interface.  If the last characters are
16 // not at a normalization boundary, the bytes will be buffered for the next
17 // write. The remaining bytes will be written on close.
18 func (w *normWriter) Write(data []byte) (n int, err error) {
19         // Process data in pieces to keep w.buf size bounded.
20         const chunk = 4000
21
22         for len(data) > 0 {
23                 // Normalize into w.buf.
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                 // Write out complete prefix, save remainder.
35                 // Note that lastBoundary looks back at most 31 runes.
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 // Close forces data that remains in the buffer to be written.
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 // Writer returns a new writer that implements Write(b)
63 // by writing f(b) to w.  The returned writer may use an
64 // an internal buffer to maintain state across Write calls.
65 // Calling its Close method writes any buffered data to w.
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 // Read implements the standard read interface.
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 // Reader returns a new reader that implements Read
118 // by reading data from r and returning f(data).
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 }