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  }