From a1abbb8eac4c73d1235a03579ee228ed48b56f9f Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 27 Sep 2020 14:43:44 +1000 Subject: [PATCH 1/4] std: add LinearFifo(...).pump(src_reader, dest_writer) --- lib/std/fifo.zig | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig index c92da615f9..0cc8be030e 100644 --- a/lib/std/fifo.zig +++ b/lib/std/fifo.zig @@ -373,6 +373,25 @@ pub fn LinearFifo( } return self.buf[index]; } + + /// Pump data from a reader into a writer + /// stops when reader returns 0 bytes (EOF) + /// Buffer size must be set before calling; a buffer length of 0 is invalid. + pub fn pump(self: *Self, src_reader: anytype, dest_writer: anytype) !void { + assert(self.buf.len > 0); + while (true) { + if (self.writableLength() > 0) { + const n = try src_reader.read(self.writableSlice(0)); + if (n == 0) break; // EOF + self.update(n); + } + self.discard(try dest_writer.write(self.readableSlice(0))); + } + // flush remaining data + while (self.readableLength() > 0) { + self.discard(try dest_writer.write(self.readableSlice(0))); + } + } }; } @@ -451,6 +470,15 @@ test "LinearFifo(u8, .Dynamic)" { testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?); testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?); } + + { + try fifo.ensureCapacity(1); + var in_fbs = std.io.fixedBufferStream("pump test"); + var out_buf: [50]u8 = undefined; + var out_fbs = std.io.fixedBufferStream(&out_buf); + try fifo.pump(in_fbs.reader(), out_fbs.writer()); + testing.expectEqualSlices(u8, in_fbs.buffer, out_fbs.getWritten()); + } } test "LinearFifo" { From ed5c778c103ceba5f0121d441598e160a5af643e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 27 Sep 2020 15:00:41 +1000 Subject: [PATCH 2/4] test/standalone/cat: update to new std library --- test/standalone/cat/main.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/standalone/cat/main.zig b/test/standalone/cat/main.zig index 8539a0de0f..6678cfd1ab 100644 --- a/test/standalone/cat/main.zig +++ b/test/standalone/cat/main.zig @@ -3,10 +3,14 @@ const io = std.io; const process = std.process; const fs = std.fs; const mem = std.mem; -const warn = std.debug.warn; -const allocator = std.testing.allocator; +const warn = std.log.warn; + +var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; +const allocator = &general_purpose_allocator.allocator; pub fn main() !void { + defer _ = general_purpose_allocator.deinit(); + var args_it = process.args(); const exe = try unwrapArg(args_it.next(allocator).?); var catted_anything = false; From cffab89730eb6f4183e2628d8b0d007df809436a Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 27 Sep 2020 15:06:27 +1000 Subject: [PATCH 3/4] test/standalone/cat: fix leaks --- test/standalone/cat/main.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/standalone/cat/main.zig b/test/standalone/cat/main.zig index 6678cfd1ab..58b87f76f3 100644 --- a/test/standalone/cat/main.zig +++ b/test/standalone/cat/main.zig @@ -13,6 +13,7 @@ pub fn main() !void { var args_it = process.args(); const exe = try unwrapArg(args_it.next(allocator).?); + defer allocator.free(exe); var catted_anything = false; const stdout_file = io.getStdOut(); @@ -20,6 +21,7 @@ pub fn main() !void { while (args_it.next(allocator)) |arg_or_err| { const arg = try unwrapArg(arg_or_err); + defer allocator.free(arg); if (mem.eql(u8, arg, "-")) { catted_anything = true; try cat_file(stdout_file, io.getStdIn()); From 4786eaedda76a3fc43510be67f9c04915b5fd703 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 27 Sep 2020 15:06:44 +1000 Subject: [PATCH 4/4] test/standalone/cat: use fifo.pump() --- test/standalone/cat/main.zig | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/test/standalone/cat/main.zig b/test/standalone/cat/main.zig index 58b87f76f3..65cd2b1e7e 100644 --- a/test/standalone/cat/main.zig +++ b/test/standalone/cat/main.zig @@ -50,23 +50,12 @@ fn usage(exe: []const u8) !void { // TODO use copy_file_range fn cat_file(stdout: fs.File, file: fs.File) !void { - var buf: [1024 * 4]u8 = undefined; + var fifo = std.fifo.LinearFifo(u8, .{ .Static = 1024 * 4 }).init(); - while (true) { - const bytes_read = file.read(buf[0..]) catch |err| { - warn("Unable to read from stream: {}\n", .{@errorName(err)}); - return err; - }; - - if (bytes_read == 0) { - break; - } - - stdout.writeAll(buf[0..bytes_read]) catch |err| { - warn("Unable to write to stdout: {}\n", .{@errorName(err)}); - return err; - }; - } + fifo.pump(file.reader(), stdout.writer()) catch |err| { + warn("Unable to read from stream or write to stdout: {}\n", .{@errorName(err)}); + return err; + }; } fn unwrapArg(arg: anyerror![]u8) ![]u8 {