github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/width/transform.go (about)

     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.
     4  
     5  package width
     6  
     7  import (
     8  	"unicode/utf8"
     9  
    10  	"golang.org/x/text/transform"
    11  )
    12  
    13  type foldTransform struct {
    14  	transform.NopResetter
    15  }
    16  
    17  func (foldTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
    18  	for nSrc < len(src) {
    19  		if src[nSrc] < utf8.RuneSelf {
    20  			// ASCII fast path.
    21  			start, end := nSrc, len(src)
    22  			if d := len(dst) - nDst; d < end-start {
    23  				end = nSrc + d
    24  			}
    25  			for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
    26  			}
    27  			nDst += copy(dst[nDst:], src[start:nSrc])
    28  			if nDst == len(dst) && nSrc < len(src) && src[nSrc] < utf8.RuneSelf {
    29  				return nDst, nSrc, transform.ErrShortDst
    30  			}
    31  			continue
    32  		}
    33  		v, size := trie.lookup(src[nSrc:])
    34  		if size == 0 { // incomplete UTF-8 encoding
    35  			if !atEOF {
    36  				return nDst, nSrc, transform.ErrShortSrc
    37  			}
    38  			size = 1 // gobble 1 byte
    39  		}
    40  		if elem(v)&tagNeedsFold == 0 {
    41  			if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
    42  				return nDst, nSrc, transform.ErrShortDst
    43  			}
    44  			nDst += size
    45  		} else {
    46  			data := inverseData[byte(v)]
    47  			if len(dst)-nDst < int(data[0]) {
    48  				return nDst, nSrc, transform.ErrShortDst
    49  			}
    50  			i := 1
    51  			for end := int(data[0]); i < end; i++ {
    52  				dst[nDst] = data[i]
    53  				nDst++
    54  			}
    55  			dst[nDst] = data[i] ^ src[nSrc+size-1]
    56  			nDst++
    57  		}
    58  		nSrc += size
    59  	}
    60  	return nDst, nSrc, nil
    61  }
    62  
    63  type narrowTransform struct {
    64  	transform.NopResetter
    65  }
    66  
    67  func (narrowTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
    68  	for nSrc < len(src) {
    69  		if src[nSrc] < utf8.RuneSelf {
    70  			// ASCII fast path.
    71  			start, end := nSrc, len(src)
    72  			if d := len(dst) - nDst; d < end-start {
    73  				end = nSrc + d
    74  			}
    75  			for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
    76  			}
    77  			nDst += copy(dst[nDst:], src[start:nSrc])
    78  			if nDst == len(dst) && nSrc < len(src) && src[nSrc] < utf8.RuneSelf {
    79  				return nDst, nSrc, transform.ErrShortDst
    80  			}
    81  			continue
    82  		}
    83  		v, size := trie.lookup(src[nSrc:])
    84  		if size == 0 { // incomplete UTF-8 encoding
    85  			if !atEOF {
    86  				return nDst, nSrc, transform.ErrShortSrc
    87  			}
    88  			size = 1 // gobble 1 byte
    89  		}
    90  		if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
    91  			if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
    92  				return nDst, nSrc, transform.ErrShortDst
    93  			}
    94  			nDst += size
    95  		} else {
    96  			data := inverseData[byte(v)]
    97  			if len(dst)-nDst < int(data[0]) {
    98  				return nDst, nSrc, transform.ErrShortDst
    99  			}
   100  			i := 1
   101  			for end := int(data[0]); i < end; i++ {
   102  				dst[nDst] = data[i]
   103  				nDst++
   104  			}
   105  			dst[nDst] = data[i] ^ src[nSrc+size-1]
   106  			nDst++
   107  		}
   108  		nSrc += size
   109  	}
   110  	return nDst, nSrc, nil
   111  }
   112  
   113  type wideTransform struct {
   114  	transform.NopResetter
   115  }
   116  
   117  func (wideTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
   118  	for nSrc < len(src) {
   119  		// TODO: Consider ASCII fast path. Special-casing ASCII handling can
   120  		// reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
   121  		// not enough to warrant the extra code and complexity.
   122  		v, size := trie.lookup(src[nSrc:])
   123  		if size == 0 { // incomplete UTF-8 encoding
   124  			if !atEOF {
   125  				return nDst, nSrc, transform.ErrShortSrc
   126  			}
   127  			size = 1 // gobble 1 byte
   128  		}
   129  		if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
   130  			if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
   131  				return nDst, nSrc, transform.ErrShortDst
   132  			}
   133  			nDst += size
   134  		} else {
   135  			data := inverseData[byte(v)]
   136  			if len(dst)-nDst < int(data[0]) {
   137  				return nDst, nSrc, transform.ErrShortDst
   138  			}
   139  			i := 1
   140  			for end := int(data[0]); i < end; i++ {
   141  				dst[nDst] = data[i]
   142  				nDst++
   143  			}
   144  			dst[nDst] = data[i] ^ src[nSrc+size-1]
   145  			nDst++
   146  		}
   147  		nSrc += size
   148  	}
   149  	return nDst, nSrc, nil
   150  }