aboutsummaryrefslogtreecommitdiff
path: root/std/io.zig
diff options
context:
space:
mode:
authorJimmi Holst Christensen <jimmi@ziglang.org>2018-11-29 22:38:39 +0100
committerGitHub <noreply@github.com>2018-11-29 22:38:39 +0100
commit823969a5a47e054842056e3380b3987058ccd2dd (patch)
treee1d512ab0d9bdab6994bf541d36cec81bc19cdae /std/io.zig
parentb29769532be198bbaeca20efae1016b23ba97e4a (diff)
downloadzig-823969a5a47e054842056e3380b3987058ccd2dd.tar.gz
zig-823969a5a47e054842056e3380b3987058ccd2dd.zip
Implemented new more flexible readLineFrom (#1801)
Diffstat (limited to 'std/io.zig')
-rw-r--r--std/io.zig76
1 files changed, 62 insertions, 14 deletions
diff --git a/std/io.zig b/std/io.zig
index 6473d993c4..f4122a2f8b 100644
--- a/std/io.zig
+++ b/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);
+}