Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 1 | // 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 | |
| 10 | package mysql |
| 11 | |
Julien Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 12 | import "io" |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 13 | |
Julien Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 14 | const defaultBufSize = 4096 |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 15 | |
Julien Schmidt | e2532ba | 2013-06-02 01:40:54 | [diff] [blame] | 16 | // A read buffer similar to bufio.Reader but zero-copy-ish |
| 17 | // Also highly optimized for this particular use case. |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 18 | type buffer struct { |
| 19 | buf []byte |
| 20 | rd io.Reader |
| 21 | idx int |
| 22 | length int |
| 23 | } |
| 24 | |
| 25 | func newBuffer(rd io.Reader) *buffer { |
Julien Schmidt | 04653f2 | 2013-06-03 20:34:22 | [diff] [blame] | 26 | var b [defaultBufSize]byte |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 27 | return &buffer{ |
Julien Schmidt | 04653f2 | 2013-06-03 20:34:22 | [diff] [blame] | 28 | buf: b[:], |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 29 | rd: rd, |
| 30 | } |
| 31 | } |
| 32 | |
Julien Schmidt | c2dde2d | 2013-04-21 13:16:44 | [diff] [blame] | 33 | // fill reads into the buffer until at least _need_ bytes are in it |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 34 | func (b *buffer) fill(need int) (err error) { |
Julien Schmidt | c2dde2d | 2013-04-21 13:16:44 | [diff] [blame] | 35 | // 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 Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 40 | // grow buffer if necessary |
| 41 | if need > len(b.buf) { |
Julien Schmidt | 04653f2 | 2013-06-03 20:34:22 | [diff] [blame] | 42 | newBuf := make([]byte, need) |
| 43 | copy(newBuf, b.buf) |
| 44 | b.buf = newBuf |
Julien Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 45 | } |
| 46 | |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 47 | b.idx = 0 |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 48 | |
Julien Schmidt | d1deaee | 2013-03-06 02:06:50 | [diff] [blame] | 49 | var n int |
Julien Schmidt | e2532ba | 2013-06-02 01:40:54 | [diff] [blame] | 50 | for { |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 51 | n, err = b.rd.Read(b.buf[b.length:]) |
| 52 | b.length += n |
Julien Schmidt | 74a6452 | 2013-03-03 17:41:13 | [diff] [blame] | 53 | |
Julien Schmidt | e2532ba | 2013-06-02 01:40:54 | [diff] [blame] | 54 | if b.length < need && err == nil { |
Julien Schmidt | 74a6452 | 2013-03-03 17:41:13 | [diff] [blame] | 55 | continue |
| 56 | } |
| 57 | return // err |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 58 | } |
Julien Schmidt | b494bac | 2013-06-02 13:53:19 | [diff] [blame] | 59 | return |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 60 | } |
| 61 | |
Julien Schmidt | 96a4f13 | 2013-04-21 12:57:58 | [diff] [blame] | 62 | // returns next N bytes from buffer. |
| 63 | // The returned slice is only guaranteed to be valid until the next read |
| 64 | func (b *buffer) readNext(need int) (p []byte, err error) { |
Julien Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 65 | if b.length < need { |
| 66 | // refill |
| 67 | err = b.fill(need) // err deferred |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 68 | } |
Julien Schmidt | a602069 | 2013-04-24 14:40:08 | [diff] [blame] | 69 | |
| 70 | p = b.buf[b.idx : b.idx+need] |
| 71 | b.idx += need |
| 72 | b.length -= need |
Julien Schmidt | ccad956 | 2013-03-01 19:31:43 | [diff] [blame] | 73 | return |
| 74 | } |