authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-11-11 03:07:57+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-18 16:47:03-05:00
log38ad7daebb42d562946c092a59cfbbf94e75870a
tree7edcc066089eb6e06ba6d74ca06968f2fd470294
parentbdff2f43bdc112cb02e36678d079e82fd5a96605
signature Commit is signed but in an unrecognized format.

std: use LinearFifo to implement io.PeekStream


2 files changed, 17 insertions(+), 37 deletions(-)

lib/std/io.zig+13-33
......@@ -196,7 +196,7 @@ test "io.BufferedInStream" {
196196
197197/// Creates a stream which supports 'un-reading' data, so that it can be read again.
198198/// This makes look-ahead style parsing much easier.
199pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
199pub fn PeekStream(comptime buffer_type: usize, comptime InStreamError: type) type {
200200 return struct {
201201 const Self = @This();
202202 pub const Error = InStreamError;
......@@ -207,55 +207,35 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ
207207
208208 // Right now the look-ahead space is statically allocated, but a version with dynamic allocation
209209 // is not too difficult to derive from this.
210 buffer: [buffer_size]u8,
211 index: usize,
212 at_end: bool,
210 const FifoType = std.fifo.LinearFifo(u8, .{ .Static = buffer_size });
211 fifo: FifoType,
213212
214213 pub fn init(base: *Stream) Self {
215 return Self{
214 return .{
216215 .base = base,
217 .buffer = undefined,
218 .index = 0,
219 .at_end = false,
216 .fifo = FifoType.init(),
220217 .stream = Stream{ .readFn = readFn },
221218 };
222219 }
223220
224 pub fn putBackByte(self: *Self, byte: u8) void {
225 self.buffer[self.index] = byte;
226 self.index += 1;
221 pub fn putBackByte(self: *Self, byte: u8) !void {
222 try self.putBack(@ptrCast([*]const u8, &byte)[0..1]);
227223 }
228224
229 pub fn putBack(self: *Self, bytes: []const u8) void {
230 var pos = bytes.len;
231 while (pos != 0) {
232 pos -= 1;
233 self.putBackByte(bytes[pos]);
234 }
225 pub fn putBack(self: *Self, bytes: []const u8) !void {
226 try self.fifo.unget(bytes);
235227 }
236228
237229 fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
238230 const self = @fieldParentPtr(Self, "stream", in_stream);
239231
240232 // copy over anything putBack()'d
241 var pos: usize = 0;
242 while (pos < dest.len and self.index != 0) {
243 dest[pos] = self.buffer[self.index - 1];
244 self.index -= 1;
245 pos += 1;
246 }
247
248 if (pos == dest.len or self.at_end) {
249 return pos;
250 }
233 var dest_index = self.fifo.read(dest);
234 if (dest_index == dest.len) return dest_index;
251235
252236 // ask the backing stream for more
253 const left = dest.len - pos;
254 const read = try self.base.read(dest[pos..]);
255 assert(read <= left);
256
257 self.at_end = (read < left);
258 return pos + read;
237 dest_index += try self.base.read(dest[dest_index..]);
238 return dest_index;
259239 }
260240 };
261241}
lib/std/io/test.zig+4-4
......@@ -97,8 +97,8 @@ test "PeekStream" {
9797
9898 var dest: [4]u8 = undefined;
9999
100 ps.putBackByte(9);
101 ps.putBackByte(10);
100 try ps.putBackByte(9);
101 try ps.putBackByte(10);
102102
103103 var read = try ps.stream.read(dest[0..4]);
104104 expect(read == 4);
......@@ -114,8 +114,8 @@ test "PeekStream" {
114114 expect(read == 2);
115115 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
116116
117 ps.putBackByte(11);
118 ps.putBackByte(12);
117 try ps.putBackByte(11);
118 try ps.putBackByte(12);
119119
120120 read = try ps.stream.read(dest[0..4]);
121121 expect(read == 2);