Implemented new more flexible readLineFrom (#1801)
This commit is contained in:
parent
b29769532b
commit
823969a5a4
@ -24,15 +24,15 @@ pub fn main() !void {
|
||||
try stdout.print("\nGuess a number between 1 and 100: ");
|
||||
var line_buf: [20]u8 = undefined;
|
||||
|
||||
const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {
|
||||
error.InputTooLong => {
|
||||
const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) {
|
||||
error.OutOfMemory => {
|
||||
try stdout.print("Input too long.\n");
|
||||
continue;
|
||||
},
|
||||
error.EndOfFile, error.StdInUnavailable => return err,
|
||||
else => return err,
|
||||
};
|
||||
|
||||
const guess = fmt.parseUnsigned(u8, line_buf[0..line_len], 10) catch {
|
||||
const guess = fmt.parseUnsigned(u8, line, 10) catch {
|
||||
try stdout.print("Invalid number.\n");
|
||||
continue;
|
||||
};
|
||||
|
76
std/io.zig
76
std/io.zig
@ -683,25 +683,73 @@ test "import io tests" {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readLine(buf: []u8) !usize {
|
||||
var stdin = getStdIn() catch return error.StdInUnavailable;
|
||||
var adapter = stdin.inStream();
|
||||
var stream = &adapter.stream;
|
||||
var index: usize = 0;
|
||||
pub fn readLine(buf: *std.Buffer) ![]u8 {
|
||||
var stdin = try getStdIn();
|
||||
var stdin_stream = stdin.inStream();
|
||||
return readLineFrom(&stdin_stream.stream, buf);
|
||||
}
|
||||
|
||||
/// Reads all characters until the next newline into buf, and returns
|
||||
/// a slice of the characters read (excluding the newline character(s)).
|
||||
pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
|
||||
const start = buf.len();
|
||||
while (true) {
|
||||
const byte = stream.readByte() catch return error.EndOfFile;
|
||||
const byte = try stream.readByte();
|
||||
switch (byte) {
|
||||
'\r' => {
|
||||
// trash the following \n
|
||||
_ = stream.readByte() catch return error.EndOfFile;
|
||||
return index;
|
||||
},
|
||||
'\n' => return index,
|
||||
else => {
|
||||
if (index == buf.len) return error.InputTooLong;
|
||||
buf[index] = byte;
|
||||
index += 1;
|
||||
_ = try stream.readByte();
|
||||
return buf.toSlice()[start..];
|
||||
},
|
||||
'\n' => return buf.toSlice()[start..],
|
||||
else => try buf.appendByte(byte),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test "io.readLineFrom" {
|
||||
var bytes: [128]u8 = undefined;
|
||||
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
|
||||
|
||||
var buf = try std.Buffer.initSize(allocator, 0);
|
||||
var mem_stream = SliceInStream.init(
|
||||
\\Line 1
|
||||
\\Line 22
|
||||
\\Line 333
|
||||
);
|
||||
const stream = &mem_stream.stream;
|
||||
|
||||
debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
|
||||
debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
|
||||
debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
|
||||
debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
|
||||
}
|
||||
|
||||
pub fn readLineSlice(slice: []u8) ![]u8 {
|
||||
var stdin = try getStdIn();
|
||||
var stdin_stream = stdin.inStream();
|
||||
return readLineSliceFrom(&stdin_stream.stream, slice);
|
||||
}
|
||||
|
||||
/// Reads all characters until the next newline into slice, and returns
|
||||
/// a slice of the characters read (excluding the newline character(s)).
|
||||
pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
|
||||
// We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
|
||||
// after taking ownership, which would always require an allocation.
|
||||
var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };
|
||||
try buf.resize(0);
|
||||
return try readLineFrom(stream, &buf);
|
||||
}
|
||||
|
||||
test "io.readLineSliceFrom" {
|
||||
var buf: [7]u8 = undefined;
|
||||
var mem_stream = SliceInStream.init(
|
||||
\\Line 1
|
||||
\\Line 22
|
||||
\\Line 333
|
||||
);
|
||||
const stream = &mem_stream.stream;
|
||||
|
||||
debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
|
||||
debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user