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
|
package byteutil
import (
"errors"
"io"
"unicode/utf8"
)
var (
// ensure we conform to interfaces.
_ interface {
io.Writer
io.ByteWriter
WriteRune(rune) (int, error)
io.StringWriter
io.WriterAt
WriteStringAt(string, int64) (int, error)
} = (*Buffer)(nil)
// ErrBeyondBufferLen is returned if .WriteAt() is attempted beyond buffer length.
ErrBeyondBufferLen = errors.New("start beyond buffer length")
)
// Buffer is a simple wrapper around a byte slice.
type Buffer struct{ B []byte }
// WriteByte will append given byte to buffer, fulfilling io.ByteWriter.
func (buf *Buffer) WriteByte(c byte) error {
buf.B = append(buf.B, c)
return nil
}
// WriteRune will append given rune to buffer.
func (buf *Buffer) WriteRune(r rune) (int, error) {
// Check for single-byte rune
if r < utf8.RuneSelf {
buf.B = append(buf.B, byte(r))
return 1, nil
}
// Before-len
l := len(buf.B)
// Grow to max size rune
buf.Grow(utf8.UTFMax)
// Write encoded rune to buffer
n := utf8.EncodeRune(buf.B[l:len(buf.B)], r)
buf.B = buf.B[:l+n]
return n, nil
}
// Write will append given byte slice to buffer, fulfilling io.Writer.
func (buf *Buffer) Write(b []byte) (int, error) {
buf.B = append(buf.B, b...)
return len(b), nil
}
// WriteString will append given string to buffer, fulfilling io.StringWriter.
func (buf *Buffer) WriteString(s string) (int, error) {
buf.B = append(buf.B, s...)
return len(s), nil
}
// WriteAt will append given byte slice to buffer at index 'start', fulfilling io.WriterAt.
func (buf *Buffer) WriteAt(b []byte, start int64) (int, error) {
if start > int64(len(buf.B)) {
return 0, ErrBeyondBufferLen
}
buf.Grow(len(b) - int(int64(len(buf.B))-start))
return copy(buf.B[start:], b), nil
}
// WriteStringAt will append given string to buffer at index 'start'.
func (buf *Buffer) WriteStringAt(s string, start int64) (int, error) {
if start > int64(len(buf.B)) {
return 0, ErrBeyondBufferLen
}
buf.Grow(len(s) - int(int64(len(buf.B))-start))
return copy(buf.B[start:], s), nil
}
// Len returns the length of the buffer's underlying byte slice.
func (buf *Buffer) Len() int {
return len(buf.B)
}
// Cap returns the capacity of the buffer's underlying byte slice.
func (buf *Buffer) Cap() int {
return cap(buf.B)
}
// Grow will increase the buffers length by 'sz', and the capacity by at least this.
func (buf *Buffer) Grow(sz int) {
buf.Guarantee(sz)
buf.B = buf.B[:len(buf.B)+sz]
}
// Guarantee will guarantee buffer containers at least 'sz' remaining capacity.
func (buf *Buffer) Guarantee(sz int) {
if sz > cap(buf.B)-len(buf.B) {
nb := make([]byte, 2*cap(buf.B)+sz)
copy(nb, buf.B)
buf.B = nb[:len(buf.B)]
}
}
// Truncate will reduce the length of the buffer by 'n'.
func (buf *Buffer) Truncate(n int) {
if n > len(buf.B) {
n = len(buf.B)
}
buf.B = buf.B[:len(buf.B)-n]
}
// Reset will reset the buffer length to 0 (retains capacity).
func (buf *Buffer) Reset() {
buf.B = buf.B[:0]
}
// String returns the underlying byte slice as a string. Please note
// this value is tied directly to the underlying byte slice, if you
// write to the buffer then returned string values will also change.
//
// To get an immutable string from buffered data, use string(buf.B).
func (buf *Buffer) String() string {
return B2S(buf.B)
}
// Full returns the full capacity byteslice allocated for this buffer.
func (buf *Buffer) Full() []byte {
return buf.B[0:cap(buf.B)]
}
|