forked from kisom/goutils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sbuf.go
144 lines (124 loc) · 3.08 KB
/
sbuf.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Package sbuf implements a byte buffer that can be wiped. The underlying
// byte slice is wiped on read before being declaimed, and when the
// buffer is closed, its storage is zeroised.
package sbuf
import "io"
func zero(in []byte, n int) {
if in == nil {
return
}
stop := n
if stop > len(in) || stop == 0 {
stop = len(in)
}
for i := 0; i < stop; i++ {
in[i] ^= in[i]
}
}
// A Buffer is a variable-sized buffer of bytes with Read and Write
// methods. The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
buf []byte
}
// NewBuffer creates a new buffer with the specified capacity.
func NewBuffer(n int) *Buffer {
return &Buffer{
buf: make([]byte, 0, n),
}
}
// NewBufferFrom creates a new buffer from the byte slice passed in. The
// original data will be wiped.
func NewBufferFrom(p []byte) *Buffer {
buf := NewBuffer(len(p))
buf.Write(p)
zero(p, len(p))
return buf
}
// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
// otherwise it is nil.
func (buf *Buffer) Read(p []byte) (int, error) {
if len(buf.buf) == 0 {
if len(p) == 0 {
return 0, nil
}
return 0, io.EOF
}
copyLength := len(p)
if copyLength > len(buf.buf) {
copyLength = len(buf.buf)
}
copy(p, buf.buf)
zero(buf.buf, len(p))
buf.buf = buf.buf[copyLength:]
return copyLength, nil
}
// ReadByte reads the next byte from the buffer. If the buffer has no
// data to return, err is io.EOF; otherwise it is nil.
func (buf *Buffer) ReadByte() (byte, error) {
if len(buf.buf) == 0 {
return 0, io.EOF
}
c := buf.buf[0]
buf.buf[0] = 0
buf.buf = buf.buf[1:]
return c, nil
}
func (buf *Buffer) grow(n int) {
tmp := make([]byte, len(buf.buf), len(buf.buf)+n)
copy(tmp, buf.buf)
zero(buf.buf, len(buf.buf))
buf.buf = tmp
}
// Write appends the contents of p to the buffer, growing the buffer
// as needed. The return value n is the length of p; err is always nil.
func (buf *Buffer) Write(p []byte) (int, error) {
r := len(buf.buf) + len(p)
if cap(buf.buf) < r {
l := r
for {
if l > r {
break
}
l *= 2
}
buf.grow(l - cap(buf.buf))
}
buf.buf = append(buf.buf, p...)
return len(p), nil
}
// WriteByte adds the byte c to the buffer, growing the buffer as needed.
func (buf *Buffer) WriteByte(c byte) error {
r := len(buf.buf) + 1
if cap(buf.buf) < r {
l := r * 2
buf.grow(l - cap(buf.buf))
}
buf.buf = append(buf.buf, c)
return nil
}
// Close destroys and zeroises the buffer. The buffer will be re-opened
// on the next write.
func (buf *Buffer) Close() {
zero(buf.buf, len(buf.buf))
buf.buf = nil
}
// Len returns the length of the buffer.
func (buf *Buffer) Len() int {
return len(buf.buf)
}
// Cap returns the capacity of the buffer.
func (buf *Buffer) Cap() int {
return cap(buf.buf)
}
// Bytes returns the bytes currently in the buffer, and closes itself.
func (buf *Buffer) Bytes() []byte {
if buf.buf == nil {
return nil
}
p := make([]byte, buf.Len())
buf.Read(p)
buf.Close()
return p
}