Merge pull request #6434 from daurnimator/fifo.pump

std: add LinearFifo(...).pump(src_reader, dest_writer)
master
Veikka Tuominen 2020-11-18 16:35:13 +02:00 committed by GitHub
commit a6470088c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 18 deletions

View File

@ -375,6 +375,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)));
}
}
};
}
@ -461,6 +480,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" {

View File

@ -3,12 +3,17 @@ 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).?);
defer allocator.free(exe);
var catted_anything = false;
const stdout_file = io.getStdOut();
@ -16,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());
@ -44,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 {