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)...@@ -121,76 +121,37 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
121121
122 unbuffered_in_stream: *Stream,122 unbuffered_in_stream: *Stream,
123123
124 buffer: [buffer_size]u8,124 const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
125 start_index: usize,125 fifo: FifoType,
126 end_index: usize,
127126
128 pub fn init(unbuffered_in_stream: *Stream) Self {127 pub fn init(unbuffered_in_stream: *Stream) Self {
129 return Self{128 return Self{
130 .unbuffered_in_stream = unbuffered_in_stream,129 .unbuffered_in_stream = unbuffered_in_stream,
131 .buffer = undefined,130 .fifo = FifoType.init(),
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
140 .stream = Stream{ .readFn = readFn },131 .stream = Stream{ .readFn = readFn },
141 };132 };
142 }133 }
143134
144 fn readFn(in_stream: *Stream, dest: []u8) !usize {135 fn readFn(in_stream: *Stream, dest: []u8) !usize {
145 const self = @fieldParentPtr(Self, "stream", in_stream);136 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
154 var dest_index: usize = 0;137 var dest_index: usize = 0;
155 while (true) {138 while (dest_index < dest.len) {
156 const dest_space = dest.len - dest_index;139 const written = self.fifo.read(dest[dest_index..]);
157 if (dest_space == 0) {140 if (written == 0) {
158 return dest_index;141 // fifo empty, fill it
159 }142 const writable = self.fifo.writableSlice(0);
160 const amt_buffered = self.end_index - self.start_index;143 assert(writable.len > 0);
161 if (amt_buffered == 0) {144 const n = try self.unbuffered_in_stream.read(writable);
162 assert(self.end_index <= buffer_size);145 if (n == 0) {
163 // Make sure the last read actually gave us some data
164 if (self.end_index == 0) {
165 // reading from the unbuffered stream returned nothing146 // reading from the unbuffered stream returned nothing
166 // so we have nothing left to read.147 // so we have nothing left to read.
167 return dest_index;148 return dest_index;
168 }149 }
169 // we can read more data from the unbuffered stream150 self.fifo.update(n);
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 }
186 }151 }
187152 dest_index += written;
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;
193 }153 }
154 return dest.len;
194 }155 }
195 };156 };
196}157}