Source file src/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  	// 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  	}
    29  	i, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), eof)
    30  	n := copy(dst, b[:i])
    31  	if !ok {
    32  		nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
    33  		return nDst + n, nSrc + n, err
    34  	}
    35  
    36  	if err == nil && 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 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 {
    82  			if err == nil && n < rb.nsrc && !atEOF {
    83  				err = transform.ErrShortSrc
    84  			}
    85  			return nDst, nSrc, err
    86  		}
    87  	}
    88  }
    89  

View as plain text