mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-12-05 01:52:46 +00:00
59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
|
package bytebuffer
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
// ByteBuffer is a wrapper around a slice to reduce memory allocation while handling blob of data.
|
||
|
type ByteBuffer struct {
|
||
|
blob []byte
|
||
|
}
|
||
|
|
||
|
// New creates a new ByteBuffer instance.
|
||
|
func New() *ByteBuffer {
|
||
|
entry := bufferPool.Get().(*ByteBuffer)
|
||
|
entry.blob = entry.blob[:0]
|
||
|
return entry
|
||
|
}
|
||
|
|
||
|
// Bytes returns the content buffer.
|
||
|
func (buffer *ByteBuffer) Bytes() []byte {
|
||
|
return buffer.blob
|
||
|
}
|
||
|
|
||
|
// String returns the content buffer.
|
||
|
func (buffer *ByteBuffer) String() string {
|
||
|
// Copied from strings.(*Builder).String
|
||
|
return *(*string)(unsafe.Pointer(&buffer.blob)) // nolint: gosec
|
||
|
}
|
||
|
|
||
|
// Concat appends given arguments to blob content
|
||
|
func (buffer *ByteBuffer) Concat(args ...string) {
|
||
|
for i := range args {
|
||
|
buffer.blob = append(buffer.blob, args[i]...)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Close recycles underlying resources of encoder.
|
||
|
func (buffer *ByteBuffer) Close() {
|
||
|
// Proper usage of a sync.Pool requires each entry to have approximately
|
||
|
// the same memory cost. To obtain this property when the stored type
|
||
|
// contains a variably-sized buffer, we add a hard limit on the maximum buffer
|
||
|
// to place back in the pool.
|
||
|
//
|
||
|
// See https://golang.org/issue/23199
|
||
|
if buffer != nil && cap(buffer.blob) < (1<<16) {
|
||
|
bufferPool.Put(buffer)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// A byte buffer pool to reduce memory allocation pressure.
|
||
|
var bufferPool = &sync.Pool{
|
||
|
New: func() interface{} {
|
||
|
return &ByteBuffer{
|
||
|
blob: make([]byte, 0, 1024),
|
||
|
}
|
||
|
},
|
||
|
}
|