github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/perf/bbp/buffer.go (about) 1 package bbp 2 3 import ( 4 "io" 5 "unicode/utf8" 6 7 "github.com/jxskiss/gopkg/v2/internal/unsafeheader" 8 ) 9 10 // MinRead is the minimum slice size passed to a Read call by Buffer.ReadFrom. 11 const MinRead = 512 12 13 // NewBuffer creates a new Buffer with specified capacity. 14 // When you finish the work with the buffer, you may call PutBuffer 15 // to put it back to the pool for reusing. 16 func NewBuffer(capacity int) *Buffer { 17 return &Buffer{buf: Get(0, capacity)} 18 } 19 20 // PutBuffer puts back a Buffer to the pool for reusing. 21 // 22 // The buffer mustn't be touched after returning it to the pool, 23 // otherwise data races will occur. 24 func PutBuffer(buf *Buffer) { 25 put(buf.buf) 26 } 27 28 // Buffer provides byte buffer, which can be used for minimizing 29 // memory allocations. 30 // 31 // Buffer may be used with functions appending data to the underlying 32 // []byte slice. See example code for details. 33 // 34 // Use NewBuffer for obtaining a buffer with specified capacity. 35 // The zero value for Buffer is an empty buffer ready to use. 36 type Buffer struct { 37 buf []byte 38 } 39 40 // Len returns the size of the byte buffer. 41 func (b *Buffer) Len() int { 42 return len(b.buf) 43 } 44 45 // Grow grows the buffer's capacity, if necessary, to guarantee space for 46 // another n bytes. After Grow(n), at least n bytes can be written to the 47 // buffer without another allocation. 48 // If n is negative, Grow will panic. 49 func (b *Buffer) Grow(n int) { 50 if n < 0 { 51 panic("bbp.Buffer.Grow: negative size to grow") 52 } 53 if newCap := len(b.buf) + n; newCap > cap(b.buf) { 54 b.buf = grow(b.buf, newCap, true) 55 } 56 } 57 58 // Append accepts a function which append data to the underlying byte slice. 59 func (b *Buffer) Append(f func([]byte) []byte) { 60 b.buf = f(b.buf) 61 } 62 63 // ReadFrom implements io.ReaderFrom. 64 // 65 // The function appends all the data read from r to b. 66 func (b *Buffer) ReadFrom(r io.Reader) (int64, error) { 67 p := b.buf 68 nStart := len(p) 69 nMax := cap(p) 70 n := nStart 71 if nMax == 0 || nMax == minBufSize { 72 nMax = MinRead 73 p = get(nMax, nMax) 74 } else { 75 p = p[:nMax] 76 } 77 for { 78 if n == nMax { 79 nMax *= 2 80 p = grow(p, nMax, true) 81 p = p[:nMax] 82 } 83 nn, err := r.Read(p[n:]) 84 n += nn 85 if err != nil { 86 b.buf = p[:n] 87 n -= nStart 88 if err == io.EOF { 89 return int64(n), nil 90 } 91 return int64(n), err 92 } 93 } 94 } 95 96 // WriteTo implements io.WriterTo. 97 func (b *Buffer) WriteTo(w io.Writer) (int64, error) { 98 n, err := w.Write(b.buf) 99 return int64(n), err 100 } 101 102 // Write implements io.Writer - it appends p to the underlying byte buffer. 103 func (b *Buffer) Write(p []byte) (int, error) { 104 b.buf = append(b.buf, p...) 105 return len(p), nil 106 } 107 108 // WriteByte appends the byte c to the buffer. 109 // The purpose of this function is bytes.Buffer compatibility. 110 func (b *Buffer) WriteByte(c byte) error { 111 b.buf = append(b.buf, c) 112 return nil 113 } 114 115 // WriteRune appends the UTF-8 encoding of Unicode code point r to the buffer. 116 // The purpose of this function is bytes.Buffer compatibility. 117 func (b *Buffer) WriteRune(r rune) (n int, err error) { 118 oldLen := len(b.buf) 119 b.buf = utf8.AppendRune(b.buf, r) 120 return len(b.buf) - oldLen, nil 121 } 122 123 // WriteString appends s to the underlying byte slice. 124 func (b *Buffer) WriteString(s string) (int, error) { 125 b.buf = append(b.buf, s...) 126 return len(s), nil 127 } 128 129 // WriteStrings appends a slice of strings to the underlying byte slice. 130 func (b *Buffer) WriteStrings(s []string) (int, error) { 131 lenb := len(b.buf) 132 lens := 0 133 for i := 0; i < len(s); i++ { 134 lens += len(s[i]) 135 } 136 want := lenb + lens 137 if want > cap(b.buf) { 138 b.buf = grow(b.buf, want, true) 139 } 140 b.buf = b.buf[:want] 141 for _, x := range s { 142 lenb += copy(b.buf[lenb:], x) 143 } 144 return lens, nil 145 } 146 147 // Set first re-slice the underlying byte slice to empty, 148 // then write p to the buffer. 149 func (b *Buffer) Set(p []byte) { 150 b.buf = append(b.buf[:0], p...) 151 } 152 153 // SetString first re-slice the underlying byte slice to empty, 154 // then write s to the buffer. 155 func (b *Buffer) SetString(s string) { 156 b.buf = append(b.buf[:0], s...) 157 } 158 159 // Reset re-slice the underlying byte slice to empty. 160 func (b *Buffer) Reset() { 161 b.buf = b.buf[:0] 162 } 163 164 // Clone returns a new copy of the buffer, including the underlying 165 // byte slice. 166 func (b *Buffer) Clone() *Buffer { 167 cp := &Buffer{ 168 buf: make([]byte, len(b.buf), cap(b.buf)), 169 } 170 copy(cp.buf, b.buf) 171 return cp 172 } 173 174 // Bytes returns the underlying byte slice, i.e. all the bytes accumulated 175 // in the buffer. 176 // 177 // Note that this method doesn't copy the underlying byte slice, the caller 178 // should either copy the byte slice explicitly or don't return the Buffer 179 // back to the pool, otherwise data race will occur. 180 // You may use Buffer.Copy to get a copy of the underlying byte slice. 181 func (b *Buffer) Bytes() []byte { 182 return b.buf 183 } 184 185 // Copy returns a copy of the underlying byte slice. 186 func (b *Buffer) Copy() []byte { 187 buf := make([]byte, len(b.buf)) 188 copy(buf, b.buf) 189 return buf 190 } 191 192 // String returns a string copy of the underlying byte slice. 193 func (b *Buffer) String() string { 194 return string(b.buf) 195 } 196 197 // StringUnsafe is equivalent to String, but the string that it returns 198 // is _NOT_ copied, so modifying this buffer after calling StringUnsafe 199 // will lead to undefined behavior. 200 func (b *Buffer) StringUnsafe() string { 201 return unsafeheader.BytesToString(b.buf) 202 }