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
|
// Handle the rest of the input
return write(input[count:])
}
return write
}
// Returns a reader that delegates calls to Read(...) while ensuring
// that the output buffer is never smaller than the required size
// and is downsized to a multiple of the required size if larger.
func SizedReader(reader io.Reader, size int) io.Reader {
var (
buffer []byte = make([]byte, size)
from, to int = 0, 0
)
return ReaderFunc(func(output []byte) (int, error) {
var (
count int
err error
)
start:
// Reply with the buffered data if there is any
if to-from > 0 {
count = copy(output, buffer[from:to])
// Advance the data in the buffer
from += count
// Check whether we have reached the end of the buffer
if to-from == 0 {
// Reset the buffer
from, to = 0, 0
return count, err
}
// Do not propagate an error until the buffer is exhausted
return count, nil
}
// Delegate if the buffer is empty and the destination buffer is large enough
if len(output) >= size {
return reader.Read(output[:(len(output)/size)*size])
}
// Perform a read into the buffer
count, err = reader.Read(buffer)
// Size the buffer down to the read data size
// and restart if we have successfully read some bytes
from, to = 0, count
if to-from > 0 {
goto start
}
// Returning on err/misbehaving noop reader
return 0, err
})
}
|
>
>
>
>
>
>
|
>
|
|
<
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
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
145
|
// Handle the rest of the input
return write(input[count:])
}
return write
}
type sizedReader struct {
reader io.Reader
buffer []byte
from, to, size int
}
// Returns a reader that delegates calls to Read(...) while ensuring
// that the output buffer is never smaller than the required size
// and is downsized to a multiple of the required size if larger.
func SizedReader(reader io.Reader, size int) io.Reader {
var sr sizedReader
sr.reader = reader
sr.buffer = make([]byte, size)
sr.size, sr.from, sr.to = size, 0, 0
return &sr
}
func (sr *sizedReader) Read(output []byte) (int, error) {
var (
count int
err error
)
start:
// Reply with the buffered data if there is any
if sr.to-sr.from > 0 {
count = copy(output, sr.buffer[sr.from:sr.to])
// Advance the data in the buffer
sr.from += count
// Check whether we have reached the end of the buffer
if sr.to-sr.from == 0 {
// Reset the buffer
sr.from, sr.to = 0, 0
return count, err
}
// Do not propagate an error until the buffer is exhausted
return count, nil
}
// Delegate if the buffer is empty and the destination buffer is large enough
if len(output) >= sr.size {
return sr.reader.Read(output[:(len(output)/sr.size)*sr.size])
}
// Perform a read into the buffer
count, err = sr.reader.Read(sr.buffer)
// Size the buffer down to the read data size
// and restart if we have successfully read some bytes
sr.from, sr.to = 0, count
if sr.to-sr.from > 0 {
goto start
}
// Returning on err/misbehaving noop reader
return 0, err
}
|