Skip to content

Commit c2dde2d

Browse files
committed
optimized buffer refill
No extra allocation when refilling the buffer Closes #52
1 parent 96a4f13 commit c2dde2d

File tree

1 file changed

+21
-15
lines changed

1 file changed

+21
-15
lines changed

buffer.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ func newBuffer(rd io.Reader) *buffer {
3131
}
3232
}
3333

34-
// fill reads at least _need_ bytes in the buffer
35-
// existing data in the buffer gets lost
34+
// fill reads into the buffer until at least _need_ bytes are in it
3635
func (b *buffer) fill(need int) (err error) {
36+
// move existing data to the beginning
37+
if b.length > 0 && b.idx > 0 {
38+
copy(b.buf[0:b.length], b.buf[b.idx:])
39+
}
40+
3741
b.idx = 0
38-
b.length = 0
3942

4043
var n int
4144
for b.length < need {
@@ -62,27 +65,30 @@ func (b *buffer) readNext(need int) (p []byte, err error) {
6265
return
6366

6467
} else {
65-
p = make([]byte, need)
66-
has := 0
67-
68-
// copy data that is already in the buffer
69-
if b.length > 0 {
70-
copy(p[0:b.length], b.buf[b.idx:])
71-
has = b.length
72-
need -= has
73-
b.idx = 0
74-
b.length = 0
75-
}
7668

7769
// does the data fit into the buffer?
7870
if need < len(b.buf) {
71+
// refill
7972
err = b.fill(need) // err deferred
80-
copy(p[has:has+need], b.buf[b.idx:])
73+
p = b.buf[:need]
8174
b.idx += need
8275
b.length -= need
8376
return
8477

8578
} else {
79+
p = make([]byte, need)
80+
has := 0
81+
82+
// copy data that is already in the buffer
83+
if b.length > 0 {
84+
copy(p[0:b.length], b.buf[b.idx:])
85+
has = b.length
86+
need -= has
87+
b.idx = 0
88+
b.length = 0
89+
}
90+
91+
// read rest directly into the new slice
8692
var n int
8793
for err == nil && need > 0 {
8894
n, err = b.rd.Read(p[has:])

0 commit comments

Comments
 (0)