authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-11-18 16:35:13+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-11-18 16:35:13+02:00
loga6470088c6629e91edad8390f3f2930f1d7c92b1
tree3dcc3a24868b474a43c8da65d030267074921bcf
parentee1d21bbef04d7f77f7b1260540ab6a3342ff750
parent4786eaedda76a3fc43510be67f9c04915b5fd703
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6434 from daurnimator/fifo.pump

std: add LinearFifo(...).pump(src_reader, dest_writer)

2 files changed, 41 insertions(+), 18 deletions(-)

lib/std/fifo.zig+28
...@@ -375,6 +375,25 @@ pub fn LinearFifo(...@@ -375,6 +375,25 @@ pub fn LinearFifo(
375 }375 }
376 return self.buf[index];376 return self.buf[index];
377 }377 }
378
379 /// Pump data from a reader into a writer
380 /// stops when reader returns 0 bytes (EOF)
381 /// Buffer size must be set before calling; a buffer length of 0 is invalid.
382 pub fn pump(self: *Self, src_reader: anytype, dest_writer: anytype) !void {
383 assert(self.buf.len > 0);
384 while (true) {
385 if (self.writableLength() > 0) {
386 const n = try src_reader.read(self.writableSlice(0));
387 if (n == 0) break; // EOF
388 self.update(n);
389 }
390 self.discard(try dest_writer.write(self.readableSlice(0)));
391 }
392 // flush remaining data
393 while (self.readableLength() > 0) {
394 self.discard(try dest_writer.write(self.readableSlice(0)));
395 }
396 }
378 };397 };
379}398}
380399
...@@ -461,6 +480,15 @@ test "LinearFifo(u8, .Dynamic)" {...@@ -461,6 +480,15 @@ test "LinearFifo(u8, .Dynamic)" {
461 testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);480 testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
462 testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);481 testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
463 }482 }
483
484 {
485 try fifo.ensureCapacity(1);
486 var in_fbs = std.io.fixedBufferStream("pump test");
487 var out_buf: [50]u8 = undefined;
488 var out_fbs = std.io.fixedBufferStream(&out_buf);
489 try fifo.pump(in_fbs.reader(), out_fbs.writer());
490 testing.expectEqualSlices(u8, in_fbs.buffer, out_fbs.getWritten());
491 }
464}492}
465493
466test "LinearFifo" {494test "LinearFifo" {
test/standalone/cat/main.zig+13-18
...@@ -3,12 +3,17 @@ const io = std.io;...@@ -3,12 +3,17 @@ const io = std.io;
3const process = std.process;3const process = std.process;
4const fs = std.fs;4const fs = std.fs;
5const mem = std.mem;5const mem = std.mem;
6const warn = std.debug.warn;6const warn = std.log.warn;
7const allocator = std.testing.allocator;7
8var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
9const allocator = &general_purpose_allocator.allocator;
810
9pub fn main() !void {11pub fn main() !void {
12 defer _ = general_purpose_allocator.deinit();
13
10 var args_it = process.args();14 var args_it = process.args();
11 const exe = try unwrapArg(args_it.next(allocator).?);15 const exe = try unwrapArg(args_it.next(allocator).?);
16 defer allocator.free(exe);
12 var catted_anything = false;17 var catted_anything = false;
13 const stdout_file = io.getStdOut();18 const stdout_file = io.getStdOut();
1419
...@@ -16,6 +21,7 @@ pub fn main() !void {...@@ -16,6 +21,7 @@ pub fn main() !void {
1621
17 while (args_it.next(allocator)) |arg_or_err| {22 while (args_it.next(allocator)) |arg_or_err| {
18 const arg = try unwrapArg(arg_or_err);23 const arg = try unwrapArg(arg_or_err);
24 defer allocator.free(arg);
19 if (mem.eql(u8, arg, "-")) {25 if (mem.eql(u8, arg, "-")) {
20 catted_anything = true;26 catted_anything = true;
21 try cat_file(stdout_file, io.getStdIn());27 try cat_file(stdout_file, io.getStdIn());
...@@ -44,23 +50,12 @@ fn usage(exe: []const u8) !void {...@@ -44,23 +50,12 @@ fn usage(exe: []const u8) !void {
4450
45// TODO use copy_file_range51// TODO use copy_file_range
46fn cat_file(stdout: fs.File, file: fs.File) !void {52fn cat_file(stdout: fs.File, file: fs.File) !void {
47 var buf: [1024 * 4]u8 = undefined;53 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 1024 * 4 }).init();
48
49 while (true) {
50 const bytes_read = file.read(buf[0..]) catch |err| {
51 warn("Unable to read from stream: {}\n", .{@errorName(err)});
52 return err;
53 };
54
55 if (bytes_read == 0) {
56 break;
57 }
5854
59 stdout.writeAll(buf[0..bytes_read]) catch |err| {55 fifo.pump(file.reader(), stdout.writer()) catch |err| {
60 warn("Unable to write to stdout: {}\n", .{@errorName(err)});56 warn("Unable to read from stream or write to stdout: {}\n", .{@errorName(err)});
61 return err;57 return err;
62 };58 };
63 }
64}59}
6560
66fn unwrapArg(arg: anyerror![]u8) ![]u8 {61fn unwrapArg(arg: anyerror![]u8) ![]u8 {