1 // Copyright 2015 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.
10 "golang.org/x/text/transform"
13 type foldTransform struct {
17 func (foldTransform) Span(src []byte, atEOF bool) (n int, err error) {
19 if src[n] < utf8.RuneSelf {
21 for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
25 v, size := trie.lookup(src[n:])
26 if size == 0 { // incomplete UTF-8 encoding
28 err = transform.ErrShortSrc
34 if elem(v)&tagNeedsFold != 0 {
35 err = transform.ErrEndOfSpan
43 func (foldTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
45 if src[nSrc] < utf8.RuneSelf {
47 start, end := nSrc, len(src)
48 if d := len(dst) - nDst; d < end-start {
51 for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
53 n := copy(dst[nDst:], src[start:nSrc])
54 if nDst += n; nDst == len(dst) {
57 return nDst, nSrc, nil
59 if src[nSrc] < utf8.RuneSelf {
60 return nDst, nSrc, transform.ErrShortDst
65 v, size := trie.lookup(src[nSrc:])
66 if size == 0 { // incomplete UTF-8 encoding
68 return nDst, nSrc, transform.ErrShortSrc
70 size = 1 // gobble 1 byte
72 if elem(v)&tagNeedsFold == 0 {
73 if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
74 return nDst, nSrc, transform.ErrShortDst
78 data := inverseData[byte(v)]
79 if len(dst)-nDst < int(data[0]) {
80 return nDst, nSrc, transform.ErrShortDst
83 for end := int(data[0]); i < end; i++ {
87 dst[nDst] = data[i] ^ src[nSrc+size-1]
92 return nDst, nSrc, nil
95 type narrowTransform struct {
99 func (narrowTransform) Span(src []byte, atEOF bool) (n int, err error) {
101 if src[n] < utf8.RuneSelf {
103 for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
107 v, size := trie.lookup(src[n:])
108 if size == 0 { // incomplete UTF-8 encoding
110 err = transform.ErrShortSrc
116 if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
118 err = transform.ErrEndOfSpan
126 func (narrowTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
127 for nSrc < len(src) {
128 if src[nSrc] < utf8.RuneSelf {
130 start, end := nSrc, len(src)
131 if d := len(dst) - nDst; d < end-start {
134 for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
136 n := copy(dst[nDst:], src[start:nSrc])
137 if nDst += n; nDst == len(dst) {
139 if nSrc == len(src) {
140 return nDst, nSrc, nil
142 if src[nSrc] < utf8.RuneSelf {
143 return nDst, nSrc, transform.ErrShortDst
148 v, size := trie.lookup(src[nSrc:])
149 if size == 0 { // incomplete UTF-8 encoding
151 return nDst, nSrc, transform.ErrShortSrc
153 size = 1 // gobble 1 byte
155 if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
156 if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
157 return nDst, nSrc, transform.ErrShortDst
161 data := inverseData[byte(v)]
162 if len(dst)-nDst < int(data[0]) {
163 return nDst, nSrc, transform.ErrShortDst
166 for end := int(data[0]); i < end; i++ {
170 dst[nDst] = data[i] ^ src[nSrc+size-1]
175 return nDst, nSrc, nil
178 type wideTransform struct {
179 transform.NopResetter
182 func (wideTransform) Span(src []byte, atEOF bool) (n int, err error) {
184 // TODO: Consider ASCII fast path. Special-casing ASCII handling can
185 // reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
186 // not enough to warrant the extra code and complexity.
187 v, size := trie.lookup(src[n:])
188 if size == 0 { // incomplete UTF-8 encoding
190 err = transform.ErrShortSrc
196 if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
198 err = transform.ErrEndOfSpan
206 func (wideTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
207 for nSrc < len(src) {
208 // TODO: Consider ASCII fast path. Special-casing ASCII handling can
209 // reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
210 // not enough to warrant the extra code and complexity.
211 v, size := trie.lookup(src[nSrc:])
212 if size == 0 { // incomplete UTF-8 encoding
214 return nDst, nSrc, transform.ErrShortSrc
216 size = 1 // gobble 1 byte
218 if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
219 if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
220 return nDst, nSrc, transform.ErrShortDst
224 data := inverseData[byte(v)]
225 if len(dst)-nDst < int(data[0]) {
226 return nDst, nSrc, transform.ErrShortDst
229 for end := int(data[0]); i < end; i++ {
233 dst[nDst] = data[i] ^ src[nSrc+size-1]
238 return nDst, nSrc, nil