-
Notifications
You must be signed in to change notification settings - Fork 109
/
reader.go
81 lines (73 loc) · 1.33 KB
/
reader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package iconv
import (
"io"
)
// Reader represents an auto encoding converting Reader.
type Reader struct {
rdbuf []byte
cnvbuf []byte
cd Iconv
input io.Reader
from, to int // rdbuf[from:to] is valid
m int // cnvbuf[:m] is valid
err error
}
// NewReader creates a new reader.
func NewReader(cd Iconv, input io.Reader, bufSize int) *Reader {
if bufSize < 16 {
bufSize = DefaultBufSize
}
rdbuf := make([]byte, bufSize)
cnvbuf := make([]byte, bufSize)
return &Reader{rdbuf, cnvbuf, cd, input, 0, 0, 0, nil}
}
// Input changes the input stream.
func (r *Reader) Input(r1 io.Reader) {
r.input = r1
r.from, r.to, r.m = 0, 0, 0
r.err = nil
}
func (r *Reader) fetch() error {
var m int
if r.err != nil {
return r.err
}
m, r.err = r.input.Read(r.cnvbuf[r.m:])
m += r.m
if m == 0 {
return io.EOF
}
r.from = 0
r.to, r.m, r.err = r.cd.Do(r.cnvbuf, m, r.rdbuf)
if r.err != EILSEQ {
r.err = nil
}
if r.m > 0 {
copy(r.cnvbuf[:r.m], r.cnvbuf[m-r.m:m])
}
if r.to == 0 {
if r.err == nil {
return io.EOF
}
return r.err
}
return nil
}
func (r *Reader) Read(b []byte) (n int, err error) {
for {
if r.from < r.to {
n1 := copy(b, r.rdbuf[r.from:r.to])
n += n1
r.from += n1
if n1 == len(b) {
break
}
b = b[n1:]
}
err = r.fetch()
if err != nil {
break
}
}
return
}