123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // Copyright 2016 The Internal Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Package buffer implements a pool of pointers to byte slices.
- //
- // Example usage pattern
- //
- // p := buffer.Get(size)
- // b := *p // Now you can use b in any way you need.
- // ...
- // // When b will not be used anymore
- // buffer.Put(p)
- // ...
- // // If b or p are not going out of scope soon, optionally
- // b = nil
- // p = nil
- //
- // Otherwise the pool cannot release the buffer on garbage collection.
- //
- // Do not do
- //
- // p := buffer.Get(size)
- // b := *p
- // ...
- // buffer.Put(&b)
- //
- // or
- //
- // b := *buffer.Get(size)
- // ...
- // buffer.Put(&b)
- package buffer
- import (
- "github.com/cznic/internal/slice"
- "io"
- )
- // CGet returns a pointer to a byte slice of len size. The pointed to byte
- // slice is zeroed up to its cap. CGet panics for size < 0.
- //
- // CGet is safe for concurrent use by multiple goroutines.
- func CGet(size int) *[]byte { return slice.Bytes.CGet(size).(*[]byte) }
- // Get returns a pointer to a byte slice of len size. The pointed to byte slice
- // is not zeroed. Get panics for size < 0.
- //
- // Get is safe for concurrent use by multiple goroutines.
- func Get(size int) *[]byte { return slice.Bytes.Get(size).(*[]byte) }
- // Put puts a pointer to a byte slice into a pool for possible later reuse by
- // CGet or Get.
- //
- // Put is safe for concurrent use by multiple goroutines.
- func Put(p *[]byte) { slice.Bytes.Put(p) }
- // Bytes is similar to bytes.Buffer but may generate less garbage when properly
- // Closed. Zero value is ready to use.
- type Bytes struct {
- p *[]byte
- }
- // Bytes return the content of b. The result is R/O.
- func (b *Bytes) Bytes() []byte {
- if b.p != nil {
- return *b.p
- }
- return nil
- }
- // Close will recycle the underlying storage, if any. After Close, b is again
- // the zero value.
- func (b *Bytes) Close() error {
- if b.p != nil {
- Put(b.p)
- b.p = nil
- }
- return nil
- }
- // Len returns the size of content in b.
- func (b *Bytes) Len() int {
- if b.p != nil {
- return len(*b.p)
- }
- return 0
- }
- // Reset discard the content of Bytes while keeping the internal storage, if any.
- func (b *Bytes) Reset() {
- if b.p != nil {
- *b.p = (*b.p)[:0]
- }
- }
- // Write writes p into b and returns (len(p), nil).
- func (b *Bytes) Write(p []byte) (int, error) {
- n := b.Len()
- b.grow(n + len(p))
- copy((*b.p)[n:], p)
- return len(p), nil
- }
- // WriteByte writes p into b and returns nil.
- func (b *Bytes) WriteByte(p byte) error {
- n := b.Len()
- b.grow(n + 1)
- (*b.p)[n] = p
- return nil
- }
- // WriteTo writes b's content to w and returns the number of bytes written to w
- // and an error, if any.
- func (b *Bytes) WriteTo(w io.Writer) (int64, error) {
- n, err := w.Write(b.Bytes())
- return int64(n), err
- }
- // WriteString writes s to b and returns (len(s), nil).
- func (b *Bytes) WriteString(s string) (int, error) {
- n := b.Len()
- b.grow(n + len(s))
- copy((*b.p)[n:], s)
- return len(s), nil
- }
- func (b *Bytes) grow(n int) {
- if b.p != nil {
- if n <= cap(*b.p) {
- *b.p = (*b.p)[:n]
- return
- }
- np := Get(2 * n)
- *np = (*np)[:n]
- copy(*np, *b.p)
- Put(b.p)
- b.p = np
- return
- }
- b.p = Get(n)
- }
|