~baidu-picture-scope-team/baidu-picture-scope/trunk

« back to all changes in this revision

Viewing changes to src/go/src/code.google.com/p/go.text/unicode/norm/readwriter.go

  • Committer: Zhang Enwei
  • Date: 2016-08-26 02:22:48 UTC
  • Revision ID: enwei.zhang@canonical.com-20160826022248-mf89jsetpcc2hg9e
Intial release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        panic("should not reach here")
 
116
}
 
117
 
 
118
// Reader returns a new reader that implements Read
 
119
// by reading data from r and returning f(data).
 
120
func (f Form) Reader(r io.Reader) io.Reader {
 
121
        const chunk = 4000
 
122
        buf := make([]byte, chunk)
 
123
        rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
 
124
        rr.rb.init(f, buf)
 
125
        return rr
 
126
}