buffer.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package buf
  2. import (
  3. "io"
  4. "github.com/v2fly/v2ray-core/v5/common/bytespool"
  5. )
  6. const (
  7. // Size of a regular buffer.
  8. Size = 2048
  9. )
  10. var pool = bytespool.GetPool(Size)
  11. // ownership represents the data owner of the buffer.
  12. type ownership uint8
  13. const (
  14. managed ownership = 0
  15. unmanaged ownership = 1
  16. bytespools ownership = 2
  17. )
  18. // Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
  19. // the buffer into an internal buffer pool, in order to recreate a buffer more
  20. // quickly.
  21. type Buffer struct {
  22. v []byte
  23. start int32
  24. end int32
  25. ownership ownership
  26. }
  27. // New creates a Buffer with 0 length and 2K capacity.
  28. func New() *Buffer {
  29. return &Buffer{
  30. v: pool.Get().([]byte),
  31. }
  32. }
  33. // NewWithSize creates a Buffer with 0 length and capacity with at least the given size.
  34. func NewWithSize(size int32) *Buffer {
  35. return &Buffer{
  36. v: bytespool.Alloc(size),
  37. ownership: bytespools,
  38. }
  39. }
  40. // FromBytes creates a Buffer with an existed bytearray
  41. func FromBytes(data []byte) *Buffer {
  42. return &Buffer{
  43. v: data,
  44. end: int32(len(data)),
  45. ownership: unmanaged,
  46. }
  47. }
  48. // StackNew creates a new Buffer object on stack.
  49. // This method is for buffers that is released in the same function.
  50. func StackNew() Buffer {
  51. return Buffer{
  52. v: pool.Get().([]byte),
  53. }
  54. }
  55. // Release recycles the buffer into an internal buffer pool.
  56. func (b *Buffer) Release() {
  57. if b == nil || b.v == nil || b.ownership == unmanaged {
  58. return
  59. }
  60. p := b.v
  61. b.v = nil
  62. b.Clear()
  63. switch b.ownership {
  64. case managed:
  65. pool.Put(p) // nolint: staticcheck
  66. case bytespools:
  67. bytespool.Free(p) // nolint: staticcheck
  68. }
  69. }
  70. // Clear clears the content of the buffer, results an empty buffer with
  71. // Len() = 0.
  72. func (b *Buffer) Clear() {
  73. b.start = 0
  74. b.end = 0
  75. }
  76. // Byte returns the bytes at index.
  77. func (b *Buffer) Byte(index int32) byte {
  78. return b.v[b.start+index]
  79. }
  80. // SetByte sets the byte value at index.
  81. func (b *Buffer) SetByte(index int32, value byte) {
  82. b.v[b.start+index] = value
  83. }
  84. // Bytes returns the content bytes of this Buffer.
  85. func (b *Buffer) Bytes() []byte {
  86. return b.v[b.start:b.end]
  87. }
  88. // Extend increases the buffer size by n bytes, and returns the extended part.
  89. // It panics if result size is larger than buf.Size.
  90. func (b *Buffer) Extend(n int32) []byte {
  91. end := b.end + n
  92. if end > int32(len(b.v)) {
  93. panic("extending out of bound")
  94. }
  95. ext := b.v[b.end:end]
  96. b.end = end
  97. return ext
  98. }
  99. // BytesRange returns a slice of this buffer with given from and to boundary.
  100. func (b *Buffer) BytesRange(from, to int32) []byte {
  101. if from < 0 {
  102. from += b.Len()
  103. }
  104. if to < 0 {
  105. to += b.Len()
  106. }
  107. return b.v[b.start+from : b.start+to]
  108. }
  109. // BytesFrom returns a slice of this Buffer starting from the given position.
  110. func (b *Buffer) BytesFrom(from int32) []byte {
  111. if from < 0 {
  112. from += b.Len()
  113. }
  114. return b.v[b.start+from : b.end]
  115. }
  116. // BytesTo returns a slice of this Buffer from start to the given position.
  117. func (b *Buffer) BytesTo(to int32) []byte {
  118. if to < 0 {
  119. to += b.Len()
  120. }
  121. return b.v[b.start : b.start+to]
  122. }
  123. // Resize cuts the buffer at the given position.
  124. func (b *Buffer) Resize(from, to int32) {
  125. if from < 0 {
  126. from += b.Len()
  127. }
  128. if to < 0 {
  129. to += b.Len()
  130. }
  131. if to < from {
  132. panic("Invalid slice")
  133. }
  134. b.end = b.start + to
  135. b.start += from
  136. }
  137. // Advance cuts the buffer at the given position.
  138. func (b *Buffer) Advance(from int32) {
  139. if from < 0 {
  140. from += b.Len()
  141. }
  142. b.start += from
  143. }
  144. // Len returns the length of the buffer content.
  145. func (b *Buffer) Len() int32 {
  146. if b == nil {
  147. return 0
  148. }
  149. return b.end - b.start
  150. }
  151. // Cap returns the capacity of the buffer content.
  152. func (b *Buffer) Cap() int32 {
  153. if b == nil {
  154. return 0
  155. }
  156. return int32(len(b.v))
  157. }
  158. // IsEmpty returns true if the buffer is empty.
  159. func (b *Buffer) IsEmpty() bool {
  160. return b.Len() == 0
  161. }
  162. // IsFull returns true if the buffer has no more room to grow.
  163. func (b *Buffer) IsFull() bool {
  164. return b != nil && b.end == int32(len(b.v))
  165. }
  166. // Write implements Write method in io.Writer.
  167. func (b *Buffer) Write(data []byte) (int, error) {
  168. nBytes := copy(b.v[b.end:], data)
  169. b.end += int32(nBytes)
  170. return nBytes, nil
  171. }
  172. // WriteByte writes a single byte into the buffer.
  173. func (b *Buffer) WriteByte(v byte) error {
  174. if b.IsFull() {
  175. return newError("buffer full")
  176. }
  177. b.v[b.end] = v
  178. b.end++
  179. return nil
  180. }
  181. // WriteString implements io.StringWriter.
  182. func (b *Buffer) WriteString(s string) (int, error) {
  183. return b.Write([]byte(s))
  184. }
  185. // ReadByte implements io.ByteReader
  186. func (b *Buffer) ReadByte() (byte, error) {
  187. if b.start == b.end {
  188. return 0, io.EOF
  189. }
  190. nb := b.v[b.start]
  191. b.start++
  192. return nb, nil
  193. }
  194. // ReadBytes implements bufio.Reader.ReadBytes
  195. func (b *Buffer) ReadBytes(length int32) ([]byte, error) {
  196. if b.end-b.start < length {
  197. return nil, io.EOF
  198. }
  199. nb := b.v[b.start : b.start+length]
  200. b.start += length
  201. return nb, nil
  202. }
  203. // Read implements io.Reader.Read().
  204. func (b *Buffer) Read(data []byte) (int, error) {
  205. if b.Len() == 0 {
  206. return 0, io.EOF
  207. }
  208. nBytes := copy(data, b.v[b.start:b.end])
  209. if int32(nBytes) == b.Len() {
  210. b.Clear()
  211. } else {
  212. b.start += int32(nBytes)
  213. }
  214. return nBytes, nil
  215. }
  216. // ReadFrom implements io.ReaderFrom.
  217. func (b *Buffer) ReadFrom(reader io.Reader) (int64, error) {
  218. n, err := reader.Read(b.v[b.end:])
  219. b.end += int32(n)
  220. return int64(n), err
  221. }
  222. // ReadFullFrom reads exact size of bytes from given reader, or until error occurs.
  223. func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, error) {
  224. end := b.end + size
  225. if end > int32(len(b.v)) {
  226. v := end
  227. return 0, newError("out of bound: ", v)
  228. }
  229. n, err := io.ReadFull(reader, b.v[b.end:end])
  230. b.end += int32(n)
  231. return int64(n), err
  232. }
  233. // String returns the string form of this Buffer.
  234. func (b *Buffer) String() string {
  235. return string(b.Bytes())
  236. }