config: make it possible not to leak

Using the GPA is a bit annoying sometimes. The other option would be to
just use page allocator to allocate the config and bypass the GPA.
This commit is contained in:
torque 2024-07-11 21:48:49 -07:00
parent de76cce706
commit 2194dd4a8c
Signed by: torque
SSH Key Fingerprint: SHA256:nCrXefBNo6EbjNSQhv0nXmEg/VuNq3sMF5b8zETw3Tk
2 changed files with 36 additions and 26 deletions

View File

@ -5,31 +5,37 @@ const lj = @import("./labjack.zig");
const Config = @This();
var global_internal: Config = undefined;
pub const global: *const Config = &global_internal;
var global_internal: std.json.Parsed(Config) = undefined;
pub const global: *const Config = &global_internal.value;
pub fn load(allocator: std.mem.Allocator, reader: anytype, err_writer: anytype) !void {
var jread = std.json.Reader(1024, @TypeOf(reader)).init(allocator, reader);
defer jread.deinit();
global_internal = try std.json.parseFromTokenSourceLeaky(
global_internal = try std.json.parseFromTokenSource(
Config,
allocator,
&jread,
.{},
);
try global_internal.validate(err_writer);
try global.validate(err_writer);
}
pub fn loadDefault(allocator: std.mem.Allocator) void {
_ = allocator;
global_internal = .{};
const arena = allocator.create(std.heap.ArenaAllocator) catch unreachable;
arena.* = std.heap.ArenaAllocator.init(allocator);
global_internal = .{
.arena = arena,
.value = .{},
};
}
pub fn destroy(allocator: std.mem.Allocator) void {
pub fn deinit() void {
// TODO: implement this probably
_ = allocator;
const allocator = global_internal.arena.child_allocator;
global_internal.arena.deinit();
allocator.destroy(global_internal.arena);
}
pub fn validate(self: Config, err_writer: anytype) !void {

View File

@ -53,37 +53,23 @@ pub fn main() !u8 {
}
Config.loadDefault(allocator);
defer Config.deinit();
return writeDefaultConfig(if (args.len == 3) args[2] else null);
} else if (std.mem.eql(u8, args[1], commands.run)) {
if (args.len > 3) {
printHelp(exename, .run);
return 1;
}
blk: {
const confpath = if (args.len == 3) args[2] else "yaes.json";
const conf_file = std.fs.cwd().openFile(confpath, .{}) catch {
log.warn("Could not load config file '{s}'. Using default config.", .{confpath});
Config.loadDefault(allocator);
break :blk;
};
defer conf_file.close();
Config.load(allocator, conf_file.reader(), std.io.getStdErr().writer()) catch |err| {
log.err("Could not parse config file '{s}': {s}.", .{ confpath, @errorName(err) });
loadConfigOrDefault(allocator, if (args.len == 3) args[2] else null) catch
return 1;
};
}
defer Config.destroy(allocator);
const ver = lj.getDriverVersion();
std.debug.print("Driver version: {d}\n", .{ver});
defer Config.deinit();
RotCtl.run(allocator) catch |err| {
log.err("rotator controller ceased unexpectedly! {s}", .{@errorName(err)});
return 1;
};
return 0;
} else if (std.mem.eql(u8, args[1], commands.help)) {
if (args.len != 3) {
printHelp(exename, .help);
@ -103,6 +89,24 @@ pub fn main() !u8 {
printHelp(exename, .main);
return 1;
}
return 0;
}
fn loadConfigOrDefault(allocator: std.mem.Allocator, path: ?[]const u8) !void {
const confpath = path orelse "yaes.json";
const conf_file = std.fs.cwd().openFile(confpath, .{}) catch {
log.warn("Could not load config file '{s}'. Using default config.", .{confpath});
Config.loadDefault(allocator);
return;
};
defer conf_file.close();
Config.load(allocator, conf_file.reader(), std.io.getStdErr().writer()) catch |err| {
log.err("Could not parse config file '{s}': {s}.", .{ confpath, @errorName(err) });
return error.InvalidConfig;
};
log.info("Loaded config from '{s}'.", .{confpath});
}
fn installUdevRules(outpath: ?[]const u8) u8 {