buffer.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 (
  11. "io"
  12. )
  13. const (
  14. defaultBufSize = 4096
  15. )
  16. type buffer struct {
  17. buf []byte
  18. rd io.Reader
  19. idx int
  20. length int
  21. }
  22. func newBuffer(rd io.Reader) *buffer {
  23. return &buffer{
  24. buf: make([]byte, defaultBufSize),
  25. rd: rd,
  26. }
  27. }
  28. // fill reads into the buffer until at least _need_ bytes are in it
  29. func (b *buffer) fill(need int) (err error) {
  30. // move existing data to the beginning
  31. if b.length > 0 && b.idx > 0 {
  32. copy(b.buf[0:b.length], b.buf[b.idx:])
  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. // returns next N bytes from buffer.
  47. // The returned slice is only guaranteed to be valid until the next read
  48. func (b *buffer) readNext(need int) (p []byte, err error) {
  49. // return slice from buffer if possible
  50. if b.length >= need {
  51. p = b.buf[b.idx : b.idx+need]
  52. b.idx += need
  53. b.length -= need
  54. return
  55. } else {
  56. // does the data fit into the buffer?
  57. if need < len(b.buf) {
  58. // refill
  59. err = b.fill(need) // err deferred
  60. p = b.buf[:need]
  61. b.idx += need
  62. b.length -= need
  63. return
  64. } else {
  65. p = make([]byte, need)
  66. has := 0
  67. // copy data that is already in the buffer
  68. if b.length > 0 {
  69. copy(p[0:b.length], b.buf[b.idx:])
  70. has = b.length
  71. need -= has
  72. b.idx = 0
  73. b.length = 0
  74. }
  75. // read rest directly into the new slice
  76. var n int
  77. for err == nil && need > 0 {
  78. n, err = b.rd.Read(p[has:])
  79. has += n
  80. need -= n
  81. }
  82. }
  83. }
  84. return
  85. }