9
9
10
10
package mysql
11
11
12
- import (
13
- "io"
14
- )
12
+ import "io"
15
13
16
- const (
17
- defaultBufSize = 4096
18
- )
14
+ const defaultBufSize = 4096
19
15
20
16
type buffer struct {
21
17
buf []byte
@@ -31,11 +27,19 @@ func newBuffer(rd io.Reader) *buffer {
31
27
}
32
28
}
33
29
34
- // fill reads at least _need_ bytes in the buffer
35
- // existing data in the buffer gets lost
30
+ // fill reads into the buffer until at least _need_ bytes are in it
36
31
func (b * buffer ) fill (need int ) (err error ) {
32
+ // move existing data to the beginning
33
+ if b .length > 0 && b .idx > 0 {
34
+ copy (b .buf [0 :b .length ], b .buf [b .idx :])
35
+ }
36
+
37
+ // grow buffer if necessary
38
+ if need > len (b .buf ) {
39
+ b .grow (need )
40
+ }
41
+
37
42
b .idx = 0
38
- b .length = 0
39
43
40
44
var n int
41
45
for b .length < need {
@@ -51,34 +55,33 @@ func (b *buffer) fill(need int) (err error) {
51
55
return
52
56
}
53
57
54
- // read len(p) bytes
55
- func (b * buffer ) read (p []byte ) (err error ) {
56
- need := len (p )
57
-
58
- if b .length < need {
59
- if b .length > 0 {
60
- copy (p [0 :b .length ], b .buf [b .idx :])
61
- need -= b .length
62
- p = p [b .length :]
63
-
64
- b .idx = 0
65
- b .length = 0
66
- }
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
+ }
67
69
68
- if need >= len (b .buf ) {
69
- var n int
70
- has := 0
71
- for err == nil && need > has {
72
- n , err = b .rd .Read (p [has :])
73
- has += n
74
- }
75
- return
76
- }
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
+ }
77
75
76
+ // returns next N bytes from buffer.
77
+ // The returned slice is only guaranteed to be valid until the next read
78
+ func (b * buffer ) readNext (need int ) (p []byte , err error ) {
79
+ if b .length < need {
80
+ // refill
78
81
err = b .fill (need ) // err deferred
79
82
}
80
83
81
- copy ( p , b .buf [b .idx :])
84
+ p = b .buf [b .idx : b . idx + need ]
82
85
b .idx += need
83
86
b .length -= need
84
87
return
0 commit comments