-
Notifications
You must be signed in to change notification settings - Fork 8
/
buf.go
308 lines (274 loc) · 8.21 KB
/
buf.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vom
import "io"
const minBufFree = 1024 // buffers always have at least 1K free after growth
// encbuf manages the write buffer for encoders. The approach is similar to
// bytes.Buffer, but the implementation is simplified to only deal with many
// writes followed by a read of the whole buffer.
type encbuf struct {
// It's faster to hold end than to use the len and cap properties of buf,
// since end is cheaper to update than buf.
buf []byte
end int // [0, end) is data that's already written
}
func newEncbuf() *encbuf {
return &encbuf{
buf: make([]byte, minBufFree),
}
}
// Bytes returns a slice of the bytes written so far.
func (b *encbuf) Bytes() []byte { return b.buf[:b.end] }
// Len returns the number of bytes written so far.
func (b *encbuf) Len() int { return b.end }
// Reset the length to 0 to start a new round of writes.
func (b *encbuf) Reset() { b.end = 0 }
// reserve at least min free bytes in the buffer.
func (b *encbuf) reserve(min int) {
if len(b.buf)-b.end < min {
newlen := len(b.buf) * 2
if newlen-b.end < min {
newlen = b.end + min + minBufFree
}
newbuf := make([]byte, newlen)
copy(newbuf, b.buf[:b.end])
b.buf = newbuf
}
}
// Grow the buffer by n bytes, and returns those bytes.
//
// Different from bytes.Buffer.Grow, which doesn't return the bytes.
func (b *encbuf) Grow(n int) []byte {
b.reserve(n)
oldend := b.end
b.end += n
return b.buf[oldend:b.end]
}
// WriteOneByte writes byte x into the buffer.
func (b *encbuf) WriteOneByte(x byte) {
b.reserve(1)
b.buf[b.end] = x
b.end++
}
// Write writes byte slice x to the buffer.
func (b *encbuf) Write(x []byte) {
b.reserve(len(x))
b.end += copy(b.buf[b.end:], x)
}
// WriteString writes string x to the buffer.
func (b *encbuf) WriteString(x string) {
b.reserve(len(x))
b.end += copy(b.buf[b.end:], x)
}
// decbuf manages the read buffer for decoders. The approach is similar to
// bufio.Reader, but the API is better suited for fast decoding.
type decbuf struct {
// It's faster to hold end than to use the len and cap properties of buf,
// since end is cheaper to update than buf.
buf []byte
beg, end int // [beg, end) is data read from reader but unread by the user
// lim holds the number of bytes left in the limit, or if it is any negative
// number, there is no limit. By allowing any negative number to convey "no
// limit", we avoid an extra conditional branch in the Read and Peek methods,
// making things faster. The downside is we need to worry about wraparound,
// but the limit gets reset often enough that this doesn't matter.
lim int
reader io.Reader
version Version
}
// newDecbuf returns a new decbuf that fills its internal buffer by reading r.
func newDecbuf(r io.Reader) *decbuf {
return &decbuf{
buf: make([]byte, minBufFree),
lim: -1,
reader: r,
}
}
// newDecbufFromBytes returns a new decbuf that reads directly from b.
func newDecbufFromBytes(b []byte) *decbuf {
return &decbuf{
buf: b,
end: len(b),
lim: -1,
reader: alwaysEOFReader{},
}
}
type alwaysEOFReader struct{}
func (alwaysEOFReader) Read([]byte) (int, error) { return 0, io.EOF }
// Reset resets the buffer so it has no data.
func (b *decbuf) Reset() {
b.beg = 0
b.end = 0
b.lim = -1
}
// SetLimit sets a limit to the bytes that are returned by decbuf; after a limit
// is set, subsequent reads cannot read past the limit, even if more bytes are
// available. Attempts to read past the limit return io.EOF. Call RemoveLimit
// to remove the limit.
//
// REQUIRES: limit >=0,
func (b *decbuf) SetLimit(limit int) {
b.lim = limit
}
// RemoveLimit removes the limit, and returns the number of leftover bytes.
// Returns a negative number if no limit was set.
func (b *decbuf) RemoveLimit() int {
leftover := b.lim
b.lim = -1
return leftover
}
// IsAvailable returns true iff at least n bytes are available to read, peek or
// skip. Call Fill to replenish the available bytes.
//
// The code is factored into IsAvailable followed by {Read,Peek,Skip}Available,
// since each of these methods is very short and doesn't call any other
// functions, allowing them to be inlined at the call site. This gives us a
// speedup in the common case where bytes are already available in the buffer.
func (b *decbuf) IsAvailable(n int) bool {
return b.end-b.beg >= n && (b.lim >= n || b.lim < 0)
}
// Fill the buffer with at least min bytes of data. Returns an error if fewer
// than min bytes could be filled. Doesn't advance the read position.
func (b *decbuf) Fill(min int) error {
if b.lim >= 0 && b.lim < min {
return io.EOF
}
switch avail := b.end - b.beg; {
case avail >= min:
// Fastpath - enough bytes are available.
return nil
case len(b.buf) < min:
// The buffer isn't big enough. Make a new buffer that's big enough and
// copy existing data to the front.
newlen := len(b.buf) * 2
if newlen < min+minBufFree {
newlen = min + minBufFree
}
newbuf := make([]byte, newlen)
b.end = copy(newbuf, b.buf[b.beg:b.end])
b.beg = 0
b.buf = newbuf
default:
// The buffer is big enough. Move existing data to the front.
b.moveDataToFront()
}
// INVARIANT: len(b.buf)-b.beg >= min
//
// Fill [b.end:] until min bytes are available. We must loop since Read may
// return success with fewer bytes than requested.
for b.end-b.beg < min {
switch nread, err := b.reader.Read(b.buf[b.end:]); {
case nread > 0:
b.end += nread
case err != nil:
return err
}
}
return nil
}
// moveDataToFront moves existing data in buf to the front, so that b.beg is 0.
func (b *decbuf) moveDataToFront() {
b.end = copy(b.buf, b.buf[b.beg:b.end])
b.beg = 0
}
// ReadAvailable returns a buffer with the next n bytes, and increments the read
// position past those bytes. The returned slice points directly at our
// internal buffer, and is only valid until the next decbuf call.
//
// REQUIRES: b.IsAvailable(n) && n >= 0
func (b *decbuf) ReadAvailable(n int) []byte {
b.lim -= n
buf := b.buf[b.beg : b.beg+n]
b.beg += n
return buf
}
// PeekAvailable is like ReadAvailable, but doesn't increment the read position.
func (b *decbuf) PeekAvailable(n int) []byte {
return b.buf[b.beg : b.beg+n]
}
// ReadAvailableByte returns the next byte, and increments the read position.
//
// REQUIRES: b.IsAvailable(1)
func (b *decbuf) ReadAvailableByte() byte {
b.lim--
ret := b.buf[b.beg]
b.beg++
return ret
}
// PeekAvailableByte is like ReadAvailableByte, but doesn't increment the read
// position.
func (b *decbuf) PeekAvailableByte() byte {
return b.buf[b.beg]
}
// ReadByte returns the next byte, and increments the read position.
func (b *decbuf) ReadByte() (byte, error) {
if !b.IsAvailable(1) {
if err := b.Fill(1); err != nil {
return 0, err
}
}
return b.ReadAvailableByte(), nil
}
// SkipAvailable increments the read position past the next n bytes.
//
// REQUIRES: b.IsAvailable(n) && n >= 0
func (b *decbuf) SkipAvailable(n int) {
b.lim -= n
b.beg += n
}
// Skip increments the read position past the next n bytes. Returns an error if
// fewer than n bytes are available.
//
// REQUIRES: n >= 0
func (b *decbuf) Skip(n int) error {
if b.lim >= 0 && b.lim < n {
return io.EOF
}
b.lim -= n
// If enough bytes are available, just update indices.
avail := b.end - b.beg
if avail >= n {
b.beg += n
return nil
}
n -= avail
// Keep reading into buf until we've read enough bytes.
for {
switch nread, err := b.reader.Read(b.buf); {
case nread > 0:
if nread >= n {
b.beg = n
b.end = nread
return nil
}
n -= nread
case err != nil:
return err
}
}
}
// ReadIntoBuf reads the next len(p) bytes into p, and increments the read position
// past those bytes. Returns an error if fewer than len(p) bytes are available.
func (b *decbuf) ReadIntoBuf(p []byte) error {
if b.lim > -1 {
if b.lim < len(p) {
return io.EOF
}
b.lim -= len(p)
}
// Copy bytes from the buffer.
ncopy := copy(p, b.buf[b.beg:b.end])
b.beg += ncopy
p = p[ncopy:]
// Keep reading into p until we've read enough bytes.
for len(p) > 0 {
switch nread, err := b.reader.Read(p); {
case nread > 0:
p = p[nread:]
case err != nil:
return err
}
}
return nil
}