authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-11-29 22:38:39+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-11-29 22:38:39+01:00
log823969a5a47e054842056e3380b3987058ccd2dd
treee1d512ab0d9bdab6994bf541d36cec81bc19cdae
parentb29769532be198bbaeca20efae1016b23ba97e4a
signature Signed by PGP key 4AEE18F83AFDEB23

Implemented new more flexible readLineFrom (#1801)


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

example/guess_number/main.zig+4-4
......@@ -24,15 +24,15 @@ pub fn main() !void {
2424 try stdout.print("\nGuess a number between 1 and 100: ");
2525 var line_buf: [20]u8 = undefined;
2626
27 const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {
28 error.InputTooLong => {
27 const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) {
28 error.OutOfMemory => {
2929 try stdout.print("Input too long.\n");
3030 continue;
3131 },
32 error.EndOfFile, error.StdInUnavailable => return err,
32 else => return err,
3333 };
3434
35 const guess = fmt.parseUnsigned(u8, line_buf[0..line_len], 10) catch {
35 const guess = fmt.parseUnsigned(u8, line, 10) catch {
3636 try stdout.print("Invalid number.\n");
3737 continue;
3838 };
std/io.zig+62-14
......@@ -683,25 +683,73 @@ test "import io tests" {
683683 }
684684}
685685
686pub fn readLine(buf: []u8) !usize {
687 var stdin = getStdIn() catch return error.StdInUnavailable;
688 var adapter = stdin.inStream();
689 var stream = &adapter.stream;
690 var index: usize = 0;
686pub fn readLine(buf: *std.Buffer) ![]u8 {
687 var stdin = try getStdIn();
688 var stdin_stream = stdin.inStream();
689 return readLineFrom(&stdin_stream.stream, buf);
690}
691
692/// Reads all characters until the next newline into buf, and returns
693/// a slice of the characters read (excluding the newline character(s)).
694pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
695 const start = buf.len();
691696 while (true) {
692 const byte = stream.readByte() catch return error.EndOfFile;
697 const byte = try stream.readByte();
693698 switch (byte) {
694699 '\r' => {
695700 // trash the following \n
696 _ = stream.readByte() catch return error.EndOfFile;
697 return index;
698 },
699 '\n' => return index,
700 else => {
701 if (index == buf.len) return error.InputTooLong;
702 buf[index] = byte;
703 index += 1;
701 _ = try stream.readByte();
702 return buf.toSlice()[start..];
704703 },
704 '\n' => return buf.toSlice()[start..],
705 else => try buf.appendByte(byte),
705706 }
706707 }
707708}
709
710test "io.readLineFrom" {
711 var bytes: [128]u8 = undefined;
712 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
713
714 var buf = try std.Buffer.initSize(allocator, 0);
715 var mem_stream = SliceInStream.init(
716 \\Line 1
717 \\Line 22
718 \\Line 333
719 );
720 const stream = &mem_stream.stream;
721
722 debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
723 debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
724 debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
725 debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
726}
727
728pub fn readLineSlice(slice: []u8) ![]u8 {
729 var stdin = try getStdIn();
730 var stdin_stream = stdin.inStream();
731 return readLineSliceFrom(&stdin_stream.stream, slice);
732}
733
734/// Reads all characters until the next newline into slice, and returns
735/// a slice of the characters read (excluding the newline character(s)).
736pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
737 // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
738 // after taking ownership, which would always require an allocation.
739 var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };
740 try buf.resize(0);
741 return try readLineFrom(stream, &buf);
742}
743
744test "io.readLineSliceFrom" {
745 var buf: [7]u8 = undefined;
746 var mem_stream = SliceInStream.init(
747 \\Line 1
748 \\Line 22
749 \\Line 333
750 );
751 const stream = &mem_stream.stream;
752
753 debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
754 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
755}