-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathwriter.go
127 lines (114 loc) · 2.6 KB
/
writer.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
package bufit
import "io"
type writer struct {
empty bool
off, roff int
data []byte
}
// NewMemoryWriter returns a new Writer for use with NewBuffer that internally
// stores bytes in a []byte. The given []byte will be the initial buffer used.
// It's a good idea to preallocate the normal size of your buffer here.
// ex. NewMemoryWriter(make([]byte, 0, CAPACITY)) where CAPACITY is large
// enough for Keep() + the number of buffered Write chunks
// you expect to need to hold in the buffer at any given time.
// This saves swapping the internal buffer out for a larger one as capacity
// needs grow, this means less large locking copies of the internal buffer.
func NewMemoryWriter(p []byte) Writer {
return newWriter(p)
}
func newWriter(p []byte) *writer {
return &writer{
empty: len(p) == 0,
off: len(p),
data: p[0:cap(p)],
}
}
func split(a, b int, p []byte) (as, bs []byte) {
if a < b {
return p[a:b], nil
}
return p[a:], p[0:b]
}
func (buf *writer) Len() int {
if buf.empty {
return 0
} else if buf.roff < buf.off {
return buf.off - buf.roff
} else {
return len(buf.data) - buf.roff + buf.off
}
}
func (buf *writer) Cap() int {
return cap(buf.data)
}
func (buf *writer) grow(s int) *writer {
c, l := buf.Cap(), buf.Len()
if c-l >= s {
return buf
}
next := newWriter(make([]byte, 0, c*2+s))
if !buf.empty {
a, b := split(buf.roff, buf.off, buf.data)
next.Write(a)
next.Write(b)
}
return next
}
// no bounds check, expected.
func (buf *writer) Discard(s int) (n int, err error) {
if s > 0 {
buf.roff = (buf.roff + s) % cap(buf.data)
if buf.roff == buf.off {
err = io.EOF
buf.empty = true
}
}
return s, err
}
func (buf *writer) Write(p []byte) (n int, err error) {
*buf = *buf.grow(len(p))
a, b := split(buf.off, buf.roff, buf.data)
n = copy(a, p)
if n < len(p) {
n += copy(b, p[n:])
}
if n > 0 {
buf.empty = false
}
buf.off = (buf.off + n) % cap(buf.data)
return n, err
}
func (buf *writer) Read(p []byte) (n int, err error) {
if buf.empty {
return 0, io.EOF
}
a, b := split(buf.roff, buf.off, buf.data)
n = copy(p, a)
if n < len(p) {
n += copy(p[n:], b)
}
return buf.Discard(n)
}
func (buf *writer) ReadAt(p []byte, off int64) (n int, err error) {
if buf.empty {
return 0, io.EOF
}
a, b := split(buf.roff, buf.off, buf.data)
if int64(len(a)) > off {
a = a[off:]
} else if int64(len(b)) > off-int64(len(a)) {
b = b[off-int64(len(a)):]
a = nil
} else {
return 0, io.EOF
}
n = copy(p, a)
if n < len(p) {
n += copy(p[n:], b)
}
if n < len(p) {
err = io.EOF
}
return n, err
}
func (buf writer) NextReader() Reader { return &buf }