|
|
@@ -9,13 +9,9 @@
|
|
|
|
|
|
package mysql
|
|
|
|
|
|
-import (
|
|
|
- "io"
|
|
|
-)
|
|
|
+import "io"
|
|
|
|
|
|
-const (
|
|
|
- defaultBufSize = 4096
|
|
|
-)
|
|
|
+const defaultBufSize = 4096
|
|
|
|
|
|
type buffer struct {
|
|
|
buf []byte
|
|
|
@@ -31,11 +27,19 @@ func newBuffer(rd io.Reader) *buffer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// fill reads at least _need_ bytes in the buffer
|
|
|
-// existing data in the buffer gets lost
|
|
|
+// fill reads into the buffer until at least _need_ bytes are in it
|
|
|
func (b *buffer) fill(need int) (err error) {
|
|
|
+ // move existing data to the beginning
|
|
|
+ if b.length > 0 && b.idx > 0 {
|
|
|
+ copy(b.buf[0:b.length], b.buf[b.idx:])
|
|
|
+ }
|
|
|
+
|
|
|
+ // grow buffer if necessary
|
|
|
+ if need > len(b.buf) {
|
|
|
+ b.grow(need)
|
|
|
+ }
|
|
|
+
|
|
|
b.idx = 0
|
|
|
- b.length = 0
|
|
|
|
|
|
var n int
|
|
|
for b.length < need {
|
|
|
@@ -51,34 +55,33 @@ func (b *buffer) fill(need int) (err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-// read len(p) bytes
|
|
|
-func (b *buffer) read(p []byte) (err error) {
|
|
|
- need := len(p)
|
|
|
-
|
|
|
- if b.length < need {
|
|
|
- if b.length > 0 {
|
|
|
- copy(p[0:b.length], b.buf[b.idx:])
|
|
|
- need -= b.length
|
|
|
- p = p[b.length:]
|
|
|
-
|
|
|
- b.idx = 0
|
|
|
- b.length = 0
|
|
|
- }
|
|
|
+// grow the buffer to at least the given size
|
|
|
+// credit for this code snippet goes to Maxim Khitrov
|
|
|
+// https://groups.google.com/forum/#!topic/golang-nuts/ETbw1ECDgRs
|
|
|
+func (b *buffer) grow(size int) {
|
|
|
+ // If append would be too expensive, alloc a new slice
|
|
|
+ if size > 2*cap(b.buf) {
|
|
|
+ newBuf := make([]byte, size)
|
|
|
+ copy(newBuf, b.buf)
|
|
|
+ b.buf = newBuf
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- if need >= len(b.buf) {
|
|
|
- var n int
|
|
|
- has := 0
|
|
|
- for err == nil && need > has {
|
|
|
- n, err = b.rd.Read(p[has:])
|
|
|
- has += n
|
|
|
- }
|
|
|
- return
|
|
|
- }
|
|
|
+ for cap(b.buf) < size {
|
|
|
+ b.buf = append(b.buf[:cap(b.buf)], 0)
|
|
|
+ }
|
|
|
+ b.buf = b.buf[:cap(b.buf)]
|
|
|
+}
|
|
|
|
|
|
+// returns next N bytes from buffer.
|
|
|
+// The returned slice is only guaranteed to be valid until the next read
|
|
|
+func (b *buffer) readNext(need int) (p []byte, err error) {
|
|
|
+ if b.length < need {
|
|
|
+ // refill
|
|
|
err = b.fill(need) // err deferred
|
|
|
}
|
|
|
|
|
|
- copy(p, b.buf[b.idx:])
|
|
|
+ p = b.buf[b.idx : b.idx+need]
|
|
|
b.idx += need
|
|
|
b.length -= need
|
|
|
return
|