forked from morita-kuma/golog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriter_buffered.go
127 lines (102 loc) · 2.89 KB
/
writer_buffered.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 golog
import (
"io"
)
var defaultBufferedWriterSize = 4096
// bufferedWriter implements buffering for an io.bufferedWriter object.
// If an error occurs writing to a bufferedWriter, no more data will be
// accepted and all subsequent writes, and Flush, will return the error.
// After all data has been written, the client should call the
// Flush method to guarantee all data has been forwarded to
// the underlying io.bufferedWriter.
type bufferedWriter struct {
err error
buffer []byte
writer io.Writer
numberOfWrittenBytes int
}
type writerOption func(writer *bufferedWriter)
// NewWriterSize returns a new bufferedWriter whose buffer has at least the specified
// size. If the argument io.bufferedWriter is already a bufferedWriter with large enough
// size, it returns the underlying bufferedWriter.
func newBufferedWriter(writer io.Writer, writerOptions ...writerOption) *bufferedWriter {
if bufferedWriter, ok := writer.(*bufferedWriter); ok {
return bufferedWriter
}
bufferedWriter := &bufferedWriter{
buffer: make([]byte, defaultBufferedWriterSize),
writer: writer,
}
for _, option := range writerOptions {
option(bufferedWriter)
}
return bufferedWriter
}
func withBufferSize(size int) writerOption {
return func(writer *bufferedWriter) {
if size <= 0 {
writer.buffer = make([]byte, defaultBufferedWriterSize)
return
}
writer.buffer = make([]byte, size)
}
}
// Write writes the contents of p into the buffer.
// It returns the number of bytes written.
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (w *bufferedWriter) Write(data []byte) (n int, err error) {
if w.hasError() {
return n, w.err
}
if len(data) > w.capacity() {
n, w.err = w.writer.Write(data)
return
}
if len(data) > w.available() {
err = w.Flush()
n = copy(w.buffer[0:len(data)], data)
w.numberOfWrittenBytes += n
return
}
n = copy(w.buffer[w.buffered():], data)
w.numberOfWrittenBytes += n
return
}
// Flush writes any buffered data to the underlying io.Writer.
func (w *bufferedWriter) Flush() error {
if w.hasError() {
return w.err
}
if w.buffered() == 0 {
return nil
}
n, err := w.writer.Write(w.buffer[0:w.buffered()])
if n < w.buffered() && err == nil {
err = io.ErrShortWrite
}
if err != nil {
if n > 0 && n < w.buffered() {
copy(w.buffer[0:w.buffered()-n], w.buffer[n:w.buffered()])
}
w.numberOfWrittenBytes -= n
w.err = err
return err
}
w.numberOfWrittenBytes = 0
return nil
}
func (w *bufferedWriter) capacity() int {
return cap(w.buffer)
}
// buffered returns the number of bytes that have been written into the current buffer.
func (w *bufferedWriter) buffered() int {
return w.numberOfWrittenBytes
}
// available returns how many bytes are unused in the buffer.
func (w *bufferedWriter) available() int {
return w.capacity() - w.buffered()
}
func (w *bufferedWriter) hasError() bool {
return w.err != nil
}