99
1010package mysql
1111
12- import (
13- "io"
14- )
12+ import "io"
1513
16- const (
17- defaultBufSize = 4096
18- )
14+ const defaultBufSize = 4096
1915
2016type buffer struct {
2117 buf []byte
@@ -31,11 +27,19 @@ func newBuffer(rd io.Reader) *buffer {
3127 }
3228}
3329
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
3631func (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+
3742 b .idx = 0
38- b .length = 0
3943
4044 var n int
4145 for b .length < need {
@@ -51,34 +55,33 @@ func (b *buffer) fill(need int) (err error) {
5155 return
5256}
5357
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+ }
6769
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+ }
7775
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
7881 err = b .fill (need ) // err deferred
7982 }
8083
81- copy ( p , b .buf [b .idx :])
84+ p = b .buf [b .idx : b . idx + need ]
8285 b .idx += need
8386 b .length -= need
8487 return
0 commit comments