OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / unicode / norm / transform.go
1 // Copyright 2013 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 (
8         "unicode/utf8"
9
10         "golang.org/x/text/transform"
11 )
12
13 // Reset implements the Reset method of the transform.Transformer interface.
14 func (Form) Reset() {}
15
16 // Transform implements the Transform method of the transform.Transformer
17 // interface. It may need to write segments of up to MaxSegmentSize at once.
18 // Users should either catch ErrShortDst and allow dst to grow or have dst be at
19 // least of size MaxTransformChunkSize to be guaranteed of progress.
20 func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
21         n := 0
22         // Cap the maximum number of src bytes to check.
23         b := src
24         eof := atEOF
25         if ns := len(dst); ns < len(b) {
26                 err = transform.ErrShortDst
27                 eof = false
28                 b = b[:ns]
29         }
30         i, ok := formTable[f].quickSpan(inputBytes(b), n, len(b), eof)
31         n += copy(dst[n:], b[n:i])
32         if !ok {
33                 nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
34                 return nDst + n, nSrc + n, err
35         }
36         if n < len(src) && !atEOF {
37                 err = transform.ErrShortSrc
38         }
39         return n, n, err
40 }
41
42 func flushTransform(rb *reorderBuffer) bool {
43         // Write out (must fully fit in dst, or else it is a ErrShortDst).
44         if len(rb.out) < rb.nrune*utf8.UTFMax {
45                 return false
46         }
47         rb.out = rb.out[rb.flushCopy(rb.out):]
48         return true
49 }
50
51 var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc}
52
53 // transform implements the transform.Transformer interface. It is only called
54 // when quickSpan does not pass for a given string.
55 func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
56         // TODO: get rid of reorderBuffer. See CL 23460044.
57         rb := reorderBuffer{}
58         rb.init(f, src)
59         for {
60                 // Load segment into reorder buffer.
61                 rb.setFlusher(dst[nDst:], flushTransform)
62                 end := decomposeSegment(&rb, nSrc, atEOF)
63                 if end < 0 {
64                         return nDst, nSrc, errs[-end]
65                 }
66                 nDst = len(dst) - len(rb.out)
67                 nSrc = end
68
69                 // Next quickSpan.
70                 end = rb.nsrc
71                 eof := atEOF
72                 if n := nSrc + len(dst) - nDst; n < end {
73                         err = transform.ErrShortDst
74                         end = n
75                         eof = false
76                 }
77                 end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof)
78                 n := copy(dst[nDst:], rb.src.bytes[nSrc:end])
79                 nSrc += n
80                 nDst += n
81                 if ok {
82                         if n < rb.nsrc && !atEOF {
83                                 err = transform.ErrShortSrc
84                         }
85                         return nDst, nSrc, err
86                 }
87         }
88 }