Merge pull request #6434 from daurnimator/fifo.pump
std: add LinearFifo(...).pump(src_reader, dest_writer)master
commit
a6470088c6
|
@ -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" {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue