-
Notifications
You must be signed in to change notification settings - Fork 32
/
buffer.go
84 lines (68 loc) · 2.09 KB
/
buffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package jingo
// buffer.go manages Buffer and its responsibilities.
// Its existence is justified by the performance increase gained
// over more general implementations and the fact that we allow
// these buffers to be pooled, which reduces our allocation
// profile quite significantly.
import (
"io"
"sync"
"unsafe"
)
// Buffer is used to pass on to the encoders Marshal methods.
type Buffer struct {
Bytes []byte
}
var _ io.Writer = &Buffer{} // commit to compatibility with io.Writer
// Write a chunk of bytes to the buffer
func (b *Buffer) Write(v []byte) (int, error) {
b.Bytes = append(b.Bytes, v...)
return len(v), nil
}
// WriteString writes a string to the buffer
func (b *Buffer) WriteString(v string) {
b.Bytes = append(b.Bytes, v...)
}
// WriteByte writes a single byte into the output buffer
func (b *Buffer) WriteByte(v byte) error {
b.Bytes = append(b.Bytes, v)
return nil
}
// Reset allows this to be reused by emptying
func (b *Buffer) Reset() {
b.Bytes = b.Bytes[:0]
}
func (b *Buffer) String() string {
return *(*string)(unsafe.Pointer(&b.Bytes))
}
// WriteTo writes the contents of our buffer to an io.Writer
func (b *Buffer) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(b.Bytes)
return int64(n), err
}
var bufpool = sync.Pool{
New: func() interface{} { return &Buffer{} },
}
// NewBufferFromPool returns a pointer to a zerod Buffer. This may be retrieved from a
// pool. When you're done with it, call 'ReturnToPool'.
func NewBufferFromPool() *Buffer {
b := bufpool.Get().(*Buffer)
b.Reset()
return b
}
// NewBufferFromPoolWithCap returns a pointer to a zero'd Buffer with its underlying
// capacity set. This may be retrieved from a pool. When you're done with it, call 'ReturnToPool'.
func NewBufferFromPoolWithCap(size int) *Buffer {
b := bufpool.Get().(*Buffer)
if c := cap(b.Bytes); c < size {
b.Bytes = make([]byte, 0, size)
} else if c > 0 {
b.Reset()
}
return b
}
// ReturnToPool puts this instance back in the underlying pool. Reading from or using this instance
// in any way after calling this is invalid.
func (b *Buffer) ReturnToPool() {
bufpool.Put(b)
}