mirror of
https://codeberg.org/fairyglade/ly.git
synced 2026-08-09 15:19:13 +02:00
fix(LuaParser): use an arena allocator for config fields
The config parsing can error at any time. Using an arena allocator, only the string fields that were actually allocated are freed.
This commit is contained in:
parent
d3e6dd4814
commit
200d210a8e
1 changed files with 29 additions and 24 deletions
|
|
@ -122,13 +122,39 @@ pub fn LuaParser(comptime Struct: type) type {
|
|||
errors: std.ArrayList(Error),
|
||||
maybe_load_error: ?anyerror,
|
||||
allocator: std.mem.Allocator,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
|
||||
pub fn init(
|
||||
allocator: std.mem.Allocator,
|
||||
path: []const u8,
|
||||
) !Self {
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
const arena_alloc = arena.allocator();
|
||||
|
||||
var maybe_load_error: ?anyerror = null;
|
||||
errdefer |err| maybe_load_error = err;
|
||||
|
||||
const data = parseLua(arena_alloc, path) catch load_error: {
|
||||
break :load_error Struct{};
|
||||
};
|
||||
|
||||
if (global_errors.items.len != 0) {
|
||||
maybe_load_error = error.InvalidConfig;
|
||||
}
|
||||
|
||||
return .{
|
||||
.structure = data,
|
||||
.errors = global_errors,
|
||||
.maybe_load_error = maybe_load_error,
|
||||
.allocator = allocator,
|
||||
.arena = arena,
|
||||
};
|
||||
}
|
||||
|
||||
fn parseLua(
|
||||
allocator: std.mem.Allocator,
|
||||
path: []const u8,
|
||||
) !Struct {
|
||||
var lua: *Lua = try .init(allocator);
|
||||
defer lua.deinit();
|
||||
|
||||
|
|
@ -152,19 +178,10 @@ pub fn LuaParser(comptime Struct: type) type {
|
|||
},
|
||||
else => @compileError("Expected a struct."),
|
||||
}
|
||||
if (global_errors.items.len != 0) {
|
||||
maybe_load_error = error.InvalidConfig;
|
||||
}
|
||||
|
||||
// Parse custom binds and labels
|
||||
try parseCustom(lua);
|
||||
|
||||
return .{
|
||||
.structure = data,
|
||||
.errors = global_errors,
|
||||
.maybe_load_error = maybe_load_error,
|
||||
.allocator = allocator,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
pub fn setField(allocator: std.mem.Allocator, lua: *Lua, comptime field: std.builtin.Type.StructField, data: *Struct) !void {
|
||||
|
|
@ -187,7 +204,7 @@ pub fn LuaParser(comptime Struct: type) type {
|
|||
|
||||
// handle missing required fields
|
||||
if (lua.isNil(-1)) {
|
||||
return error.MissingRequiredField;
|
||||
return;
|
||||
}
|
||||
const actual_type_info = @typeInfo(actual_type);
|
||||
|
||||
|
|
@ -342,19 +359,7 @@ pub fn LuaParser(comptime Struct: type) type {
|
|||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
inline for (@typeInfo(Struct).@"struct".fields) |field| {
|
||||
const type_info = @typeInfo(field.type);
|
||||
const actual_type = if (type_info == .optional) type_info.optional.child else field.type;
|
||||
|
||||
const value = @field(self.structure, field.name);
|
||||
if (actual_type == []const u8 or actual_type == [:0]const u8) {
|
||||
if (type_info == .optional) {
|
||||
if (value) |inner| self.allocator.free(inner);
|
||||
} else {
|
||||
self.allocator.free(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.arena.deinit();
|
||||
for (0..global_errors.items.len) |i| {
|
||||
const err = global_errors.items[i];
|
||||
temporary_allocator.free(err.type_name);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue