diff options
author | jjanzen <jjanzen@jjanzen.ca> | 2025-01-22 12:17:02 -0600 |
---|---|---|
committer | jjanzen <jjanzen@jjanzen.ca> | 2025-01-22 12:17:02 -0600 |
commit | 8ecefa4b3fd56fc87f822f3dbefa1ce1ef6601d8 (patch) | |
tree | ababfbbdbbfe53e8ddef835af779d0d9da5da728 /src | |
parent | 275d7f14633be3a7b16e839a5864f4c2e5886b05 (diff) |
generic io interface
Diffstat (limited to 'src')
-rw-r--r-- | src/frontend/io_interface.zig | 50 | ||||
-rw-r--r-- | src/frontend/ncurses.zig | 26 | ||||
-rw-r--r-- | src/main.zig | 45 |
3 files changed, 80 insertions, 41 deletions
diff --git a/src/frontend/io_interface.zig b/src/frontend/io_interface.zig new file mode 100644 index 0000000..a2aa0ca --- /dev/null +++ b/src/frontend/io_interface.zig @@ -0,0 +1,50 @@ +const std = @import("std"); +const Action = @import("../actions.zig").Action; + +pub const IOInterface = struct { + ptr: *anyopaque, + displayMessageFn: *const fn (ptr: *anyopaque, str: []const u8) anyerror!void, + waitForTickFn: *const fn (ptr: *anyopaque) anyerror!Action, + deinitFn: *const fn (ptr: *anyopaque) void, + + pub fn init(ptr: anytype) !IOInterface { + const T = @TypeOf(ptr); + const ptr_info = @typeInfo(T); + + const gen = struct { + pub fn displayMessage(pointer: *anyopaque, str: []const u8) anyerror!void { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.Pointer.child.displayMessage(self, str); + } + + pub fn waitForTick(pointer: *anyopaque) anyerror!Action { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.Pointer.child.waitForTick(self); + } + + pub fn deinit(pointer: *anyopaque) void { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.Pointer.child.deinit(self); + } + }; + + return .{ + .ptr = ptr, + .displayMessageFn = gen.displayMessage, + .waitForTickFn = gen.waitForTick, + .deinitFn = gen.deinit, + }; + } + + pub fn displayMessage(self: IOInterface, str: []const u8) anyerror!void { + return self.displayMessageFn(self.ptr, str); + } + + pub fn waitForTick(self: IOInterface) anyerror!Action { + return self.waitForTickFn(self.ptr); + } + + pub fn deinit(self: IOInterface) void { + return self.deinitFn(self.ptr); + } +}; diff --git a/src/frontend/ncurses.zig b/src/frontend/ncurses.zig index dfbf276..fd58cf1 100644 --- a/src/frontend/ncurses.zig +++ b/src/frontend/ncurses.zig @@ -1,5 +1,5 @@ //! This module provides an implementation of IO using the ncurses library. -const io_interface = @import("io_interface.zig"); +const IOInterface = @import("io_interface.zig").IOInterface; const std = @import("std"); const Action = @import("../actions.zig").Action; const ncurses = @cImport({ @@ -120,7 +120,7 @@ pub const IO = struct { /// Display a message in the message box. /// Takes a pre-formatted null-terminated string /// If the message is too wide for the box, display "Message too long" instead. - pub fn displayMessage(self: *IO, str: []const u8) error{OutOfMemory}!void { + pub fn displayMessage(self: *IO, str: []const u8) anyerror!void { if (self.msgs == null) return; for (1..MESSAGE_PANEL_WIDTH - 1) |i| { @@ -161,7 +161,7 @@ pub const IO = struct { /// An interface for user input and time processing. /// Waits for the end of a tick and returns a tick action. /// If input is given before the end of the tick, return that instead. - pub fn waitForTick(self: *IO) !Action { + pub fn waitForTick(self: *IO) anyerror!Action { var new = std.time.milliTimestamp(); while (new - self.prev_tick_time <= TICK_MS) { @@ -236,17 +236,17 @@ pub const IO = struct { ); } - pub fn init(allocator: std.mem.Allocator) !IO { + pub fn init(allocator: std.mem.Allocator) !IOInterface { _ = locale.setlocale(locale.LC_ALL, ""); - var io = IO{ - .allocator = allocator, - .inst = null, - .msgs = null, - .stat = null, - .main = null, - .prev_tick_time = std.time.milliTimestamp(), - }; + const io_ptr = try allocator.alloc(IO, 1); + var io = &io_ptr[0]; + io.allocator = allocator; + io.inst = null; + io.msgs = null; + io.stat = null; + io.main = null; + io.prev_tick_time = std.time.milliTimestamp(); if (ncurses.initscr() == null) { return error.CursesInitFail; @@ -275,7 +275,7 @@ pub const IO = struct { try io.createPanels(); } - return io; + return IOInterface.init(io); } fn deleteWindows(self: *IO) void { diff --git a/src/main.zig b/src/main.zig index 5fe26db..f55935d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,48 +2,37 @@ const std = @import("std"); const IO = @import("frontend/ncurses.zig").IO; const Action = @import("actions.zig").Action; -pub fn main() u8 { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - const allocator = gpa.allocator(); - var io = IO.init(allocator) catch |err| { - std.log.err("{}", .{err}); - return 1; - }; - defer io.deinit(); +fn run(allocator: std.mem.Allocator) !void { + var io = try IO.init(allocator); + defer { + io.deinit(); + } - io.displayMessage("Initialized") catch { - return 1; - }; + try io.displayMessage("Initialized"); var action = Action.illegal; var tick_count: usize = 0; while (action != Action.exit) { - const str = std.fmt.allocPrint(allocator, "{}", .{tick_count}) catch { - return 1; - }; + const str = try std.fmt.allocPrint(allocator, "{}", .{tick_count}); defer allocator.free(str); - io.displayMessage(str) catch { - return 1; - }; + try io.displayMessage(str); - action = io.waitForTick() catch { - return 1; - }; + action = try io.waitForTick(); switch (action) { Action.tick => { - const str2 = std.fmt.allocPrint(allocator, "{}", .{tick_count}) catch { - return 1; - }; - defer allocator.free(str2); - io.displayMessage(str2) catch { - return 1; - }; - tick_count += 1; }, else => {}, } } +} + +pub fn main() u8 { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + run(allocator) catch { + return 1; + }; return 0; } |