]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
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) { | |
15c0b25d AP |
21 | // Cap the maximum number of src bytes to check. |
22 | b := src | |
23 | eof := atEOF | |
24 | if ns := len(dst); ns < len(b) { | |
25 | err = transform.ErrShortDst | |
26 | eof = false | |
27 | b = b[:ns] | |
28 | } | |
107c1cdb ND |
29 | i, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), eof) |
30 | n := copy(dst, b[:i]) | |
15c0b25d AP |
31 | if !ok { |
32 | nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF) | |
33 | return nDst + n, nSrc + n, err | |
34 | } | |
107c1cdb ND |
35 | |
36 | if err == nil && n < len(src) && !atEOF { | |
15c0b25d AP |
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 an 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 { | |
107c1cdb | 82 | if err == nil && n < rb.nsrc && !atEOF { |
15c0b25d AP |
83 | err = transform.ErrShortSrc |
84 | } | |
85 | return nDst, nSrc, err | |
86 | } | |
87 | } | |
88 | } |