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 }