buffer.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. package mysql
  10. import "io"
  11. const defaultBufSize = 4096
  12. type buffer struct {
  13. buf []byte
  14. rd io.Reader
  15. idx int
  16. length int
  17. }
  18. func newBuffer(rd io.Reader) *buffer {
  19. return &buffer{
  20. buf: make([]byte, defaultBufSize),
  21. rd: rd,
  22. }
  23. }
  24. // fill reads into the buffer until at least _need_ bytes are in it
  25. func (b *buffer) fill(need int) (err error) {
  26. // move existing data to the beginning
  27. if b.length > 0 && b.idx > 0 {
  28. copy(b.buf[0:b.length], b.buf[b.idx:])
  29. }
  30. // grow buffer if necessary
  31. if need > len(b.buf) {
  32. b.grow(need)
  33. }
  34. b.idx = 0
  35. var n int
  36. for b.length < need {
  37. n, err = b.rd.Read(b.buf[b.length:])
  38. b.length += n
  39. if err == nil {
  40. continue
  41. }
  42. return // err
  43. }
  44. return
  45. }
  46. // grow the buffer to at least the given size
  47. // credit for this code snippet goes to Maxim Khitrov
  48. // https://groups.google.com/forum/#!topic/golang-nuts/ETbw1ECDgRs
  49. func (b *buffer) grow(size int) {
  50. // If append would be too expensive, alloc a new slice
  51. if size > 2*cap(b.buf) {
  52. newBuf := make([]byte, size)
  53. copy(newBuf, b.buf)
  54. b.buf = newBuf
  55. return
  56. }
  57. for cap(b.buf) < size {
  58. b.buf = append(b.buf[:cap(b.buf)], 0)
  59. }
  60. b.buf = b.buf[:cap(b.buf)]
  61. }
  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) {
  65. if b.length < need {
  66. // refill
  67. err = b.fill(need) // err deferred
  68. if err == io.EOF && b.length >= need {
  69. err = nil
  70. }
  71. }
  72. p = b.buf[b.idx : b.idx+need]
  73. b.idx += need
  74. b.length -= need
  75. return
  76. }