buffer.go raw

   1  // Copyright 2022 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package buffer provides a pool-allocated byte buffer.
   6  package buffer
   7  
   8  import (
   9  	"sync"
  10  )
  11  
  12  // Buffer adapted from go/src/fmt/print.go
  13  type Buffer []byte
  14  
  15  // Having an initial size gives a dramatic speedup.
  16  var bufPool = sync.Pool{
  17  	New: func() any {
  18  		b := make([]byte, 0, 1024)
  19  		return (*Buffer)(&b)
  20  	},
  21  }
  22  
  23  func New() *Buffer {
  24  	return bufPool.Get().(*Buffer)
  25  }
  26  
  27  func (b *Buffer) Free() {
  28  	// To reduce peak allocation, return only smaller buffers to the pool.
  29  	const maxBufferSize = 16 << 10
  30  	if cap(*b) <= maxBufferSize {
  31  		*b = (*b)[:0]
  32  		bufPool.Put(b)
  33  	}
  34  }
  35  
  36  func (b *Buffer) Reset() {
  37  	*b = (*b)[:0]
  38  }
  39  
  40  func (b *Buffer) Write(p []byte) (int, error) {
  41  	*b = append(*b, p...)
  42  	return len(p), nil
  43  }
  44  
  45  func (b *Buffer) WriteString(s string) {
  46  	*b = append(*b, s...)
  47  }
  48  
  49  func (b *Buffer) WriteByte(c byte) {
  50  	*b = append(*b, c)
  51  }
  52  
  53  func (b *Buffer) WritePosInt(i int) {
  54  	b.WritePosIntWidth(i, 0)
  55  }
  56  
  57  // WritePosIntWidth writes non-negative integer i to the buffer, padded on the left
  58  // by zeroes to the given width. Use a width of 0 to omit padding.
  59  func (b *Buffer) WritePosIntWidth(i, width int) {
  60  	// Cheap integer to fixed-width decimal ASCII.
  61  	// Copied from log/log.go.
  62  
  63  	if i < 0 {
  64  		panic("negative int")
  65  	}
  66  
  67  	// Assemble decimal in reverse order.
  68  	var bb [20]byte
  69  	bp := len(bb) - 1
  70  	for i >= 10 || width > 1 {
  71  		width--
  72  		q := i / 10
  73  		bb[bp] = byte('0' + i - q*10)
  74  		bp--
  75  		i = q
  76  	}
  77  	// i < 10
  78  	bb[bp] = byte('0' + i)
  79  	b.Write(bb[bp:])
  80  }
  81  
  82  func (b *Buffer) String() string {
  83  	return string(*b)
  84  }
  85