-
Notifications
You must be signed in to change notification settings - Fork 2
/
buffer.go
117 lines (105 loc) · 1.81 KB
/
buffer.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package redisgo
import (
"bytes"
"io"
)
const minReadBufferSize = 100
type reader struct {
rd io.Reader
b []byte
r int
w int
sz int
}
func newReader(r io.Reader, sz int) *reader {
if sz < minReadBufferSize {
sz = minReadBufferSize
}
br := new(reader)
br.rd = r
br.b = make([]byte, sz)
br.sz = sz
return br
}
func (r *reader) buffered() int {
return r.w - r.r
}
func (r *reader) free() int {
return len(r.b) - r.w
}
func (r *reader) bytes() []byte {
return r.b[r.r:r.w]
}
func (r *reader) buf() []byte {
return r.b[r.w:]
}
func (r *reader) readmore(n int) error {
if r.free() < n {
sz := r.sz
b := r.bytes()
for sz-len(b) < n {
sz += r.sz
}
r.b = make([]byte, sz)
r.r = 0
r.w = copy(r.b, b)
}
readn, err := io.ReadAtLeast(r.rd, r.buf(), n)
if readn > 0 {
r.w += readn
}
return err
}
// Read reads n bytes from underlying reader
func (r *reader) Read(n int) (b []byte, err error) {
if bn := r.buffered(); bn < n {
if err = r.readmore(n - bn); err != nil {
return
}
}
b = r.bytes()[:n:n]
r.r += n
return
}
func (r *reader) fillmore() error {
if r.free() < minReadBufferSize || r.buffered() > r.sz/2 {
b := r.bytes()
sz := 2 * len(b)
if sz < r.sz {
sz = r.sz
}
r.b = make([]byte, sz)
r.r = 0
r.w = copy(r.b, b)
}
readn, err := r.rd.Read(r.buf())
if readn > 0 {
r.w += readn
if err == io.EOF {
err = nil
}
}
return err
}
// Readline reads line ending with CRLF
func (r *reader) Readline() (b []byte, err error) {
if r.buffered() == 0 {
err = r.fillmore()
}
start := 0
for err == nil {
p := r.bytes()
pos := bytes.IndexByte(p[start:], LF)
if pos > 0 && p[start+pos-1] == CR {
b = p[: start+pos+1 : start+pos+1]
r.r += (start + pos + 1)
return
}
if pos >= 0 {
start += pos + 1
continue
}
err = r.fillmore()
}
return
}