Source file src/vendor/golang.org/x/text/unicode/norm/readwriter.go

     1  // Copyright 2011 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 "io"
     8  
     9  type normWriter struct {
    10  	rb  reorderBuffer
    11  	w   io.Writer
    12  	buf []byte
    13  }
    14  
    15  // Write implements the standard write interface.  If the last characters are
    16  // not at a normalization boundary, the bytes will be buffered for the next
    17  // write. The remaining bytes will be written on close.
    18  func (w *normWriter) Write(data []byte) (n int, err error) {
    19  	// Process data in pieces to keep w.buf size bounded.
    20  	const chunk = 4000
    21  
    22  	for len(data) > 0 {
    23  		// Normalize into w.buf.
    24  		m := len(data)
    25  		if m > chunk {
    26  			m = chunk
    27  		}
    28  		w.rb.src = inputBytes(data[:m])
    29  		w.rb.nsrc = m
    30  		w.buf = doAppend(&w.rb, w.buf, 0)
    31  		data = data[m:]
    32  		n += m
    33  
    34  		// Write out complete prefix, save remainder.
    35  		// Note that lastBoundary looks back at most 31 runes.
    36  		i := lastBoundary(&w.rb.f, w.buf)
    37  		if i == -1 {
    38  			i = 0
    39  		}
    40  		if i > 0 {
    41  			if _, err = w.w.Write(w.buf[:i]); err != nil {
    42  				break
    43  			}
    44  			bn := copy(w.buf, w.buf[i:])
    45  			w.buf = w.buf[:bn]
    46  		}
    47  	}
    48  	return n, err
    49  }
    50  
    51  // Close forces data that remains in the buffer to be written.
    52  func (w *normWriter) Close() error {
    53  	if len(w.buf) > 0 {
    54  		_, err := w.w.Write(w.buf)
    55  		if err != nil {
    56  			return err
    57  		}
    58  	}
    59  	return nil
    60  }
    61  
    62  // Writer returns a new writer that implements Write(b)
    63  // by writing f(b) to w. The returned writer may use an
    64  // internal buffer to maintain state across Write calls.
    65  // Calling its Close method writes any buffered data to w.
    66  func (f Form) Writer(w io.Writer) io.WriteCloser {
    67  	wr := &normWriter{rb: reorderBuffer{}, w: w}
    68  	wr.rb.init(f, nil)
    69  	return wr
    70  }
    71  
    72  type normReader struct {
    73  	rb           reorderBuffer
    74  	r            io.Reader
    75  	inbuf        []byte
    76  	outbuf       []byte
    77  	bufStart     int
    78  	lastBoundary int
    79  	err          error
    80  }
    81  
    82  // Read implements the standard read interface.
    83  func (r *normReader) Read(p []byte) (int, error) {
    84  	for {
    85  		if r.lastBoundary-r.bufStart > 0 {
    86  			n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
    87  			r.bufStart += n
    88  			if r.lastBoundary-r.bufStart > 0 {
    89  				return n, nil
    90  			}
    91  			return n, r.err
    92  		}
    93  		if r.err != nil {
    94  			return 0, r.err
    95  		}
    96  		outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
    97  		r.outbuf = r.outbuf[0:outn]
    98  		r.bufStart = 0
    99  
   100  		n, err := r.r.Read(r.inbuf)
   101  		r.rb.src = inputBytes(r.inbuf[0:n])
   102  		r.rb.nsrc, r.err = n, err
   103  		if n > 0 {
   104  			r.outbuf = doAppend(&r.rb, r.outbuf, 0)
   105  		}
   106  		if err == io.EOF {
   107  			r.lastBoundary = len(r.outbuf)
   108  		} else {
   109  			r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
   110  			if r.lastBoundary == -1 {
   111  				r.lastBoundary = 0
   112  			}
   113  		}
   114  	}
   115  }
   116  
   117  // Reader returns a new reader that implements Read
   118  // by reading data from r and returning f(data).
   119  func (f Form) Reader(r io.Reader) io.Reader {
   120  	const chunk = 4000
   121  	buf := make([]byte, chunk)
   122  	rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
   123  	rr.rb.init(f, buf)
   124  	return rr
   125  }
   126  

View as plain text