diff options
| author | Jimmi Holst Christensen <jimmi@ziglang.org> | 2018-11-29 22:38:39 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-29 22:38:39 +0100 |
| commit | 823969a5a47e054842056e3380b3987058ccd2dd (patch) | |
| tree | e1d512ab0d9bdab6994bf541d36cec81bc19cdae /std/io.zig | |
| parent | b29769532be198bbaeca20efae1016b23ba97e4a (diff) | |
| download | zig-823969a5a47e054842056e3380b3987058ccd2dd.tar.gz zig-823969a5a47e054842056e3380b3987058ccd2dd.zip | |
Implemented new more flexible readLineFrom (#1801)
Diffstat (limited to 'std/io.zig')
| -rw-r--r-- | std/io.zig | 76 |
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); +} |
