authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-11-11 02:49:35+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-18 16:47:03-05:00
logbdff2f43bdc112cb02e36678d079e82fd5a96605
treecbf338c2adff746e572e8479306d5e3dd6440b61
parent662996e4a8826f62f76bdafdb7ccbb1d52210c96
signaturelock-open Commit is signed but in an unrecognized format.

std: use LinearFifo to implement io.BufferedInStreamCustom


1 files changed, 14 insertions(+), 53 deletions(-)

lib/std/io.zig+14-53
......@@ -121,76 +121,37 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
121121
122122 unbuffered_in_stream: *Stream,
123123
124 buffer: [buffer_size]u8,
125 start_index: usize,
126 end_index: usize,
124 const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
125 fifo: FifoType,
127126
128127 pub fn init(unbuffered_in_stream: *Stream) Self {
129128 return Self{
130129 .unbuffered_in_stream = unbuffered_in_stream,
131 .buffer = undefined,
132
133 // Initialize these two fields to buffer_size so that
134 // in `readFn` we treat the state as being able to read
135 // more from the unbuffered stream. If we set them to 0
136 // and 0, the code would think we already hit EOF.
137 .start_index = buffer_size,
138 .end_index = buffer_size,
139
130 .fifo = FifoType.init(),
140131 .stream = Stream{ .readFn = readFn },
141132 };
142133 }
143134
144135 fn readFn(in_stream: *Stream, dest: []u8) !usize {
145136 const self = @fieldParentPtr(Self, "stream", in_stream);
146
147 // Hot path for one byte reads
148 if (dest.len == 1 and self.end_index > self.start_index) {
149 dest[0] = self.buffer[self.start_index];
150 self.start_index += 1;
151 return 1;
152 }
153
154137 var dest_index: usize = 0;
155 while (true) {
156 const dest_space = dest.len - dest_index;
157 if (dest_space == 0) {
158 return dest_index;
159 }
160 const amt_buffered = self.end_index - self.start_index;
161 if (amt_buffered == 0) {
162 assert(self.end_index <= buffer_size);
163 // Make sure the last read actually gave us some data
164 if (self.end_index == 0) {
138 while (dest_index < dest.len) {
139 const written = self.fifo.read(dest[dest_index..]);
140 if (written == 0) {
141 // fifo empty, fill it
142 const writable = self.fifo.writableSlice(0);
143 assert(writable.len > 0);
144 const n = try self.unbuffered_in_stream.read(writable);
145 if (n == 0) {
165146 // reading from the unbuffered stream returned nothing
166147 // so we have nothing left to read.
167148 return dest_index;
168149 }
169 // we can read more data from the unbuffered stream
170 if (dest_space < buffer_size) {
171 self.start_index = 0;
172 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
173
174 // Shortcut
175 if (self.end_index >= dest_space) {
176 mem.copy(u8, dest[dest_index..], self.buffer[0..dest_space]);
177 self.start_index = dest_space;
178 return dest.len;
179 }
180 } else {
181 // asking for so much data that buffering is actually less efficient.
182 // forward the request directly to the unbuffered stream
183 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
184 return dest_index + amt_read;
185 }
150 self.fifo.update(n);
186151 }
187
188 const copy_amount = math.min(dest_space, amt_buffered);
189 const copy_end_index = self.start_index + copy_amount;
190 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
191 self.start_index = copy_end_index;
192 dest_index += copy_amount;
152 dest_index += written;
193153 }
154 return dest.len;
194155 }
195156 };
196157}