// This is a derivitive work of Go's bytes.Buffer implementation.//// Originally copyright 2009 The Go Authors. All rights reserved.//// Modifications copyright 2018 Steven Allen. All rights reserved.//// Use of this source code is governed by both a BSD-style and an MIT-style// license that can be found in the LICENSE_BSD and LICENSE files.package poolimport ()// Buffer is a buffer like bytes.Buffer that://// 1. Uses a buffer pool.// 2. Frees memory on read.//// If you only have a few buffers and read/write at a steady rate, *don't* use// this package, it'll be slower.//// However://// 1. If you frequently create/destroy buffers, this implementation will be// significantly nicer to the allocator.// 2. If you have many buffers with bursty traffic, this implementation will use// significantly less memory.typeBufferstruct {// Pool is the buffer pool to use. If nil, this Buffer will use the // global buffer pool. Pool *BufferPool buf []byte rOff int// Preallocated slice for samll reads/writes. // This is *really* important for performance and only costs 8 words. bootstrap [64]byte}// NewBuffer constructs a new buffer initialized to `buf`.// Unlike `bytes.Buffer`, we *copy* the buffer but don't reuse it (to ensure// that we *only* use buffers from the pool).func ( []byte) *Buffer { := new(Buffer)iflen() > 0 { .buf = .getBuf(len())copy(.buf, ) }return}// NewBufferString is identical to NewBuffer *except* that it allows one to// initialize the buffer from a string (without having to allocate an// intermediate bytes slice).func ( string) *Buffer { := new(Buffer)iflen() > 0 { .buf = .getBuf(len())copy(.buf, ) }return}func ( *Buffer) ( int) int { := len(.buf) := cap(.buf)if >= + { .buf = .buf[:+]return } := .Len() := 2* + // Slide if cap >= minCap. // Reallocate otherwise.if >= {copy(.buf, .buf[.rOff:]) } else {// Needs new buffer. := .getBuf()copy(, .buf[.rOff:]) .returnBuf() .buf = } .rOff = 0 .buf = .buf[:+]return}func ( *Buffer) () *BufferPool {if .Pool == nil {returnGlobalPool }return .Pool}func ( *Buffer) () {ifcap(.buf) > len(.bootstrap) { .getPool().Put(.buf) } .buf = nil}func ( *Buffer) ( int) []byte {if <= len(.bootstrap) {return .bootstrap[:] }return .getPool().Get()}// Len returns the number of bytes that can be read from this buffer.func ( *Buffer) () int {returnlen(.buf) - .rOff}// Cap returns the current capacity of the buffer.//// Note: Buffer *may* re-allocate when writing (or growing by) `n` bytes even if// `Cap() < Len() + n` to avoid excessive copying.func ( *Buffer) () int {returncap(.buf)}// Bytes returns the slice of bytes currently buffered in the Buffer.//// The buffer returned by Bytes is valid until the next call grow, truncate,// read, or write. Really, just don't touch the Buffer until you're done with// the return value of this function.func ( *Buffer) () []byte {return .buf[.rOff:]}// String returns the string representation of the buffer.//// It returns `<nil>` the buffer is a nil pointer.func ( *Buffer) () string {if == nil {return"<nil>" }returnstring(.buf[.rOff:])}// WriteString writes a string to the buffer.//// This function is identical to Write except that it allows one to write a// string directly without allocating an intermediate byte slice.func ( *Buffer) ( string) (int, error) { := .grow(len())returncopy(.buf[:], ), nil}// Truncate truncates the Buffer.//// Panics if `n > b.Len()`.//// This function may free memory by shrinking the internal buffer.func ( *Buffer) ( int) {if < 0 || > .Len() {panic("truncation out of range") } .buf = .buf[:.rOff+] .shrink()}// Reset is equivalent to Truncate(0).func ( *Buffer) () { .returnBuf() .rOff = 0}// ReadByte reads a single byte from the Buffer.func ( *Buffer) () (byte, error) {if .rOff >= len(.buf) {return0, io.EOF } := .buf[.rOff] .rOff++return , nil}// WriteByte writes a single byte to the Buffer.func ( *Buffer) ( byte) error { := .grow(1) .buf[] = returnnil}// Grow grows the internal buffer such that `n` bytes can be written without// reallocating.func ( *Buffer) ( int) { := .grow() .buf = .buf[:]}// Next is an alternative to `Read` that returns a byte slice instead of taking// one.//// The returned byte slice is valid until the next read, write, grow, or// truncate.func ( *Buffer) ( int) []byte { := .Len()if < { = } := .buf[.rOff : .rOff+] .rOff += return}// Write writes the byte slice to the buffer.func ( *Buffer) ( []byte) (int, error) { := .grow(len())returncopy(.buf[:], ), nil}// WriteTo copies from the buffer into the given writer until the buffer is// empty.func ( *Buffer) ( io.Writer) (int64, error) {if .rOff < len(.buf) { , := .Write(.buf[.rOff:]) .rOff += if .rOff > len(.buf) {panic("invalid write count") } .shrink()returnint64(), }return0, nil}// MinRead is the minimum slice size passed to a Read call by// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond// what is required to hold the contents of r, ReadFrom will not grow the// underlying buffer.constMinRead = 512// ReadFrom reads from the given reader into the buffer.func ( *Buffer) ( io.Reader) (int64, error) { := int64(0)for { := .grow(MinRead)// Use *entire* buffer. .buf = .buf[:cap(.buf)] , := .Read(.buf[:]) .buf = .buf[:+] += int64()switch {casenil:caseio.EOF: = nilfallthroughdefault: .shrink()return , } }}// Read reads at most `len(buf)` bytes from the internal buffer into the given// buffer.func ( *Buffer) ( []byte) (int, error) {iflen() == 0 {return0, nil }if .rOff >= len(.buf) {return0, io.EOF } := copy(, .buf[.rOff:]) .rOff += .shrink()return , nil}func ( *Buffer) () { := .Cap()// Either nil or bootstrap.if <= len(.bootstrap) {return } := .Len()if == 0 {// Shortcut if empty. .returnBuf() .rOff = 0 } elseif *8 < {// Only shrink when capacity > 8x length. Avoids shrinking too aggressively. := .getBuf()copy(, .buf[.rOff:]) .returnBuf() .rOff = 0 .buf = [:] }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.