buffer.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public
  6. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  7. // You can obtain one at http://mozilla.org/MPL/2.0/.
  8. package mysql
  9. import "io"
  10. const defaultBufSize = 4096
  11. // A read buffer similar to bufio.Reader but zero-copy-ish
  12. // Also highly optimized for this particular use case.
  13. type buffer struct {
  14. buf []byte
  15. rd io.Reader
  16. idx int
  17. length int
  18. }
  19. func newBuffer(rd io.Reader) *buffer {
  20. var b [defaultBufSize]byte
  21. return &buffer{
  22. buf: b[:],
  23. rd: rd,
  24. }
  25. }
  26. // fill reads into the buffer until at least _need_ bytes are in it
  27. func (b *buffer) fill(need int) (err error) {
  28. // move existing data to the beginning
  29. if b.length > 0 && b.idx > 0 {
  30. copy(b.buf[0:b.length], b.buf[b.idx:])
  31. }
  32. // grow buffer if necessary
  33. if need > len(b.buf) {
  34. newBuf := make([]byte, need)
  35. copy(newBuf, b.buf)
  36. b.buf = newBuf
  37. }
  38. b.idx = 0
  39. var n int
  40. for {
  41. n, err = b.rd.Read(b.buf[b.length:])
  42. b.length += n
  43. if b.length < need && err == nil {
  44. continue
  45. }
  46. return // err
  47. }
  48. return
  49. }
  50. // returns next N bytes from buffer.
  51. // The returned slice is only guaranteed to be valid until the next read
  52. func (b *buffer) readNext(need int) (p []byte, err error) {
  53. if b.length < need {
  54. // refill
  55. err = b.fill(need) // err deferred
  56. if err == io.EOF && b.length >= need {
  57. err = nil
  58. }
  59. }
  60. p = b.buf[b.idx : b.idx+need]
  61. b.idx += need
  62. b.length -= need
  63. return
  64. }