From e5eca00399e68ceec72b6a8c9e73b2052799bcd8 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Wed, 3 Aug 2022 22:32:09 +0200 Subject: Implemented decimalInput io function --- src/io.zig | 75 ++++++++++++++++++++++++++++++++++++++++++++++++--------- src/main.zig | 8 ++++-- src/pointer.zig | 8 ++++-- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/io.zig b/src/io.zig index 5ec3b48..886d7e7 100644 --- a/src/io.zig +++ b/src/io.zig @@ -4,7 +4,24 @@ pub fn Context(readerType: anytype, writerType: anytype) type { return struct { reader: readerType, writer: writerType, - pub fn characterInput(self: @This()) !i64 { + lastChar: ?i64 = null, + allocator: std.mem.Allocator, + const Self = @This(); + pub fn deinit(self: *Self) void { + self.allocator.destroy(self); + } + pub fn init(allocator: std.mem.Allocator, reader: readerType, writer: writerType) !*Self { + var c = try allocator.create(Self); + c.allocator = allocator; + c.reader = reader; + c.writer = writer; + return c; + } + pub fn characterInput(self: *Self) !i64 { + if (self.lastChar) |c| { + self.lastChar = null; + return c; + } var buffer = [_]u8{0}; var n = try self.reader.read(buffer[0..]); if (n == 1) { @@ -12,26 +29,62 @@ pub fn Context(readerType: anytype, writerType: anytype) type { } return error.IOError; } - pub fn decimalInput(self: @This()) !i64 { - _ = self; - return error.NotImplemented; + test "characterInput" { + var stdin = std.io.fixedBufferStream("ab0"); + var stdout = std.ArrayList(u8).init(std.testing.allocator); + defer stdout.deinit(); + var ioContext = try context(std.testing.allocator, stdin, stdout); + defer ioContext.deinit(); + try std.testing.expectEqual(try ioContext.characterInput(), 'a'); + try std.testing.expectEqual(try ioContext.characterInput(), 'b'); + try std.testing.expectEqual(try ioContext.characterInput(), '0'); + try std.testing.expectEqual(ioContext.characterInput(), error.IOError); + } + pub fn decimalInput(self: *Self) !i64 { + var result: i64 = undefined; + while (true) { // Fist we need to find the next numeric char + const c = self.characterInput() catch return error.IOError; + if (c >= '0' and c <= '9') { + result = c - '0'; + break; + } + } + while (true) { // then we read until we encounter a non numeric char + const c = self.characterInput() catch break; + if (c >= '0' and c <= '9') { + result = result * 10 + c - '0'; + } else { + self.lastChar = c; + break; + } + } + return result; } - pub fn characterOutput(self: @This(), v: i64) !void { + test "decimalInput" { + var stdin = std.io.fixedBufferStream("1 234abc5d6ef"); + var stdout = std.ArrayList(u8).init(std.testing.allocator); + defer stdout.deinit(); + var ioContext = try context(std.testing.allocator, stdin, stdout); + defer ioContext.deinit(); + try std.testing.expectEqual(try ioContext.decimalInput(), 1); + try std.testing.expectEqual(try ioContext.decimalInput(), 234); + try std.testing.expectEqual(try ioContext.decimalInput(), 5); + try std.testing.expectEqual(try ioContext.decimalInput(), 6); + try std.testing.expectEqual(ioContext.decimalInput(), error.IOError); + } + pub fn characterOutput(self: Self, v: i64) !void { try self.writer.print("{c}", .{@intCast(u8, v)}); return; } - pub fn decimalOutput(self: @This(), v: i64) !void { + pub fn decimalOutput(self: Self, v: i64) !void { try self.writer.print("{d}", .{v}); return; } }; } -pub fn context(reader: anytype, writer: anytype) Context(@TypeOf(reader), @TypeOf(writer)) { - return .{ - .reader = reader, - .writer = writer, - }; +pub fn context(allocator: std.mem.Allocator, reader: anytype, writer: anytype) !*Context(@TypeOf(reader), @TypeOf(writer)) { + return Context(@TypeOf(reader), @TypeOf(writer)).init(allocator, reader, writer); } test "all" { diff --git a/src/main.zig b/src/main.zig index e83a2fd..b85aa6f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -18,7 +18,9 @@ pub fn main() anyerror!void { var i = try interpreter.Interpreter.init(gpa.allocator(), file.reader(), args); defer i.deinit(); - std.os.exit(@intCast(u8, try i.run(io.context(std.io.getStdIn().reader(), std.io.getStdOut().writer())))); + var ioContext = try io.context(gpa.allocator(), std.io.getStdIn().reader(), std.io.getStdOut().writer()); + defer ioContext.deinit(); + std.os.exit(@intCast(u8, try i.run(ioContext))); } test "all" { @@ -34,6 +36,8 @@ test "sanity" { const args = [_][]const u8{"sanity"}; var i = try interpreter.Interpreter.init(std.testing.allocator, file.reader(), args[0..]); defer i.deinit(); - try std.testing.expectEqual(try i.run(io.context(stdin.reader(), stdout.writer())), 0); + var ioContext = try io.context(std.testing.allocator, stdin.reader(), stdout.writer()); + defer ioContext.deinit(); + try std.testing.expectEqual(try i.run(ioContext), 0); try std.testing.expectEqual(std.mem.eql(u8, stdout.items, expected), true); } diff --git a/src/pointer.zig b/src/pointer.zig index d2d24bb..75bcd10 100644 --- a/src/pointer.zig +++ b/src/pointer.zig @@ -342,7 +342,9 @@ test "minimal" { const argv = [_][]const u8{"minimal"}; var p = try Pointer.init(std.testing.allocator, f, argv[0..]); defer p.deinit(); - try std.testing.expectEqual(p.exec(io.context(std.io.getStdIn().reader(), std.io.getStdOut().writer())), pointerReturn{}); + var ioContext = try io.context(std.testing.allocator, std.io.getStdIn().reader(), std.io.getStdOut().writer()); + defer ioContext.deinit(); + try std.testing.expectEqual(p.exec(ioContext), pointerReturn{}); } test "almost minimal" { const minimal = std.io.fixedBufferStream(" @").reader(); @@ -351,5 +353,7 @@ test "almost minimal" { const argv = [_][]const u8{"minimal"}; var p = try Pointer.init(std.testing.allocator, f, argv[0..]); defer p.deinit(); - try std.testing.expectEqual(p.exec(io.context(std.io.getStdIn().reader(), std.io.getStdOut().writer())), pointerReturn{}); + var ioContext = try io.context(std.testing.allocator, std.io.getStdIn().reader(), std.io.getStdOut().writer()); + defer ioContext.deinit(); + try std.testing.expectEqual(p.exec(ioContext), pointerReturn{}); } -- cgit v1.2.3