@@ -13,6 +13,8 @@ import "io"
13
13
14
14
const defaultBufSize = 4096
15
15
16
+ // A read buffer similar to bufio.Reader but zero-copy-ish
17
+ // Also highly optimized for this particular use case.
16
18
type buffer struct {
17
19
buf []byte
18
20
rd io.Reader
@@ -36,43 +38,31 @@ func (b *buffer) fill(need int) (err error) {
36
38
37
39
// grow buffer if necessary
38
40
if need > len (b .buf ) {
39
- b .grow (need )
41
+ for {
42
+ b .buf = append (b .buf , 0 )
43
+ b .buf = b .buf [:cap (b .buf )]
44
+
45
+ if cap (b .buf ) >= need {
46
+ break
47
+ }
48
+ }
40
49
}
41
50
42
51
b .idx = 0
43
52
44
53
var n int
45
- for b . length < need {
54
+ for {
46
55
n , err = b .rd .Read (b .buf [b .length :])
47
56
b .length += n
48
57
49
- if err == nil {
58
+ if b . length < need && err == nil {
50
59
continue
51
60
}
52
61
return // err
53
62
}
54
-
55
63
return
56
64
}
57
65
58
- // grow the buffer to at least the given size
59
- // credit for this code snippet goes to Maxim Khitrov
60
- // https://groups.google.com/forum/#!topic/golang-nuts/ETbw1ECDgRs
61
- func (b * buffer ) grow (size int ) {
62
- // If append would be too expensive, alloc a new slice
63
- if size > 2 * cap (b .buf ) {
64
- newBuf := make ([]byte , size )
65
- copy (newBuf , b .buf )
66
- b .buf = newBuf
67
- return
68
- }
69
-
70
- for cap (b .buf ) < size {
71
- b .buf = append (b .buf [:cap (b .buf )], 0 )
72
- }
73
- b .buf = b .buf [:cap (b .buf )]
74
- }
75
-
76
66
// returns next N bytes from buffer.
77
67
// The returned slice is only guaranteed to be valid until the next read
78
68
func (b * buffer ) readNext (need int ) (p []byte , err error ) {
0 commit comments