vendor/golang.org/x/text/unicode/norm/transform.go
changeset 242 2a9ec03fe5a1
child 251 1c52a0eeb952
equal deleted inserted replaced
241:e77dad242f4c 242:2a9ec03fe5a1
       
     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 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 n < rb.nsrc && !atEOF {
       
    83 				err = transform.ErrShortSrc
       
    84 			}
       
    85 			return nDst, nSrc, err
       
    86 		}
       
    87 	}
       
    88 }