blob: ca790d32fc31540740d9f305af5ec8001c9fc445 [file] [log] [blame]
Julien Schmidtccad9562013-03-01 19:31:431// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
2//
3// Copyright 2013 Julien Schmidt. All rights reserved.
4// http://www.julienschmidt.com
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this file,
8// You can obtain one at http://mozilla.org/MPL/2.0/.
9
10package mysql
11
Julien Schmidta6020692013-04-24 14:40:0812import "io"
Julien Schmidtccad9562013-03-01 19:31:4313
Julien Schmidta6020692013-04-24 14:40:0814const defaultBufSize = 4096
Julien Schmidtccad9562013-03-01 19:31:4315
Julien Schmidte2532ba2013-06-02 01:40:5416// A read buffer similar to bufio.Reader but zero-copy-ish
17// Also highly optimized for this particular use case.
Julien Schmidtccad9562013-03-01 19:31:4318type buffer struct {
19 buf []byte
20 rd io.Reader
21 idx int
22 length int
23}
24
25func newBuffer(rd io.Reader) *buffer {
Julien Schmidt04653f22013-06-03 20:34:2226 var b [defaultBufSize]byte
Julien Schmidtccad9562013-03-01 19:31:4327 return &buffer{
Julien Schmidt04653f22013-06-03 20:34:2228 buf: b[:],
Julien Schmidtccad9562013-03-01 19:31:4329 rd: rd,
30 }
31}
32
Julien Schmidtc2dde2d2013-04-21 13:16:4433// fill reads into the buffer until at least _need_ bytes are in it
Julien Schmidtccad9562013-03-01 19:31:4334func (b *buffer) fill(need int) (err error) {
Julien Schmidtc2dde2d2013-04-21 13:16:4435 // move existing data to the beginning
36 if b.length > 0 && b.idx > 0 {
37 copy(b.buf[0:b.length], b.buf[b.idx:])
38 }
39
Julien Schmidta6020692013-04-24 14:40:0840 // grow buffer if necessary
41 if need > len(b.buf) {
Julien Schmidt04653f22013-06-03 20:34:2242 newBuf := make([]byte, need)
43 copy(newBuf, b.buf)
44 b.buf = newBuf
Julien Schmidta6020692013-04-24 14:40:0845 }
46
Julien Schmidtccad9562013-03-01 19:31:4347 b.idx = 0
Julien Schmidtccad9562013-03-01 19:31:4348
Julien Schmidtd1deaee2013-03-06 02:06:5049 var n int
Julien Schmidte2532ba2013-06-02 01:40:5450 for {
Julien Schmidtccad9562013-03-01 19:31:4351 n, err = b.rd.Read(b.buf[b.length:])
52 b.length += n
Julien Schmidt74a64522013-03-03 17:41:1353
Julien Schmidte2532ba2013-06-02 01:40:5454 if b.length < need && err == nil {
Julien Schmidt74a64522013-03-03 17:41:1355 continue
56 }
57 return // err
Julien Schmidtccad9562013-03-01 19:31:4358 }
Julien Schmidtb494bac2013-06-02 13:53:1959 return
Julien Schmidtccad9562013-03-01 19:31:4360}
61
Julien Schmidt96a4f132013-04-21 12:57:5862// returns next N bytes from buffer.
63// The returned slice is only guaranteed to be valid until the next read
64func (b *buffer) readNext(need int) (p []byte, err error) {
Julien Schmidta6020692013-04-24 14:40:0865 if b.length < need {
66 // refill
67 err = b.fill(need) // err deferred
Julien Schmidtccad9562013-03-01 19:31:4368 }
Julien Schmidta6020692013-04-24 14:40:0869
70 p = b.buf[b.idx : b.idx+need]
71 b.idx += need
72 b.length -= need
Julien Schmidtccad9562013-03-01 19:31:4373 return
74}