-
Notifications
You must be signed in to change notification settings - Fork 5
/
byte_reader.go
141 lines (110 loc) · 2.38 KB
/
byte_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
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package rdb
import (
"io"
)
const (
maxBufferSize = 4096
minReadSize = 512
)
type byteReader interface {
ReadBytes(n int) ([]byte, error)
}
type sliceReader struct {
data []byte
offset int
}
func newSliceReader(data []byte) *sliceReader {
return &sliceReader{
data: data,
}
}
func (b *sliceReader) ReadBytes(n int) ([]byte, error) {
offset := b.offset
remaining := len(b.data) - offset
if remaining <= 0 {
return nil, io.EOF
}
if remaining < n {
n = remaining
}
b.offset += n
return b.data[offset : offset+n], nil
}
type bufferReader struct {
r io.Reader
offset int
length int
buf []byte
}
func newBufferReader(r io.Reader) *bufferReader {
return &bufferReader{
r: r,
}
}
func (b *bufferReader) ReadBytes(n int) ([]byte, error) {
if n > maxBufferSize {
return b.readIntoNewBuffer(n)
}
if b.remaining() < n {
if err := b.fill(n); err != nil {
return nil, err
}
}
offset := b.offset
b.offset += n
return b.buf[offset : offset+n], nil
}
func (b *bufferReader) remaining() int {
return b.length - b.offset
}
func (b *bufferReader) readIntoNewBuffer(n int) ([]byte, error) {
// Allocate a new buffer for the result
buf := make([]byte, n)
// Copy the remaining data to the result
copied := copy(buf, b.buf[b.offset:b.length])
// Reset the length and the offset
b.offset = 0
b.length = 0
// Read the data into the result
if _, err := io.ReadFull(b.r, buf[copied:]); err != nil {
return nil, err
}
return buf, nil
}
func (b *bufferReader) fill(n int) error {
remaining := b.remaining()
minRead := n - remaining
readSize := max(minRead, minReadSize)
minCap := remaining + readSize
// If the buffer capacity is not enough for reading
if b.length+readSize > cap(b.buf) {
if minCap <= cap(b.buf) {
// Move the remaining data to the front if the buffer is enough
copy(b.buf, b.buf[b.offset:b.length])
} else {
// Otherwise, allocate a bigger buffer
bufSize := max(cap(b.buf), minReadSize)
for bufSize < minCap && bufSize < maxBufferSize {
bufSize *= 2
}
buf := make([]byte, bufSize)
copy(buf, b.buf[b.offset:b.length])
b.buf = buf
}
b.length -= b.offset
b.offset = 0
}
// Read the buffer to its capacity
read, err := io.ReadAtLeast(b.r, b.buf[b.length:], minRead)
if err != nil {
return err
}
b.length += read
return nil
}
func max(a, b int) int {
if a > b {
return a
}
return b
}