github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mahonia/reader.go (about)

     1  package mahonia
     2  
     3  // This file is based on bufio.Reader in the Go standard library,
     4  // which has the following copyright notice:
     5  
     6  // Copyright 2009 The Go Authors. All rights reserved.
     7  // Use of this source code is governed by a BSD-style
     8  // license that can be found in the LICENSE file.
     9  
    10  import (
    11  	"io"
    12  	"unicode/utf8"
    13  )
    14  
    15  const (
    16  	defaultBufSize = 4096
    17  )
    18  
    19  // Reader implements character-set decoding for an io.Reader object.
    20  type Reader struct {
    21  	buf    []byte
    22  	rd     io.Reader
    23  	decode Decoder
    24  	r, w   int
    25  	err    error
    26  }
    27  
    28  // NewReader creates a new Reader that uses the receiver to decode text.
    29  func (d Decoder) NewReader(rd io.Reader) *Reader {
    30  	b := new(Reader)
    31  	b.buf = make([]byte, defaultBufSize)
    32  	b.rd = rd
    33  	b.decode = d
    34  	return b
    35  }
    36  
    37  // fill reads a new chunk into the buffer.
    38  func (b *Reader) fill() {
    39  	// Slide existing data to beginning.
    40  	if b.r > 0 {
    41  		copy(b.buf, b.buf[b.r:b.w])
    42  		b.w -= b.r
    43  		b.r = 0
    44  	}
    45  
    46  	// Read new data.
    47  	n, e := b.rd.Read(b.buf[b.w:])
    48  	b.w += n
    49  	if e != nil {
    50  		b.err = e
    51  	}
    52  }
    53  
    54  // Read reads data into p.
    55  // It returns the number of bytes read into p.
    56  // It calls Read at most once on the underlying Reader,
    57  // hence n may be less than len(p).
    58  // At EOF, the count will be zero and err will be os.EOF.
    59  func (b *Reader) Read(p []byte) (n int, err error) {
    60  	n = len(p)
    61  	filled := false
    62  	if n == 0 {
    63  		return 0, b.err
    64  	}
    65  	if b.w == b.r {
    66  		if b.err != nil {
    67  			return 0, b.err
    68  		}
    69  		if n > len(b.buf) {
    70  			// Large read, empty buffer.
    71  			// Allocate a larger buffer for efficiency.
    72  			b.buf = make([]byte, n)
    73  		}
    74  		b.fill()
    75  		filled = true
    76  		if b.w == b.r {
    77  			return 0, b.err
    78  		}
    79  	}
    80  
    81  	i := 0
    82  	for i < n {
    83  		rune, size, status := b.decode(b.buf[b.r:b.w])
    84  
    85  		if status == STATE_ONLY {
    86  			b.r += size
    87  			continue
    88  		}
    89  
    90  		if status == NO_ROOM {
    91  			if b.err != nil {
    92  				rune = 0xfffd
    93  				size = b.w - b.r
    94  				if size == 0 {
    95  					break
    96  				}
    97  				status = INVALID_CHAR
    98  			} else if filled {
    99  				break
   100  			} else {
   101  				b.fill()
   102  				filled = true
   103  				continue
   104  			}
   105  		}
   106  
   107  		if i+utf8.RuneLen(rune) > n {
   108  			break
   109  		}
   110  
   111  		b.r += size
   112  		if rune < 128 {
   113  			p[i] = byte(rune)
   114  			i++
   115  		} else {
   116  			i += utf8.EncodeRune(p[i:], rune)
   117  		}
   118  	}
   119  
   120  	return i, nil
   121  }
   122  
   123  // ReadRune reads a single Unicode character and returns the
   124  // rune and its size in bytes.
   125  func (b *Reader) ReadRune() (c rune, size int, err error) {
   126  read:
   127  	c, size, status := b.decode(b.buf[b.r:b.w])
   128  
   129  	if status == NO_ROOM && b.err == nil {
   130  		b.fill()
   131  		goto read
   132  	}
   133  
   134  	if status == STATE_ONLY {
   135  		b.r += size
   136  		goto read
   137  	}
   138  
   139  	if b.r == b.w {
   140  		return 0, 0, b.err
   141  	}
   142  
   143  	if status == NO_ROOM {
   144  		c = 0xfffd
   145  		size = b.w - b.r
   146  		status = INVALID_CHAR
   147  	}
   148  
   149  	b.r += size
   150  	return c, size, nil
   151  }